## File: README.md

# Sandstorm

Sandstorm is a self-hostable web productivity suite. It's implemented as a security-hardened web app package manager. Sandstorm makes it easy to run your own server.

Use Sandstorm to install apps to create [documents](https://apps.sandstorm.io/app/h37dm17aa89yrd8zuqpdn36p6zntumtv08fjpu8a8zrte7q1cn60),
[spreadsheets](https://apps.sandstorm.io/app/a0n6hwm32zjsrzes8gnjg734dh6jwt7x83xdgytspe761pe2asw0), [blogs](https://apps.sandstorm.io/app/aax9j672p6z8n7nyupzvj2nmumeqd4upa0f7mgu8gprwmy53x04h),
[git repos](https://apps.sandstorm.io/app/zx9d3pt0fjh4uqrprjftgpqfwgzp6y2ena6098ug3ctv37uv6kfh), [task lists](https://apps.sandstorm.io/app/m86q05rdvj14yvn78ghaxynqz7u2svw6rnttptxx49g1785cdv1h), and
[more](https://apps.sandstorm.io/) as easily as you'd install apps on your
phone.

Sandstorm is open source and can be installed on any x86-64 Linux
system.

* Read more at: https://sandstorm.io/
* Try the demo: https://demo.sandstorm.io/
* Documentation available at: https://docs.sandstorm.io/

## Installing

See [installation instructions in the Sandstorm documentation](https://docs.sandstorm.io/en/latest/install/).

## Using Sandstorm

See [the overview in the Sandstorm documentation](https://docs.sandstorm.io/en/latest/using/).

## How It Works

See [how it works](https://sandstorm.io/how-it-works) and [security practices](https://docs.sandstorm.io/en/latest/using/security-practices/) in the Sandstorm documentation.

## How to Package Apps

See [the developer hub in the Sandstorm documentation](https://docs.sandstorm.io/en/latest/developing/).

## Contribute

Want to help? Check out [CONTRIBUTING.md](https://github.com/sandstorm-io/sandstorm/blob/master/CONTRIBUTING.md). Also see our [community page](https://sandstorm.io/community) or get on our [discussion group](https://groups.io/g/sandstorm-dev-group) and let us know!

---

## File: acme-dns-01-sandcats/README.md

# ACME.js plugin for Sandcats.io

This allows you to issue Let's Encrypt certificates against your Sandcats.io subdomain.

This code is intended to be used inside the Sandstorm server.

---

## File: docs/administering/active-directory.md

This document explains how to integrate with Microsoft Active Directory (also known as AD).  This
allows all users, or specific users within your Windows domain, to log into a Sandstorm server.

## AD & Sandstorm: Overview

Sandstorm can rely on AD to authenticate users.

Active Directory exists as part of a cloud product called Windows Azure as well as a software
product called Windows Server. Sandstorm supports both products.

Sandstorm can be configured to use single sign-on in a configuration where AD has full control over
the login form, allowing you to enjoy AD's support for multi-factor authentication, Windows
credentials login, and a consistent sign-in experience for all apps within your organization. As a
security benefit, the Sandstorm software never sees the user's passwords. This relies on Sandstorm's
support for SAML 2.0.

This document provides textual advice as well as a great deal of screenshots to allow you to proceed
with confidence. If you have questions, please [open an issue on GitHub](https://github.com/sandstorm-io/sandstorm/issues/new). We want to help you
successfully set up Sandstorm!

Note that you can also set up Sandstorm to integrate with Active Directory using LDAP bind to
authenticate users. We recommend Active Directory Federation Services or Microsoft Azure AD Single
Sign-On instead. Both of these products use SAML for authentication. If you must use LDAP bind for
authentication instead, see the general [documentation about
LDAP](for-work.md#authentication-provider-ldap).

## Windows Azure Active Directory

**Summary:** Once you have created a directory, you must add a new **application from the gallery,**
configure Sandstorm as a **custom app,** then enable **Microsoft Azure AD Single Sign-On.** This
process will involve Azure AD creating a SAML provider entry point URL and a custom SAML
certificate. Once you have done this, you can use Active Directory to choose which users in your
domain are allowed to use Sandstorm.

Here is a screenshot tour, using example.sandcats.io as an example Sandstorm server.

These instructions use the Classic Azure Active Directory portal found at
[manage.windowsazure.com.](https://manage.windowsazure.com) If you are using the new portal at
portal.azure.com, please click on "classic portal" or browse to manage.windowsazure.com in order to
follow these instructions.

- Go to: manage.windowsazure.com



- Click "Active Directory" in the sidebar.



- Choose the directory you wish to use to sign into Sandstorm.



- Click "Applications" in the top bar.



- Choose "Add" from the bottom bar (NOT "+ New").



- Choose "Add an application from the gallery"



- Choose "custom" from the sidebar. Choose "Add an unlisted application my organization is using".

    - If this option is not displayed: Make sure you are using the classic portal. At the time of
      writing, Microsoft is still working on adding this option to the new portal. This option may
      require upgrading to Azure AD Premium.



- Enter name: "Sandstorm". Click the checkmark in the lower-right.



- Choose "Configure single sign-on"



- Choose "Microsoft Azure AD Single Sign-On". Click the "next" arrow.



- Now, visit your Sandstorm server and begin configuring SAML login. In the Sandstorm SAML config, adjust the "Entity ID" to be the full URL to your Sandstorm server, including the leading "https://", which you will also use as the Azure AD "Identifier". Azure AD requires that the entity ID be a full URL, not a hostname. You will also need to copy the Sandstorm server's Service URL to your clipboard.



- Return to the Microsoft Azure AD page in your web browser. For "Identifier", enter the Sandstorm server's URL. (Example: "https://example.sandcats.io") For "Reply URL", enter the Sandstorm server's Service URL from the Sandstorm SAML config. (Example: "https://example.sandcats.io/_saml/validate/default"). Click the "next" arrow.



- Click "Download Certificate (Base 64 - most common)".



- Open the certificate file in a text editor (such as Notepad).



- Copy/paste the contents of the file into Sandstorm's SAML login configuration under "SAML cert for above provider:".



- Back in the Azure AD configuration, copy the line titled "Single Sign-On Service URL". In the Sandstorm config, paste this under "SAML provider entry point URL:".





- In the Azure AD config, check the box: "Confirm that you have configured single sign-on as
  described above." Click the "next" arrow.



- Enter your email address for service alerts from Microsoft. Click
  the checkbox to complete configuration.



- Click "Assign accounts".



- Click: "Users and Groups", then "All Users". Click the check-mark to request Sandstorm access for
  all users.



- The system will ask you if you are sure. Click "Yes" to confirm.



**Congratulations!** You have enabled Sandstorm for all the users in your Microsoft Azure Active Directory service.

## Windows Server Active Directory

**Summary:** Once you have created a directory, you must use Active Directory Federation Services to
add a new Relying Party, namely the Sandstorm web application. Each Sandstorm server publishes
federation metadata information at a URL available within the SAML configuration page.  You must
configure a rule that sends the user email address to Sandstorm, as well as a rule that declares
email addresses are the persistent identifier. You must also export the custom SAML certificate to
Sandstorm.  Once you have done this, you can use Active Directory to choose which users in your
domain are allowed to use Sandstorm.

To connect to Active Directory via SAML, you must enable Active Directory Federation Services (AD
FS). We will assume you have already done this. We also assume that your users' web browsers can
reach the the Sandstorm server as well as the AD server. With SAML, all communication between the
Service Provider (Sandstorm) and the Identity Provider (AD) is through the browser. The only
server-to-server communication happens during setup, where AD FS fetches a configuration XML file
from Sandstorm. If desired, the admin can avoid this server-to-server communication be by
downloading the XML from Sandstorm and then uploading it to AD separately.

Note that AD FS requires that your Sandstorm server supports HTTPS with a valid certificate. You can
use a private CA for this, but setting up a private CA is beyond the scope of this document.

Here is a screenshot tour, using example.sandcats.io as an example Sandstorm server.

### Part 1: Configure AD FS

- Open the AD FS management UI.



- In the left sidebar, browse to: "Trust Relationships > Relying Party Trusts". In the right sidebar, click: "Add Relying Party Trust...".



- You will see the "Add Relying Party Trust Wizard." Click "Start."



- At this time, open the Sandstorm SAML configuration interface in a new browser tab. Take note of
  the Sandstorm service provider metadata URL. This is typically of the form:
  https://example.sandcats.io/_saml/config/default



- Back in the "Add Relying Party Trust Wizard," choose the radio button for: "Import data about the
  relying party published online or on a local network".  Under "Federation metadata address (host
  name or URL)", enter the address of Sandstorm server's service URL. This is typically of the form:
  https://example.sandcats.io/_saml/config/default . Then, click Next.

    - If your Sandstorm server does not support HTTPS, AD FS will complain at this point. Do NOT try to work around this by downloading the metadata and feeding it to AD FS manually. If you do that, AD FS may appear to accept the metadata, but it will leave all the endpoints unconfigured, because AD FS will not accept a non-HTTPS endpoint.



- Choose a display name (for example, the server's hostname like example.sandcats.io) and notes if
  desired, then click "Next".



- Choose whether to configure multi-factor authentication and click "Next". (Configuring
  multi-factor is beyond the scope of this document.)



- Choose "Permit all users to access this relying party" and click "Next".



- Review your choices and click "Next".



- Check the box for: "Open the Edit Claim Rules dialog for this relying party trust when the wizard closes".
  Then, click Close.



- The "Edit Claim Rules" dialog appears. Click "Add Rule..."



- Under "Claim rule template", choose: "Send LDAP Attributes as Claims". Then click "Next."



- Under "Claim rule name", enter: "Send e-mail address" (or any name you want). Use "Active
  Directory" as the attribute store. Configure the LDAP Attribute as E-Mail Addresses and the
  Outgoing Claim Type as E-Mail Address. Then click "Finish."



- Click "Add Rule...".



- Under "Claim rule template", choose: "Transform an Incoming Claim". Click "Next."



- Under "Claim rule name", enter: "Assign name ID from e-mail address" (or any name you want). Configure the
  Incoming claim type as "E-Mail Address" and set the Outgoing claim type to "Name ID." Set the Outgoing
  format to "Persistent Identifier." Choose to "Pass through all claim values." Finally, click "Finish."

    - NOTE: This differs from many other services. Do NOT choose "Email" here. You MUST choose
      "Persistent Identifier". This is because Sandstorm allows an advanced administrator to choose
      a different user attribute to use as the primary identifier. For example, if your system has a
      notion of numeric user IDs that never change, you could use that as the Name ID instead. This
      way, you could change a user's e-mail address in the future without requiring that they
      transfer all of their Sandstorm data to a new account. However, most administrators choose to
      use e-mail addresses as the primary identifier, accepting that this means that e-mail
      addresses can never change.



- Click "OK" to finish editing claim rules.





### Part 2: Extract your certificate

- Open the AD FS management UI. In the left sidebar, browse to: "Service > Certificates".



- Click on the certificate under "Token-signing" to select it.



- Click "View Certificate..." In the Certificate dialog, go to the "Details" tab.



- In the "Details" tab, click "Copy to File..."



- The Certificate Export Wizard appears. Click "Next".



- Choose the radio button for: "Base-64 encoded X.509 (.CER)". Click "Next."



- Choose where to save the certificate. Click "Next."



- Review the "Completing the Certificate Export Wizard" information, then click "Finish."



- Open the certificate file using a text editor, such as Notepad. You will need to copy/paste this next in the next part.



### Part 3: Configure Sandstorm

- Open Sandstorm's SAML login configuration.

    - Under "SAML provider entry point URL", enter your AD FS login entry point. This is usually
      "/adfs/ls" at the host associated with your Active Directory server. For example, if your Active
      Directory server is ad.example.com, the URL would be: https://ad.example.com/adfs/ls

    - Under "SAML cert for above provider", copy the contents of the certificate you extracted in part
      2, above.

    - For the entity ID, keep the Sandstorm default, which is your server hostname. For example,
      example.sandcats.io. If you change this value, logins will not work until you resynchronize AD
      FS with Sandstorm's SAML metadata.

    - Finally, click "Save."



This concludes setting up Windows Server Active Directory with Sandstorm! If you have any questions
or need further help, please email support@sandstorm.io! We'd be honored to work with you to get
your server set up properly.

---

## File: docs/administering/backups.md

# Backups

You can manually perform backups of Sandstorm data via the web interface and/or via the command line.
In the long run, we'd like to enable automated backups as well.

## To back up one individual grain

If you're the owner of a grain on Sandstorm, you can back up an individual grain by clicking the
download icon in the [top bar](../using/top-bar.md). This will give you a ZIP file of the grain's
contents. This contains the full writable state of the app, so you can restore it to any Sandstorm
server.

If you want to get crafty, you can modify a backup to point to a different app ID, allowing you to
migrate data between apps, or use your data with an experimental app with a different app ID. To
do this:
- Make a backup of your data from the "old" app.
- With the "new" app, create a new empty grain and make a backup of it.
- Find the file called "metadata" inside the second backup, and copy it over to the first backup,
  overwriting its own "metadata". Now you have a zip which Sandstorm will recognize as belonging
  to the new app, even though the data came from the old app.

You can also change the contents of the backup before restoring it, by modifying the files in the
zip.

In this way, Sandstorm gives every app a fully-functional import/export system.

## To back up the entire Sandstorm server

Sandstorm stores all its data in `/opt/sandstorm`, plus two symbolic links in `/usr/local/bin`, plus
a service file for systemd or sysvinit.

If you run your own Sandstorm server, you can back up the entire Sandstorm installation safely by
stopping the service:

    sudo sandstorm stop
    sudo service sandstorm stop

and taking a filesystem snapshot of `/opt/sandstorm`. If your filesystem doesn't support online
snapshots you can make a quick backup by running:

    cp -a /opt/sandstorm $HOME/sandstorm-snapshot-from-$(date -I)

Alternatively, one can make a backup using tar.

    tar -cf $HOME/sandstorm-snapshot-from-$(date -I).tar /opt/sandstorm

Then restart Sandstorm to end the interruption:

    sudo service sandstorm start

This guide uses `$(date -I)`, which is a way to embed the current date into a filename, in a format
such as `2005-10-30`.

**Note about warnings from tar:** If you see errors involving socket files being ignored, you can
ignore those warnings. The `tar` utility might print messages like this:

```
/opt/sandstorm/var/sandstorm/grains/bdMmGkov6gpiSSXC9GHysy/socket: socket ignored
```

You should rely on tar's **exit code** being 0 to know if the tar command completed successfully.

### To restore a Sandstorm server backup

If you have a tar-based backup of `/opt/sandstorm`, the easiest way to restore it is to:

- Run the install script, and allow it to configure a systemd/sysvinit service.

- Stop the Sandstorm service, e.g. `sudo sandstorm stop`

- Move the `/opt/sandstorm` directory to `/opt/sandstorm.empty`

- Copy your backup into `/opt/sandstorm`

- Start the Sandstorm service, e.g. `sudo service sandstorm start`

- Visit your Sandstorm server and make sure everything still works.

- Remove the now-useless `/opt/sandstorm.empty` directory.

You can also use the [Docker container
documentation](../install.md#option-6-using-sandstorm-within-docker) to run your snapshot of
`/opt/sandstorm`. You will need to create a Docker volume with your backup of `/opt/sandstorm`, and
it will continue to execute until you stop the Docker container.

---

## File: docs/administering/config-file.md

This document provides **detailed technical documentation**, also known as reference documentation,
on the available options within Sandstorm's configuration file, `sandstorm.conf`.

## Overview

At Sandstorm startup,
[run-bundle.c++](https://github.com/sandstorm-io/sandstorm/blob/master/src/sandstorm/run-bundle.c%2B%2B)
parses the configuration file, using the information to adjust Sandstorm startup details. Typically
this takes the form of passing the config options to the Sandstorm shell as Meteor settings, but it
includes choosing what user ID to switch to, what environment variables to set, and other startup
details.

Most Sandstorm installations use `/opt/sandstorm` as the main directory. In that case, you can find
sandstorm.conf in `/opt/sandstorm/sandstorm.conf`.

## List of all sandstorm.conf settings and their effects

### SERVER_USER

If Sandstorm is started as root, Sandstorm will switch to the user ID named by this configuration parameter.
On a default install, this is `sandstorm`. Example:

```bash
SERVER_USER=sandstorm
```

### PORT

A comma-separated list of port numbers on which Sandstorm will bind, listening for inbound HTTP.
By default, 80 if that port was available; otherwise, 6080.

If Sandstorm is started as root, Sandstorm binds to this port as root, allowing it to use
low-numbered ports. The socket is passed-through to code that does not run as root.

Example:

```bash
PORT=80,6080
```

Sandstorm treats the first PORT value differently from the other ones, which we call alternate ports.

**First port.** When a request reaches Sandstorm via first PORT, if the request is for a URL within
the WILDCARD_HOST pattern, then serve a response. If the request is for a URL that is **not** within
the WILDCARD_HOST pattern, typically a static publishing website, then also serve a response.

**Alternate ports.** When a request arrives and it is for a URL within the WILDCARD_HOST pattern,
Sandstorm serves a HTTP redirect to a canonicalized version of the requested URL, with the intent
of serving the request using the primary port. If the request is outside the WILDCARD_HOST pattern,
typically a static publishing website, then serve a normal response.

### HTTPS_PORT

A port number for Sandstorm to bind on and listen for HTTPS. On a default install, if port 443
was available and the user chose to use Sandcats, this is 443. However, this may be set for any
Sandstorm-managed TLS configuration, including automated renewals of certificates with Let's Encrypt
with a supported DNS provider or a manually-uploaded certificate. If this config option is missing,
Sandstorm's built-in HTTPS server is disabled.

If Sandstorm is started as root, Sandstorm binds to this port as root, allowing it to use
low-numbered ports. The socket is passed-through to code that does not run as root.

Example:

```bash
HTTPS_PORT=443
```

A HTTPS_PORT is automatically treated as the first port, in the context of "first port" vs.
"alternate ports."

### SMTP_LISTEN_PORT

A port number on which Sandstorm will bind, listening for inbound email. By default, 30025; if
missing, the Sandstorm shell uses 30025. You can choose port 25 if you like.

If Sandstorm is started as root, Sandstorm binds to this port as root, allowing it to use
low-numbered ports. The socket is passed-through to code that does not run as root.

Example:

```bash
SMTP_LISTEN_PORT=25
```

### BIND_IP

The IP address on which Sandstorm will listen for HTTP (via PORT), HTTPS (via HTTPS_PORT), and SMTP
(via SMTP_LISTEN_PORT). Supports IPv4 or IPv6 addresses. Example:

```bash
BIND_IP=0.0.0.0
```

### MONGO_PORT

A port number that Sandstorm will bind to for its built-in MongoDB service. By default,
6081.

Example:

```
MONGO_PORT=6081
```

### BASE_URL

The URL you expect people to type into their browser address bar to reach your sandstorm server, like `https://alpha.sandstorm.io` or `http://local.sandstorm.io:6080`. It should include protocol (http:// or https://), host, and port (if non-default), but no path. Note that if you have a reverse proxy in front of your web site, BASE_URL points at the proxy, not directly at the Sandstorm server -- again, it's the URL people type into the address bar, not necessarily the physical address of the Sandstorm server itself.

Example:

```
BASE_URL=http://sandstorm.example.com:6080
```

### WILDCARD_HOST

This specifies a pattern of addresses all of which also end up at your Sandstorm server. Unlike BASE_URL, WILDCARD_HOST should not include a protocol, only hostname and optionally port. The hostname must have a * somewhere in it. If this * is replaced by any alphanumeric string, and the value is prefixed with the same protocol used in BASE_URL, the result should be a URL which, if entered in the browser, would resolve to your Sandstorm server. So, for example, `alpha-*.sandstorm.io` is the WILDCARD_HOST for Sandstorm Alpha, while `*.oasis.sandstorm.io` is the WILDCARD_HOST for Oasis, and `*.local.sandstorm.io:6080` might be the WILDCARD_HOST for a local server. Notice that you can put the * anywhere you want in the URL, but most DNS servers only support a leading *. in a wildcard entry.

Example:

```
WILDCARD_HOST=*.sandstorm.example.com:6080
```

### UPDATE_CHANNEL

The path within `install.sandstorm.io` that Sandstorm automatically checks for downloads. The term
is borrowed from [Google Chrome](https://www.chromium.org/getting-involved/dev-channel). By default,
`dev`. Set it to `none` to disable updates. Note that at the time of writing, there is only one
channel, `dev`.

Example:

```
UPDATE_CHANNEL=dev
```

### SANDCATS_BASE_DOMAIN

A hostname that is used as the API host for the built-in
[sandcats dynamic DNS and free HTTPS certificates](sandcats.md) service. By default, `sandcats.io`
if the user chooses to use sandcats; otherwise, missing. The presence/absence of this setting
controls if Sandstorm will connect to the sandcats service. By setting it to a different hostname,
you can use a different implementation of the sandcats protocol.

Example:

```
SANDCATS_BASE_DOMAIN=sandcats.io
```

### ALLOW_DEMO_ACCOUNTS

A boolean (true/false or yes/no) that controls if this Sandstorm server has [demo mode](demo.md) enabled.
By default, absent (which is the same as false).

Example:

```
ALLOW_DEMO_ACCOUNTS=false
```

### ALLOW_DEV_ACCOUNTS

A boolean (true/false or yes/no) that controls if this Sandstorm server allows any visitor to sign in and have
admin privileges or a user account. This feature is quite dangerous; it is enabled by default for
dev accounts (including within vagrant-spk). By default, false.

Example:

```
ALLOW_DEV_ACCOUNTS=false
```

### USE_EXPERIMENTAL_SECCOMP_FILTER

A boolean (true/false or yes/no) that controls whether to use
Sandstorm's experimental new seccomp filter (as opposed to the old one).
The new filter is stricter, and is disabled by default. Once it is
deemed sufficiently mature the new filter will become the default.

### LOG_SECCOMP_VIOLATIONS

A boolean (true/false or yes/no) that controls whether violations of the
seccomp filter should be logged to the kernel's message log, when using
the new experimental seccomp filter. Defaults to false.

### ALLOW_LEGACY_RELAXED_CSP

A boolean (true/false or yes/no) that controls whether to allow apps to
load client-side scripts from third-party servers. Several apps are not
yet compatible with the new Content Security Policy, so the legacy one is
currently enabled by default. Once app support is deemed sufficiently
adequate, the new CSP will become the default.

### IS_TESTING

**Used rarely.** A boolean (true/false or yes/no) that adjusts internal settings for Sandstorm's
integration test suite.

### DDP_DEFAULT_CONNECTION_URL

**Used rarely.** Alternate URL for Meteor DDP. Useful in the unusual case that you use a CDN for
your BASE_URL.

### HIDE_TROUBLESHOOTING

**Deprecated.** A boolean (true/false or yes/no) that hides the "Troubleshooting" link on
the login areas within Sandstorm. Works at present, but may be removed in the future. Use the
Personalization section of the admin panel to configure this and other related options.

### WILDCARD_PARENT_URL

**Deprecated.** Historic alternative to WILDCARD_HOST.

### MAIL_URL

**Deprecated.** URL for outbound SMTP. Configure SMTP using the admin area within Sandstorm
instead.

---

## File: docs/administering/demo.md

# Demo mode

This page documents some features of the Sandstorm demo mode, which is the mode in which [demo.sandstorm.io](https://demo.sandstorm.io) runs. The code for demo mode is in the main Sandstorm repository but usually is not enabled.

## Purpose of demo mode

The main purpose of the demo mode is to let people learn more about the Sandstorm platform by using a Sandstorm instance without having to think about registering for an account.

A secondary purpose, the code for which is not yet fully implemented, is to enable people to try out Sandstorm _apps_ without having to think about registering for an account or "installing" the app.

## Data deletion

A demo user and their data is deleted one hour after the user is created. To learn about how, read the [code implementing the demo](https://github.com/sandstorm-io/sandstorm/blob/master/shell/shared/demo.js).

At the time of writing, the period of data deletion is not configurable.

## Enabling demo mode

Demo mode is mainly intended to run on [demo.sandstorm.io](https://demo.sandstorm.io), since the purpose is to show you what Sandstorm looks like before you've installed it. That said, you can enable it on your own installation.

To enable demo mode, add the following line to `sandstorm.conf`:

```
ALLOW_DEMO_ACCOUNTS=true
```

## App demos

When a Sandstorm instance allows demo accounts, a visitor can surf to:

`/appdemo/:appId`

(where `appId` is the key ID of an app installed on that server).

At that URL, we show a screen to the visitor indicating that their data will vanish in a hour. When they click on the "Try appName" button, they find themselves in a working instance of the app.

This hinges on the app named by `appId` being installed on the server.

Your app's ID can be found near the top of the package definition file (`sandstorm-pkgdef.capnp`), where it will be defined something like this:

    const pkgdef :Spk.PackageDefinition = (
      id = "nqmcqs9spcdpmqyuxemf0tsgwn8awfvswc58wgk375g4u25xv6yh",

To find the ID of an already-built `.spk` package, run `spk unpack` on it; it will print the ID to the console. For apps on the [Sandstorm app list](https://sandstorm.io/apps/), you can also look at the `data-app-id` attribute on the "install" button.

---

## File: docs/administering/email.md

# Email in Sandstorm

This tutorial will show you how to setup your personal sandstorm instance with support for e-mail.

First, a quick rundown of how email works in sandstorm. Sandstorm is
running an SMTP server on port 30025 that will accept email of the
form `publicId`@`hostname`. `publicId` is randomly generated for every
grain that handles e-mail, and `hostname` is extracted from the
`BASE_URL` parameter in sandstorm.conf (which is initially created by
the installer script). Outgoing e-mail is sent through an external
SMTP server, controllable from the Admin settings -> Email configuration page.
(Note that the `MAIL_URL` parameter in `sandstorm.conf` has been
deprecated.) When sending e-mails, the only valid "From" addresses are
the grain's generated `publicId`@`hostname` address, or the verified
email from the user's account (e.g. the e-mail address obtained via
e.g. Google or Github or email login). The interfaces for sending/receiving e-mails
are available in
[hack-session.capnp](https://github.com/sandstorm-io/sandstorm/blob/master/src/sandstorm/hack-session.capnp).

## Outgoing SMTP

Apps can send email out to the world, subject to rate limiting. To enable this feature, you must
configure an SMTP relay in the `Email configuration` page of the Admin panel.  The SMTP server needs
to accept e-mails with the SMTP envelope's bounce address set to either your grain's local address
or the "Sandstorm server's own email address" address.

If running at home or at work, you can usually use your ISP's or corporation's SMTP
server. Otherwise, [Sendgrid](https://sendgrid.com/), [Mailgun](http://www.mailgun.com/), and others
provide SMTP services, some with free tiers. Note in our testing, Google Gmail is incompatible with
the Sandstorm outbound SMTP requirements: it will modify the From header and SMTP envelope to be
your personal address, rather than what the app specified. Therefore it may seem to work for the
first user, but when you add other users to your server, any emails sent by their apps will appear
to come from you!

Some cloud providers block outbound port 25, which you may experience as Sandstorm reporting
"Connection timed out." In that case, check if your outbound SMTP provider supports alternative
ports such as 587 or 2525.

**sandcats.io users:** Since [the sandcats dynamic DNS & HTTPS service](sandcats.md) does not
support special DNS records that improve email deliverability, we recommend you configure a
**Server's own email address** on a domain you personally control, not your sandcats subdomain.
Then, be sure to use an SMTP provider to configure that domain and your DNS provider to configure
SPF/DKIM records.

## Receiving email into Sandstorm grains

To allow Sandstorm grains to receive email, you need to do the following.

- **Set up DNS for a domain:** Configure DNS so that other computers know how to deliver email to your server.

- **Configure port 25 on your server:** When email messages arrive on inbound port 25, they must
  reach Sandstorm. Sandstorm will then route them to any specific grain.

### Aside: How to test your configuration

One great way to test inbound email is to use the Roundcube app. To do that:

- Install [Roundcube](https://apps.sandstorm.io/app/0qhha1v9ne1p42s5jw7r6qq6rt5tcx80zpg1f5ptsg7ryr4hws1h)
  from the Sandstorm app market into an account on your Sandstorm server.

- Click **Create a mailbox** from Roundcube's app details page on your server.

- Click **Connect to Your Address** within a Roundcube grain. You should now see an inbound email
  address for this Roundcube grain of the form.

Once you know Roundcube's inbound email address, use a separate email system such as Gmail to send
it an email! If this test email appears within Roundcube, you can skip the rest of these steps!
Inbound emails should appear within 5 seconds of when you send them; if they do not, click
Roundcube's **Refresh** button to make sure.

### Set up DNS

Grains can receive inbound email, and their email adddresses are always of the form
`{{publicId}}@{{BASE_DOMAIN}}`. `{{BASE_DOMAIN}}` is the domain name value component of `BASE_URL`
in your `sandstorm.conf`. `{{publicId}}` is a random unique ID that is assigned to this grain by
Sandstorm. Therefore, the domain in your `BASE_URL` needs to have a DNS configuration that enables
inbound email.

**sandcats.io users:** No action is required. Servers on the Internet that send you email will
connect to the IP address of the DNS `A` record maintained by the sandcats.io service.

**Sandstorm users on your own domain:** No action is usually required, since presumably your
server's BASE_URL resolves properly to your Sandstorm server. For extra standards compliance, you
can add an `MX` record for the domain name that you use in your `BASE_URL`. You can use any number
as the MX priority, for example, `10`.

### Configure port 25, the easy way: Sandstorm can listen on port 25

By default, Sandstorm's SMTP server runs on port 30025. You can adjust it to listen on port 25.
This is the easiest way to configure inbound email; however, note that Sandstorm's SMTP server does
not support inbound STARTTLS at this time.

Make sure nothing else is running on port 25 on this system. Then edit
`/opt/sandstorm/sandstorm.conf` to add this new line:

```bash
SMTP_LISTEN_PORT=25
```

Now stop & start Sandstorm.

At this point, you should be able to test inbound email to your Roundcube grain.

### Configure port 25, the advanced way: Proxy SMTP

If you need to share Sandstorm's SMTP service with port 25 used by other services, or you want
inbound STARTTLS, you can configure Sandstorm's SMTP service to sit behind a reverse proxy. One way
to do accomplish this is with nginx. Add the following to your `nginx.conf`:

    mail {
        ssl_certificate /etc/keys/my-ssl.crt;
        ssl_certificate_key /etc/keys/my-ssl.key;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
        ssl_prefer_server_ciphers on;

        server {
            listen 25;
            server_name sandstorm.example.com;
            auth_http localhost:8008/fake-smtp-auth;
            protocol smtp;
            timeout 30s;
            proxy on;
            xclient off;
            smtp_auth none;
            starttls on;
        }

        server {
            listen 465;
            server_name sandstorm.example.com;
            auth_http localhost:8008/fake-smtp-auth;
            protocol smtp;
            timeout 30s;
            proxy on;
            xclient off;
            smtp_auth none;
            ssl on;
        }
    }

nginx requires that you provide an authentication handler for all SMTP proxies. We don't actually
need authentication because our server is only meant to receive e-mail destined for this host (it
will not relay). So, we have to set up a fake authentication handler. In the part of your nginx
config where you defined your HTTP servers (e.g. `/etc/nginx/sites-available/default`), add this
fake server for SMTP auth purposes:

    # Fake SMTP authorizor which always accepts. Put this in your http block.
    server {
        listen 127.0.0.1:8008;
        server_name localhost;

        location /fake-smtp-auth {
            add_header Auth-Server 127.0.0.1;
            add_header Auth-Port 30025;
            return 200;
        }
    }

---

## File: docs/administering/faq.md

One way to use Sandstorm is to run the software on your own server -- we call that
_self-hosting_. This page answers common questions from self-hosters.

## How do I log in, if there's a problem with logging in via the web?

If logging into your Sandstorm server over the web isn't working, you can reset your Sandstorm's
login providers. Resetting login providers will retain all existing accounts, including account
metadata such as who is an admin.

These instructions assume you've installed Sandstorm as root, which is the default
recommendation. If not, remove the `sudo` from the instructions below.

* Use e.g. `ssh` to log into the server running Sandstorm.

* Run this command to generate a token you can use to log in as an admin, for emergency administration.

        sudo sandstorm admin-token

  This will print a message such as:

      Generated new admin token.

      Please proceed to http://sandstorm.example.com/admin/19bc20df04838fdc03101d898be075cc02de66f2
      in order to access the admin settings page and configure your login system. This token will
      expire in 15 min, and if you take too long, you will have to regenerate a new token with
      `sandstorm admin-token`.

* Visit the link it printed out, which gives you emergency access to the server's admin panel.

* From there, configure the login providers of your choosing.

* Now, log in as yourself. If you log in as the first user that ever signed into this Sandstorm instance, then you will be an admin.

## Why does Sandstorm require a wildcard host?

See [Why Sandstorm needs a wildcard host](wildcard.md).

## How do I change the domain name for my Sandstorm server?

If your Sandstorm server is currently online, and you want to change the domain name used to reach
it, you'll need to adjust `/opt/sandstorm/sandstorm.conf` and restart Sandstorm.

**Before you change the domain name,** read the following notes to avoid common problems.

- If you're using sandcats free HTTPS, you'll need to disable Sandstorm's built-in HTTPS when you
  switch to a new domain name. Sandstorm's built-in HTTPS only supports sandcats domains at the
  moment. We recommend disabling HTTPS and getting Sandstorm working on your domain with just HTTP
  first, to avoid confusion, and then adding HTTPS in a second step. When you're ready, you can
  configure [nginx or other reverse proxy tools to get HTTPS on your own domain name.](ssl.md)

- Your new Sandstorm domain will need to support [wildcard DNS.](wildcard.md) You should set up your
  wildcard DNS record before you change Sandstorm's hostname.

- Changing the server hostname will temporarily disable Google and GitHub login, since those login
  providers embed an assumption about your server's hostname. You will be able to re-enable the
  login providers after you switch to the new Sandstorm server hostname; you can use command line
  access to gain temporary admin access to the server while the login providers are disabled.

**To change the domain name, edit /opt/sandstorm/sandstorm.conf.** To do that, use `ssh` or a similar tool
to gain access to your server, and run a command such as:

```bash
sudo nano /opt/sandstorm/sandstorm.conf
```

In this file, you should change `BASE_URL` to your new URL, including `http://` or `https://` and
any port number that you need. You should typically set `WILDCARD_HOST` to
`*.{{yourSandstormDomain}}`.

The WILDCARD_HOST setting should use the same port number as the BASE_URL. If your service is on
port 80 and is a HTTP service, no port number is needed; if your service is on port 443 and is a
HTTPS service, no port number is needed. WILDCARD_HOST should not specify a protocol.

In order to disable HTTPS for sandcats, look for a line starting with `HTTPS_PORT=` and remove it.

Finally, save and exit your text editor (for example with `Ctrl-o <ENTER>` and `Ctrl-x` in nano).

**Now restart Sandstorm** to make the changes take effect. You can typically do that by running:

```bash
sudo sandstorm restart
```

**Now visit your server's admin panel** to make sure that all settings look OK. Make sure to review
the login settings and test that grains launch properly. If you can't get into the admin panel, you
can generate an "admin token" on the command line by running this command.

```bash
sudo sandstorm admin-token
```

## Why can't I access Sandstorm from the Internet, even though the server is running?

If your `sandstorm.conf` looks like this:

```
SERVER_USER=sandstorm
PORT=6080
MONGO_PORT=6081
BIND_IP=127.0.0.1
BASE_URL=http://mydomain.com:6080
WILDCARD_HOST=*.mydomain.com:6080
UPDATE_CHANNEL=dev
```

then you need to change the `BIND_IP` value to `0.0.0.0`.

(To be pedantic, this the unspecified IPv4 address. For IPv6
compatibility, you may want `::` instead. We haven't tested this yet.)

## What ports does Sandstorm need open?

If you have a strict firewall around the server running Sandstorm, or
you are at home and have to enable "port forwarding" on a home wifi
gateway, here is a list of the ports Sandstorm needs. This applies on
cloud providers like Amazon EC2, where the defaults allow no inbound
traffic.

_Default configuration_

* **TCP port 6080**
* **TCP port 30025**

_Optionally_

* **TCP port 443**
* **TCP port 80**

## What are the minimum hardware requirements?

* Architecture: **amd64** (aka x86_64)
* RAM: 1 GB
* Disk space: 5 GB
* Swap: Enabled, if possible

You can probably get away with less, but we wouldn't advise it. 2GB is vastly better than 1 GB.

Using a virtual machine from Amazon EC2, Google Compute Engine,
Linode, Digital Ocean, etc., is fine; just make sure you have a recent
Linux kernel. The latest Ubuntu LTS release is an easy and good choice of base
operating system.

## Sometimes I randomly see a lot of errors across the board, while other times the same functions work fine. What's going on?

Do you have enough RAM? Linux will start randomly killing processes when it's low on RAM. Each grain
you have open (or had open in the last couple minutes) will probably consume 50MB-500MB of RAM,
depending on the app. We therefore recommend using a server with at least 2GB. If you have less that
that, see the next question.

## My virtual machine doesn't have that much RAM, what can I do?

It might help to set up swap space. The following commands will set up a file on-disk to use as
swap:

    dd if=/dev/zero of=/swap.img bs=1M count=1024
    mkswap /swap.img
    swapon /swap.img

    echo /swap.img swap swap defaults 0 0 >> /etc/fstab

## Why do you support only Google, GitHub, and passwordless email for login?

Using Google or Github for login results in top-notch security and
straightforward federated authentication with very little work. This
lets Sandstorm be focused on what it's good at. (We could add Twitter,
Facebook, etc. login as well, but we are worried about people
forgetting which one they used and ending up with multiple accounts.)

For email logins, we chose to avoid passwords entirely. Passwords have
a lot of problems. People choose bad passwords. People -- even smart
people -- are often fooled by well-crafted phishing attacks. And, of
course, people regularly forget their passwords. In order to deal with
these threats, we believe that any password-based login system for
Sandstorm must, at the very least, support two-factor authentication
and be backed by a human security team who can respond to
hijackings. There must also be an automated password reset mechanism
which must be well-designed and monitored to avoid
attacks. Unfortunately, we don't have these things yet. Moreover, we
don't believe that building a secure password login system is the best
way for Sandstorm to deliver something interesting to the ecosystem.

Another problem with password login is that it makes federation more
complicated. When you federate with your friend's server, how does it
authenticate you? Not by password, obviously. Perhaps by OpenID or
OAuth, but that is again a thing we would need to implement.

In short, we think these are the most secure options we can provide
right now.

A note about when and why we think security is important:

* For self-hosted Sandstorm servers, we want to provide a secure experience.

* For public Sandstorm servers supporting a large number of users, account security is essential.

* For a development instance only accessible to `localhost`, login security may not be particularly important. You can enable the [dev accounts](https://github.com/sandstorm-io/sandstorm/issues/150) feature to create accounts for testing apps.

Federated login enables tracking, and passwordless email login enables
anyone with temporary access to an email account to hijack an account.
One way to overcome these problems is by building GPG login so you can
create an account based on your public key. You can track progress on
that effort in [this
issue](https://github.com/sandstorm-io/sandstorm/issues/220).

## Why do I see an error when I try to launch an app, even when the Sandstorm interface works fine?

Sometimes Sandstorm seems to be working fine but can launch no apps. This typically relates to
Sandstorm's need for **wildcard DNS**. If you use HTTPS, you will also need **wildcard HTTPS**.
You can read [technical details](wildcard.md) if you wish.

You might see an error screen like this:



even when the app management interface seems to work fine:



You might also have seen a warning from the Sandstorm admin settings area. An error will appear if
your configuration fails the self-test. If so, **read the Javascript console.** Sandstorm will log
details in your browser's Javascript console, [although those details might be
minimal](http://stackoverflow.com/questions/31058764/determine-if-ajax-call-failed-due-to-insecure-response-or-connection-refused);
thankfully, your web browser will typically provide further details about the failed connection in
the Javascript console. Here are some hints, based on errors you might see.

- `Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource`: This
  usually means your WILDCARD_HOST and BASE_URL disagree about port number, or the WILDCARD_HOST and
  BASE_URL disagree about your domain name.

- `Connection refused` or `net::ERR_CONNECTION_REFUSED`: This can occur if your WILDCARD_HOST
  specifies the wrong domain name or if the WILDCARD_HOST and BASE_URL disagree about port number.

- `HTTPS security error` or `net::ERR_INSECURE_RESPONSE`: This can occur if you are using a
  self-signed certificate for Sandstorm but have not set up a self-signed CA. Read our docs on
  [self-signed SSL for Sandstorm.](self-signed.md)

Here are some tips to fix configuration issues that can cause WILDCARD_HOST problems.

- **Make sure the `WILDCARD_HOST` has valid syntax.** In the Sandstorm config file (typically
  `/opt/sandstorm/sandstorm.conf`), look for the `WILDCARD_HOST` config item. Note that this should
  **not** have a protocol as part of it but **does** need a port number if `BASE_URL` specifies a
  port number. A valid line might be:

```
WILDCARD_HOST=*.yourname.sandcats.io:6080
```

- **Make sure wildcard DNS works for your chosen domain**. See also [our documentation on wildcard
  DNS](wildcard.md). If setting up wildcard DNS is a hassle for you, consider using our free
  [Sandcats dynamic DNS](sandcats.md) service for your `BASE_URL` and `WILDCARD_HOST`.

- **Make sure wildcard HTTPS works on your server** if your server uses HTTPS. Consider using our
  free [Sandcats dynamic DNS and HTTPS](sandcats.md) service if you are OK choosing a subdomain of
  sandcats.io as your server's name, e.g. example.sandcats.io. If you are using a self-signed
  certificate, note that you must import a CA certificate into all web browsers where you want the
  Sandstorm server to able to be viewed. Web browsers do not show a "OK to continue?" prompt for
  IFRAMEs, and Sandstorm uses IFRAMEs. Read more in the [self-signed SSL guide](self-signed.md).
  You can also read our [HTTPS topic guide](ssl.md).

## Can I customize the root page of my Sandstorm install?

You can definitely customize the root page of your Sandstorm install. You might have noticed that
[Oasis](https://oasis.sandstorm.io/) has a customized front page.



This is by contrast with the default, which you can see on our older
[alpha.sandstorm.io](https://alpha.sandstorm.io/) service.



This is achieved by configuring a web page to be displayed in the background behind the login dialog
(the home page when logged out). To configure this setting, visit your server's **Admin panel**
screen and click **Personalization**. You can enter a URL as the **Splash URL (experimental)**.

For security reasons, the page must be hosted within your Sandstorm server's wildcard host
(otherwise it will be blocked by `Content-Security-Policy`). We suggest using a static web
publishing app like [Hacker
CMS](https://apps.sandstorm.io/app/nqmcqs9spcdpmqyuxemf0tsgwn8awfvswc58wgk375g4u25xv6yh) to host the
content.

This feature is experimental; in particular the style and positioning of the login box is subject to
change without notice. Please [let us know](https://github.com/sandstorm-io/sandstorm/issues) if
you'd like to see it stabilize.

When creating your own page like this, we suggest using the Oasis splash URL as a starting point.
Use your browser's DOM inspector to find the `IFRAME` that is on the background of Oasis. Use its
CSS rules to guide your own.

## Can Sandstorm use a HTTP proxy for outgoing connections?

Yes. Set the `http_proxy` and `https_proxy` environment variables in your systemd service or init
script. Right now, this can be used to install apps, but other uses of the proxy are untested. If
you discover problems with the HTTP proxy support, please [file a
bug](https://github.com/sandstorm-io/sandstorm/issues).

As background, a Sandstorm server uses Internet access to achieve tasks like:

- Downloading apps to install.

- Automatically updating itself.

- Automatically downloading app updates.

- Updating your IP address on file with the sandcats service.

If your environment requires configuring a HTTP proxy for outbound Internet connectivity, and you
are using systemd, then you can edit `/etc/systemd/system/sandstorm.service` to look like the
following. You will then need to run `sudo systemctl daemon-reload` then `sudo systemctl restart
sandstorm`.

```
[Unit]
Description=Sandstorm server
After=local-fs.target remote-fs.target network.target
Requires=local-fs.target remote-fs.target network.target

[Service]
Type=forking
ExecStart=/opt/sandstorm/sandstorm start
ExecStop=/opt/sandstorm/sandstorm stop
Environment=http_proxy=http://127.0.0.1:3128/
Environment=https_proxy=http://127.0.0.1:3128/

[Install]
WantedBy=multi-user.target
```

If you use `sysvinit` or a different init system, then make whatever similar change results in
the `http_proxy` and `https_proxy` environment variables being set.

**Note** that the sandcats.io dynamic DNS protocol requires the ability to send UDP packets to the
Internet, so if the system cannot do that, then its IP address will not auto-update. If your IP
address does not change frequently, this should be OK.

## How do I use Sandstorm with an internal IP address?

Since Sandstorm [relies on wildcard DNS](wildcard.md), you will need to modify your `sandstorm.conf`
to point at a hostname that resolves to your internal IP address. If your organization cannot
provide one, you can either use our free [sandcats.io DNS service & HTTPS that uses public IP
addresses](sandcats.md), or use [xip.io](http://xip.io)'s free wildcard DNS for internal IP
addresses.

To use xip.io, if your Sandstorm server is at (for example) 10.0.0.2, then you should:

- Open `/opt/sandstorm/sandstorm.conf` in your favorite text editor, for example by running
  `sudo nano /opt/sandstorm/sandstorm.conf`

- Find the line containing `BASE_URL` and modify it to say:

```bash
BASE_URL=http://10.0.0.2.xip.io:6080
```

- Make sure the port number above corresponds to the port in your `PORT=...` line.

- Find the line containing `WILDCARD_HOST` and modify it to say:

```bash
WILDCARD_HOST=*.10.0.0.2.xip.io:6080
```

- Make sure the port number is the same as the port number in `BASE_URL`.

- Make sure your configuration file does **not** use the `HTTPS_PORT` or `SANDCATS_BASE_DOMAIN`
  settings, which refer to integrating with the sandcats.io DNS & HTTPS service. If you see them,
  comment them out or remove them.

```bash
#HTTPS_PORT=443
#SANDCATS_BASE_DOMAIN=sandcats.io
```


- Save and exit your text editor (for example with `Ctrl-o` and `Ctrl-x` in nano).

- Restart Sandstorm by running this command in a terminal.

```
sudo sandstorm restart
```

- Visit your Sandstorm install at http://10.0.0.2.xip.io/ and make sure it is working OK.

Note that you might not have to do this! For the purpose of this question, an internal IP address is
something like 192.168.x.y or 10.x.y.z; see [Wikipedia's article on private
networks](https://en.wikipedia.org/wiki/Private_network).  Many organizations use global IP
addresses like 18.x.y.z and rely on their organization firewall to prevent external access; in that
case, our free [sandcats.io DNS service](sandcats.md) should work fine.

Keep in mind that xip.io is maintained by the kind and gracious [Sam Stephenson](http://xip.io/),
not by a member of the Sandstorm team. If you want to run your own wildcard DNS service similar to
xip.io inside your own organization, you can do so by [downloading
xipd](https://github.com/sstephenson/xipd) which Sam generously licenses as open source software.
You can also set up your own `*.sandstorm.example.com` subdomain within your organization's domain.

## mongod failed to start. What's going on?

If your Sandstorm server isn't working, and you find this text in `/opt/sandstorm/var/log/sandstorm.log`:

```
**mongod failed to start. Initial exit code: 100, bailing out now.
```

then MongoDB is unable to start. Sandstorm operates an embedded MongoDB database instance to store
information like what user accounts exist and what permissions they have. Keep the following in mind
to address the issue.

- Your system might not have enough free disk space. Sandstorm requires about 500 MB available space
  to start successfully.

- You can read `/opt/sandstorm/var/log/mongo.log` to find out MongoDB's true error
  message. Specifically, the file will be in `var/log/mongo.log` underneath wherever Sandstorm is
  installed; most Sandstorm installations are at `/opt/sandstorm`.

- You might be running into a bug in Sandstorm where it is unable to start MongoDB successfully. If
  so, this is a bug in Sandstorm that probably affects many, many people, and if you report this
  issue, we will be grateful; your bug report could lead to a code change that fixes many people's
  Sandstorm servers. To do that, we need to hear from you.

- In theory, this error message can occur if your Sandstorm database (stored in
  `/opt/sandstorm/var/mongo`) has become corrupted. So far, we have seen no instances of this in the
  wild. If it does occur, you can likely recover from the situation. Even if there is a problem with
  the Sandstorm MongoDB instance, note that grain data is safely stored separately, so any grain data
  would not be affected.

To get further help, please [open an issue on GitHub](https://github.com/sandstorm-io/sandstorm/issues/new). Please include the most recent 100 lines
from the MongoDB log file, if you can.

## Installing and running without root privileges

In Sandstorm v0.190 and higher, Sandstorm requires either:

- The ability to launch Sandstorm as root so it can drop privileges itself, or

- Unprivileged user namespaces enabled in your system's Linux kernel.

You can ask Sandstorm to do an install as non-root by passing `-u` to the install script. For
example:

```
curl https://install.sandstorm.io/ > install.sh
bash install.sh -u
```

If you start Sandstorm as a non-root user, Sandstorm uses unprivileged user namespaces as part of an
alternative grain isolation strategy. Some Linux kernels do not have user namespaces available, or
make them only available to root, so this article provides advice on how to enable user
namespaces. If you use the userns-based sandbox, please be sure to keep up to date with kernel
updates.

- **People who don't know how to change a Linux kernel.** If you are a customer of a hosting
  provider, please ask your hosting provider to read this page.

- **Arch Linux users.** We suggest starting Sandstorm as root instead to avoid the dependency on
  user namespaces. In [#36969](https://bugs.archlinux.org/task/36969), the Arch Linux kernel
  maintainer indicated that they are not interested in supporting unprivileged user namespaces. Try
  the `linux-lqx` AUR package, or build your own kernel. Read the [Arch Linux wiki page on
  kernels](https://wiki.archlinux.org/index.php/Kernels#AUR_packages) for more information.

- **Docker users.** You can launch Sandstorm as root per our [recommendations for
  Docker](../install.md#option-6-using-sandstorm-within-docker) in our installation guide.
  Alternatively, if your system needs it, you can use the Debian-specific sysctl, but you
  will need to provide `--cap-add SYS_ADMIN --security-opt seccomp=unconfined` to `docker run`.

- **Debian and Ubuntu users.** The Sandstorm install script can use a [Debian-specific
  sysctl](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=712870) to enable unprivileged user
  namespaces. If you are unable to set it on your system, please run these commands as root and/or
  upgrade your Linux kernel.

```bash
# sysctl -w kernel.unprivileged_userns_clone=1
# echo 'kernel.unprivileged_userns_clone = 1' >> /etc/sysctl.conf"
```

- **RHEL and CentOS users.** We suggest starting Sandstorm as root. If you must use the userns
  sandbox, note that CentOS/RHEL 7.2 ships a kernel that _may_ be able to support unprivileged
  usernamespaces. In our testing, further work is needed to properly enable Sandstorm to work within
  CentOS/RHEL 7.2. If you need help with this, please email
  [support@sandstorm.io.](mailto:support@sandstorm.io)

- **OpenVZ users.** If you use an OpenVZ-based hosting provider, please try to run Sandstorm as
  root.  If that does not work, please ask your hosting provider to read our [installation
  documentation](../install.md) and this document.

- **Grsecurity kernel users.** Grsecurity seems to block unprivileged user namespaces. Sandstorm
  should operate properly if you start it as root. If you need use Sandstorm with user namespaces,
  consider running Sandstorm without Grsecurity. You might be interested to see [Sandstorm's track
  record of successfully blocking exploitation of Linux kernel
  vulnerabilities.](../using/security-non-events.md#linux-kernel)

- **Alpine Linux users.** Alpine Linux enables Grsecurity by default. See the previous item and
  consider using the [Alpine vanilla kernel.](http://forum.alpinelinux.org/downloads)

As an implementation detail, running install.sh with `-d` uses user namespaces if available, and
enables the Debian-specific sysctl on Debian/Ubuntu systems if possible.

## How do I enable WebSockets proxying? or, Why do some apps seem to crash & reload?

Some Sandstorm users find that apps like Telescope and Groove Basin seem to load an initial screen
and then refresh the page, in a loop. This is typically a symptom of Sandstorm running behind a
reverse proxy that needs WebSockets proxying to be enabled.

For `nginx`: consult the
[nginx-example.conf](https://github.com/sandstorm-io/sandstorm/blob/master/docs/administering/sample-config/nginx-example.conf)
that we provide. Pay special attention to:

- The `map $http_upgrade $connection_upgrade` section. You need to add this to the config
  file for this site.

- The two `proxy_set_header` lines relating to `Upgrade` and `Connection`.

For `apache2`: consult the
[apache-virtualhost.conf](https://github.com/sandstorm-io/sandstorm/blob/master/docs/administering/sample-config/apache-virtualhost.conf)
that we provide. Pay special attention to the `RewriteRule` stanzas.

## Can I use Let's Encrypt for adding HTTPS to Sandstorm?

Yes, support for Let's Encrypt was added in 0.263. To use Let's Encrypt, your Sandstorm server needs
to be able to modify your DNS records. This is made possible by [the ACME.js library](https://git.rootprojects.org/root/acme.js) as long as
you use a supported DNS provider (Sandcats.io, Cloudflare, Digital Ocean, DNSimple, Duck DNS, GoDaddy,
Gandi, Namecheap, Name.com, AWS Route 53, or Vultr). You can now configure this in the admin panel.

## Does Sandstorm run on ARM systems like Raspberry Pi?

Not yet, and there is currently no timeline on adding ARM support to Sandstorm.

We might revisit this in a year or two, once we're happy with the Sandstorm experience on x86-64.
You shouldn't plan on ARM support existing at any particular time. If you want Sandstorm on a small
computer, we can suggest the following, though we haven't personally tried them.

- Small desktop PCs like running 64-bit Intel CPUs, such as the [Asus Chromebox
  M004U](https://www.amazon.com/Asus-CHROMEBOX-M004U-ASUS-Desktop/dp/B00IT1WJZQ/) ($150 at time of
  writing), the [Dell Inspiron micro desktop
  series](http://www.dell.com/us/p/inspiron-3050-micro-desktop/pd), or any Intel NUC such as the
  [NUC5CPYH](https://www.amazon.com/gp/product/B00XPVRR5M/) ($130 at time of writing). Note that for
  a Chromebox, you must modify it to run Ubuntu first by following [directions like
  these.](http://dareneiri.github.io/Asus-Chromebox-With-Full-Linux-Install/)

- [Jaguarboard](http://www.jaguarboard.org/index.php/products/buy/jaguarboard.html), a 1GB RAM
  single-board computer running an [Intel Z3735G
  64-bit CPU.](http://ark.intel.com/products/80275/Intel-Atom-Processor-Z3735G-2M-Cache-up-to-1_83-GHz)
  $80 at the time of writing.

- Intel Compute Sticks such as the [CS125](https://www.amazon.com/gp/product/B01AZC4NHS/) running
  the [x5-Z8300 64-bit
  CPU.](http://ark.intel.com/products/87383/Intel-Atom-x5-Z8300-Processor-2M-Cache-up-to-1_84-GHz)
  $130 at the time of writing.

We are focusing on x86-64 because we only have so much time in the day. If you're a volunteer and
interested in tackling the ARM/multi-architecture situation, then please speak up on the
[related issue](https://github.com/sandstorm-io/sandstorm/issues/2083).

There are a few obstacles we'd need to overcome for Sandstorm to provide a good experience
on ARM.

- **Sandstorm app authors compile their own app packages,** so we would need to either ask app
  authors to cross-compile on their own systems, or we would need to set up a buildd network. If we
  set up a buildd network, this would come into conflict with the Sandstorm app package signing
  situation where app authors sign their binaries. They might not have a way to test the ARM
  binaries that we build on the automated builders, so quality might suffer. This isn't a top
  priority at the moment within Sandstorm-the-company because it would take time and attention from
  other things which we think will better serve a greater number of users right now. We would welcome
  help.

- **Historically, MongoDB doesn't officially support ARM.** Thankfully all new versions of MongoDB
  do support ARM! Read more at this [MongoDB issue.](https://jira.mongodb.org/browse/SERVER-1811)
  Although some Sandstorm apps embed old versions of MongoDB, this is presumably not a big problem
  anymore.

We hope to be able to provide a more satisfying answer one day. If you don't need ARM in particular,
but you want a power-efficient small computer that runs Sandstorm, see the links above.

## Is Sandstorm ready for production use? Is it in beta?

Sandstorm is ready for production use, and is used by thousands of users for real work every day.
The Sandstorm team itself relies on Sandstorm extensively for our day-to-day work including project
management, collaboration, and file management, as do many other individuals and companies. As with
any software product, there are plenty of things on our roadmap that we intend to add or improve
over time, but the core functionality has been stable for a while.

## Can I run Sandstorm on a totally-offline server or airgapped network?

Yes. See: [Running Sandstorm offline](offline.md)

## Why do I see strange DNS lookups in my server log?

When viewing your server's admin log, you might see DNS-related messages like this. They are
harmless and can be ignored. They are probably the result of bots scanning the Internet for security
issues that do not affect Sandstorm.

```
Error: Host "sandstorm-www.notyourdomain.example.com" must have exactly one TXT record.
    at server/pre-meteor.js:728:16
    at QueryReqWrap.asyncCallback [as callback] (dns.js:64:16)
    at QueryReqWrap.onresolve [as oncomplete] (dns.js:216:10)

Error: Error looking up DNS TXT records for host "notyourdomain.example.com": queryTxt ETIMEOUT sandstorm-www.notyourdomain.example.com
    at server/pre-meteor.js:728:16
    at QueryReqWrap.asyncCallback [as callback] (dns.js:64:16)
    at QueryReqWrap.onresolve [as oncomplete] (dns.js:216:10)
```

The odd log messages are the result of misdirected HTTP requests (probably from bots) and the way
Sandstorm's static publishing for external domains works. There's no security issue here, nor any
action required by the server admin.

Sandstorm supports publishing static sites at domains that are not part of its "wildcard domain."
This allows you to publish a website at a domain like example.com from your Sandstorm server,
preserving the domain. To achieve this, you would make a DNS A record for example.com pointing at
your Sandstorm server. This ensures that when users navigate to example.com in their browser, the
browser sends the request to Sandstorm.

Once Sandstorm receives this request, it needs to know which grain it should dispatch this request
to. This is supported by having the user create a DNS TXT record for sandstorm-www.example.com
containing the grain's "public ID". If no such DNS record is found, Sandstorm concludes that the
domain owner has not indicated a desire to publish a particular Sandstorm grain at the domain
from the HTTP request.

What's happening in your log traces is that Sandstorm is receiving HTTP requests for those domains,
performing the DNS lookup to see what grain's static publishing folder should be used to answer
those requests, and the DNS lookup is either failing (in the case of `ETIMEOUT`) or returning a
response whose format surprises Sandstorm.

Sandstorm logs this event since it could indicate a configuration problem if it occurred for a
domain name that **should** be served from this Sandstorm server.

## How do I notify the owner of a resource-hogging process?

1. Identify the process via `top`.
2. `cat /proc//mountinfo` and find the mapping that looks like `/opt/sandstorm/var/sandstorm/grains/<grain-id>/sandbox /var`. This gives you the grain ID.
3. `sudo sandstorm mongo` to get to the Sandstorm mongo shell.
4. `db.grains.find({_id: "<grain-id>"})` to get info about the grain. In particular, the `userId` is shown.
5. `db.users.find({_id: ""})` to get the user record. Look for the list of `loginCredentials`, and take the first ID shown.
6. `db.users.find({_id: "<login-credential-id>"})` to get info about the user identity.

This should show you the user's profile info including e-mail address, etc.

## A very large grain fails to start. How can I fix this issue?

In some cases, grains with a large number of files may fail to start, and the error `sandstorm/supervisor.c++:232: overloaded: inotify_add_watch: No space left on device;` is logged in the grain log. This is caused by a Linux setting which limits the maximum number of inotify watches a given user account (in this case, `sandstorm`) may request. Due to how Sandstorm monitors storage usage, this value acts as the limit of the number of files which can exist in simultaneously open grains. Starting with the Linux kernel 5.11, the default value of this setting is dynamically adjusted based on memory, but on older kernels, it may be lower than warranted. The previous default was 8,192.

You can check the setting by executing the following command: `cat /proc/sys/fs/inotify/max_user_watches`

To increase this limit, add a line like `fs.inotify.max_user_watches=32768` to `/etc/sysctl.conf` and then execute the command `sysctl -p` to load the configuration.

---

## File: docs/administering/for-work.md

Sandstorm offers [a variety of features](https://sandstorm.io/business) intended for use by
organizations (e.g., companies) that make Sandstorm available to their members (e.g., employees).
These features used to be a part of a product called "Sandstorm for Work", but have since been
merged into the standard Sandstorm build, available to everyone.

## Organizational features in depth

### Defining an organization, and its impact on permissions

Many of Sandstorm's organization features depend on a server administrator specifying the group of users
that will be working together using Sandstorm. We call this **organization management.** You can enable
and disable organization-related features via the `/admin/organization` settings area.

To apply settings to all users within an organization, you must use organization management settings to
configure the boundary of your organization with regard to at least one login provider. Users within the
organization will automatically be able to log in, install apps, and create grains.

To enable this feature:

- Log in to your server as an administrator.

- Click your name at the top right, then **Admin panel**; this should take you to `/admin`.

- Under the "Configuration" header, click "Organization settings"

- Enable and configure your organization membership on a per-login-provider basis.

Login providers have different settings that are used to define your organization. A user is
considered a member of your organization if the settings for **at least one** login provider
declare the user to be a member. You can enable/disable this on a per-login-provider basis.

- **Google authentication.** All users who use a particular Google Workspace domain of your choosing can
  receive user status in Sandstorm. When you enable the use of Google Workspace to define the boundary
  of your organization, you must specify which Google Workspace domain represents your organization.

- **SAML authentication, including Active Directory.** All users who log in via SAML can
  automatically receive user status in Sandstorm. When you use SAML to define the boundary of your
  organization, all users who log in via SAML are considered members of the organization. Sandstorm
  supports logging in via Active Directory via support for SAML 2.0 and provides a [step-by-step
  tutorial.](active-directory.md)

- **LDAP authentication.** All users who log in via LDAP can automatically receive user status in
  Sandstorm. When you use LDAP to define the boundary of your organization, all users who log in via
  LDAP are considered members of the organization.

- **Passwordless email login.** All users who use a particular email address domain name
  (e.g. @example.com) can receive user status in Sandstorm. To enable this, you must specify which
  Internet domain name represents your organization.

This feature is important because, by default, when a user signs into a Sandstorm server for the
first time, Sandstorm creates a _Visitor_ account for them. Visitors can use grains that have been
shared with them but cannot create grains of their own.

### Additional organization settings

Once you have defined your organization, you can optionally configure system-wide rules based on
organization membership. This can be done from `/admin/organization` within your Sandstorm server.

You can **disallow collaboration with users outside the organization.** If you enable this option,
grains can only be seen by users logged-in as a member of your organization. This means:

- Unauthenticated (aka anonymous) users cannot view grains, even if they have a sharing link.

- When a user attempts to create an account or sign in, Sandstorm validates that they are part
  of your organization. If not, then they may not create an account or sign in. This prevents
  [Visitors](guide.md) from using their accounts.

- Security note: at the moment, this setting only applies to new logins. If a user was already signed
  in when you first enabled this option, the user would be able to continue to use their account even
  if they're not a member of your organization.

You can **make all organization users visible to each other.** This setting automatically adds
users within the organization to each other's contact list so that they can share grains with each
other. The contact list is used for autocomplete when users are in the "Share access" dialog within
a grain. Disable this if you have some users whose identity should stay hidden from other users.

### Authentication provider: SAML 2.0

SAML 2.0 is a passwordless single sign-on protocol. It allows a web application such as Sandstorm to
request the current user's credentials from a central service, typically administered by a
university or corporate IT team. Sandstorm's SAML support is compatible with Shibboleth, Okta,
Microsoft Active Directory, SimpleSAMLphp, and other SAML services. We have special documentation
for [single sign-on with Active Directory.](active-directory.md)

To enable SAML login on your Sandstorm server, take the following steps:

- Log into your Sandstorm server as an administrator.

- Click **Admin panel** within your Sandstorm server; this should take you to `/admin`.

- Under "Configuration", click on "Identity providers"; this should take you to `/admin/identity`.

- In the Identity providers table, click the "Configure" button in the SAML row.

- Complete the form and enabled SAML login.

Your SAML IDP should be configured to return a persistent nameID. In addition, if you are not using
Active Directory, you **must** configure your IDP to provide two extra attributes, email and
displayName.

The easiest way to integrate with SAML is if your SAML IDP supports reading the service provider
metadata from a URL. If it does, you can point it to your Sandstorm base URL followed by
`/_saml/config/default`. For example: `https://sandstorm.example.com/_saml/config/default`

The Service URL of this server is displayed in the configuration dialog, and is always your server's
hostname plus `/_saml/validate/default`. For example:
`https://sandstorm.example.com/_saml/validate/default`

### Authentication provider: LDAP

LDAP is a protocol for storing information of nearly any kind; it is typically used to store data
about people who work at a company, including login credentials.  Sandstorm's LDAP support allows
you to log into Sandstorm with a username and password that is checked against an LDAP store.
Sandstorm's LDAP support is compatible with Microsoft Active Directory, OpenLDAP, and many other
LDAP servers.

To enable LDAP login, take the following steps:

- Log into your Sandstorm server as an administrator.

- Click **Admin panel** within your Sandstorm server; this should take you to `/admin`.

- Under "Configuration", click on "Identity providers"; this should take you to `/admin/identity`.

- In the Identity providers table, click the "Configure" button in the LDAP row.

- Complete the form and enabled LDAP login.

Implementation notes for LDAP that may apply to your site:

- A typical LDAP configuration (e.g. Active Directory) will use an **Base DN** of
  `ou=People` followed by the LDAP version of your domain name. For `example.com`, this would be
  `ou=People,dc=example,dc=com`.

- When logging in with LDAP, you might run hit this error: `Exception while invoking method 'login'
  SizeLimitExceededError`. In our testing, this seems to occur with LDAP sites where multiple LDAP
  objects match the username. In this case, you probably need to add a custom **LDAP Search
  Filter** under "Additional LDAP filter criteria. Your search filter should typically take the form
  of `(&(something))` so that it is AND'd against the default Sandstorm LDAP query used when a user
  is logging in.

- Some LDAP servers require authentication before permitting a search. In that case, you will need
  to configure an **Bind user DN** and **Bind user password**, a user and password for the search
  user.
  
- In Active Directory, the `uid` field is generally not set. In a typical Active Directory setup,
  set the **LDAP username attribute** to either `sAMAccountName` for username-only (e.g. bob) or
  `userPrincipalName` for user-at-domain (e.g. bob@example.com) format login.

- Typically LDAP servers use the `cn` field to store the name of the person who is successfully
  logging in. `cn` is short for common name. If your LDAP server is configured differently, please
  adjust the **LDAP given name attribute**.

### Whitelabeling

You may customize Sandstorm's appearance to make it appear more like a service of your organization.
For instance, you can:

- Change the logo used when users sign in

- Hide the "Troubleshooting" button on the login page

- Hide the "Send feedback" link on the login page

- Change the title the server shows to all its users in the top-left

To do that, visit the **Admin settings** area, then click **Personalization** and look for the
**Whitelabeling** options.

These features are in addition to Sandstorm's existing customization options, enabling the
admin to:

- Set a server title

- Set a custom splash URL on home page, as you can see on [Oasis](https://oasis.sandstorm.io).

- Change the message that users see when they receive an invitation to the server.

- Set a URL for a terms of service.

- Set a URL for a privacy policy.

You can read about these features in the [Sandstorm administration
FAQ.](faq.md#can-i-customize-the-root-page-of-my-sandstorm-install)

### Features coming soon

We're still working on the following features:

**Group management.** This will allow you to share a grain with everyone in a group, such as the
marketing department, using groups from Google or LDAP. For now, you can use the
[Collections app](https://sandstorm.io/news/2016-08-09-collections-app) to create groups of grains
that you share with the people who need access.

**Global audit logging.** Monitor data across the whole organization to keep track of who has
accessed what.

---

## File: docs/administering/guide.md

# Sandstorm administrator's guide

This guide provides an overview of essential topics you'll need to know to make productive use of
your own Sandstorm self-install.

## Customizing Sandstorm for your users

See these topics elsewhere in the docs:

- [Developing new apps for your Sandstorm server](../developing.md)

- [Creating a custom page at the root of your Sandstorm server](faq.md#can-i-customize-the-root-page-of-my-sandstorm-install)

- [Serving static content on domain names controlled by your users](../developing/web-publishing.md)

- [Enabling HTTPS/SSL](ssl.md)

## File locations & service management

By default, Sandstorm installs within **/opt/sandstorm**.

- Now is a good time to `cd /opt/sandstorm` and use `ls` take a look around!

**Note:** If you are having trouble finding `/opt/sandstorm`, it could be because you need to `vagrant
ssh` into the virtual machine that runs Sandstorm for you.

The [install script](https://github.com/sandstorm-io/sandstorm/tree/master/install.sh) creates a system
service to run Sandstorm, by default.

- To start Sandstorm, run: `sudo service sandstorm start` or `sudo systemctl start sandstorm`
  (depending on your Linux distribution).

- To stop or restart Sandstorm, replace `start` with `stop` or `restart` in the above command.

Within `/opt/sandstorm` there are a few essential files and directories.

- `/opt/sandstorm/sandstorm.conf` - this is the Sandstorm configuration file. We sometimes refer to
  this as `sandstorm.conf` for short. Edit it by running `sudo nano /opt/sandstorm/sandstorm.conf`;
  after editing it, restart Sandstorm.

- `/opt/sandstorm/var/log/sandstorm.log` - this is the log file for Sandstorm. If you are logged in
  to a Sandstorm install as an administrator, you can view this on the web by visiting **Admin
  panel** then clicking **System log**.

- `/opt/sandstorm/var/mongo` - this is the data directory for MongoDB, the database engine that
  stores all Sandstorm data like grain names, user names, and permissions. You can query it by
  starting a Mongo shell by running: `sudo sandstorm mongo`.

- `/opt/sandstorm/var/sandstorm/grains` - this directory contains the files and directories created
  by each app instance, which we call a grain.

- `/opt/sandstorm/var/sandstorm/grains/{{grainId}}/sandbox` - this directory is available within the
  grain as `/var`, via a filesystem namespace.

- `/opt/sandstorm/var/sandcats` - this directory contains configuration information for the
  [sandcats.io dynamic DNS service](sandcats.md).

- `/opt/sandstorm/sandstorm-{{versionNumber}}` - this directory contains Sandstorm and all its
  dependencies. To install your own modified version, read our instructions on [building Sandstorm
  from source](../install.md#option-4-installing-from-source).

### Processes and syscalls: Getting under the hood of Sandstorm

When Sandstorm is running, it launches the **bundle runner,** a tool that ensures other components
of Sandstorm are properly launched. The bundle runner starts by containerizing itself, using the
Linux syscalls related to [namespaces, seccomp, and so forth.](../using/security-practices.md)

The bundle runner ensures that other components of Sandstorm launch properly, including:

- The auto-updater, which executes curl periodically to check for new versions of Sandstorm.

- The Sandstorm shell, a nodejs process which serves HTTP(S) for visitors to your Sandstorm server.

- MongoDB, the database used by Sandstorm.

- The Sandstorm backend, a C++ program which itself uses namespace syscalls to launch grains.

- The server monitor, which restarts the shell, MongoDB, and/or the Sandstorm backend if any of them
  abruptly exit.

If a server is idle, these are the only Sandstorm-related processes on a server.

When a user navigates within the Sandstorm shell to launch a grain, a process tree is created
starting at `supervisor`. The per-grain supervisor containerizes and launches the processes
specified as the grain's entry point.

To manually inspect these processes, consider using `strace` and `ps` on a running Sandstorm server.

## New versions and applying updates

### Sandstorm itself

We release new versions of Sandstorm approximately once per week. We release them to
[dl.sandstorm.io](https://dl.sandstorm.io/) as `tar.xz` files.  Since they contain not just
Sandstorm but all of Sandstorm's dependencies, we call them the **Sandstorm bundle.**

Since September 2015, we [sign updates and Sandstorm verifies these
signatures](https://blog.sandstorm.io/news/2015-09-24-is-curl-bash-insecure-pgp-verified-install.html).
By default, Sandstorm checks for updates every day. You can configure this behavior by editing `sandstorm.conf`.

This setting enables automatic updates.

```
UPDATE_CHANNEL=dev
```

This setting disables it.

```
UPDATE_CHANNEL=none
```

We intend to follow the Chrome update channels system, but for now we only have a `dev` channel.

We strongly recommend that you keep automatic updates enabled. This is a work in progress, but
we intend for our automatic updates to not cause any downtime.

### Sandstorm apps

Sandstorm apps are distributed as **SPK** files. They contain contain a Linux web app and all its
dependencies, as well as metadata like the app version and author name. The SPK file format is
defined using Cap'n Proto as
[package.capnp](https://github.com/sandstorm-io/sandstorm/blob/master/src/sandstorm/package.capnp)
and you can use the `spk` command line tool to analyze a package.

Sandstorm.io, the organization, maintains a list of packages in an [app
market](https://apps.sandstorm.io/). The app market publishes metadata about what apps are
available, called the **app index.** Every day, Sandstorm downloads this file. For every app in the
app index, if a user on your Sandstorm server has an older version installed, Sandstorm creates a
notification suggesting that the user click a button to update to the latest version.

This behavior can be customized within the **Admin panel** under **App sources**. We strongly recommend
keeping this enabled. You can also point your Sandstorm install at a different app market URL and
app index URL.

## Hostnames and wildcards

In `sandstorm.conf`, the `BASE_URL` specifies the URL at which your Sandstorm install assumes it is
available. For example, it might be:

```
BASE_URL=http://sandstorm.example.com
```

Sandstorm requires a [wildcard DNS record](https://en.wikipedia.org/wiki/Wildcard_DNS_record). Each
session to each grain uses a unique, one-time-use hostname; Sandstorm uses this as [part of its
security model](wildcard.md) and this requirement cannot be disabled.

Typically, people configure a wildcard record at `*.sandstorm.example.com`. The `WILDCARD_HOST` can
point at a different wildcard within the same domain name, but note that the `BASE_URL` and
`WILDCARD_HOST` must be within the same domain name. Therefore, the following can work as well:

```
BASE_URL=http://sandstorm.example.com
WILDCARD_HOST=ss-*.example.com
```

This would cause Sandstorm to create hostnames of the form `ss-foobar.example.com` and assumes that `*.example.com` is set up as a wildcard record. In BIND syntax, that would be the following.

```
*.example.com. 3600 IN A 0.0.0.0
```

**Note** that any port number that appears in `BASE_URL` must also appear in `WILDCARD_HOST`.

**For SSL/HTTPS,** you will also need a wildcard certificate. Read more about [Sandstorm and HTTPS](ssl.md).

## Accounts, authentication, and access control

Key concepts:

- A Sandstorm grain is owned by the person who created it.

- Every Sandstorm user sees only the grains they have created or the grains that have been shared with them.

- Every Sandstorm user starts by seeing no apps installed, and must install apps on their own.

- Sandstorm supports multiple **login providers** which can be enabled/disabled from the **Admin panel**.

There are three standard levels of users.

- **Visitors** can use and re-share grains that have been shared with them. They cannot create grains of their own nor install apps. By default, anyone can click **Sign in** and become a Visitor. If you would prefer to disallow visitors entirely, you can enable the setting "Disallow collaboration with users outside the organization", found under "Organization settings" in the admin panel.

- **Users** can install apps for their own use, create grains, and share them with others. By default, these users must be invited by an Admin.

- **Admins** can also see the **Admin panel**, allowing them to invite users, modify user levels, and configure server settings like login providers and email settings.

Additionally, Sandstorm has **demo accounts** which are disabled by default. See the [Demo mode](demo.md) documentation for details.

If you see a message saying your Sandstorm install has no users, read the [How do I log in, if
there's a problem with logging in via the
web?](faq.md#how-do-i-log-in-if-theres-a-problem-with-logging-in-via-the-web) frequently-asked
question.