Skip to content

Configuration and operations

Most installs only need the settings in Install with Docker Compose. This page is the full reference, for when you need more.

  • Sail reads settings from environment variables that start with SAIL_.
  • An empty value counts as unset.
  • Any secret can come from a file instead: add _FILE to its name and give the path, such as SAIL_SECRET_KEY_FILE=/run/secrets/sail_secret_key. Use files for secrets, so they don’t show up in docker inspect.
  • If a setting is wrong, Sail lists every problem and refuses to start. Check docker compose logs sail.

The bundled compose.yaml passes the common settings through from .env. To use any other, add it in a compose.override.yaml:

services:
sail:
environment:
SAIL_LOG_FORMAT: pretty
SettingWhat it is
SAIL_PUBLIC_URLThe address people use, such as https://sail.example.com. HTTPS, except http://localhost for a trial.
SAIL_DATABASE_URLThe Postgres connection. The bundled Compose file builds it from SAIL_DATABASE_PASSWORD.
SAIL_SECRET_KEY32 random bytes, base64. Seals stored secrets. Make one with openssl rand -base64 32.
SettingDefaultWhat it does
SAIL_OIDC_ISSUER—Your identity provider’s issuer URL. Set it with the client ID and secret, or not at all.
SAIL_OIDC_CLIENT_ID—The client ID of Sail’s app in your provider
SAIL_OIDC_CLIENT_SECRET—Its client secret. Use the _FILE form.
SAIL_OIDC_ALLOWED_DOMAINS—Email domains that may sign in, separated by commas
SAIL_OIDC_REQUIRED_GROUP—A group people must be in to sign in
SAIL_OIDC_GROUPS_CLAIMgroupsThe ID-token claim that holds groups
SAIL_OIDC_SCOPESopenid email profileScopes to ask for. offline_access is added when your provider supports it.

Set in the environment, these lock the wizard’s sign-in step. See Sign in with your identity provider.

SettingWhat it does
SAIL_NEXUS_URLYour Nexus address, for a token connection
SAIL_NEXUS_TOKENA Nexus access token. Use the _FILE form.

Leave both unset to pair from the browser instead. See Connect Nexus.

SettingDefaultWhat it does
SAIL_OUTBOUND_ALLOW—Private hosts or networks Sail may call, such as nexus.internal or 10.0.0.0/8
SAIL_TRUSTED_PROXIES—Proxy networks whose X-Forwarded-For Sail believes, for real IP addresses in the audit log
SAIL_SANDBOX_URL—The separate address where interactive pages run. Unset, pages show as source.
SAIL_SECURITY_CONTACTMsty’sContacts for your /.well-known/security.txt, such as mailto:security@example.com
SAIL_SECURITY_POLICYMsty’sYour disclosure policy’s address, for security.txt
SAIL_SECURITY_EXPIRES180 days aheadWhen your security.txt expires
SettingDefaultWhat it does
SAIL_LISTEN0.0.0.0:8484Where Sail listens inside the container
SAIL_SANDBOX_LISTEN0.0.0.0:8585Where the page sandbox listens
SAIL_METRICS_LISTEN0.0.0.0:9484 in ComposeWhere Prometheus metrics are served
SAIL_STORAGE_DIR/data/filesWhere files are stored
SAIL_DATABASE_MAX_CONNECTIONS20Database connections per Sail process
SAIL_LOG_FORMATjsonjson for log tools, pretty for people
SAIL_LOGinfoLog detail, such as debug,sqlx=warn
SAIL_SHUTDOWN_GRACE_SECS30How long replies in progress may finish when Sail stops
SAIL_UPSTREAM_IDLE_TIMEOUT_SECS120How long Sail waits on a silent Nexus or identity provider

These live in .env and are read by compose.yaml, not by Sail itself.

SettingWhat it does
SAIL_IMAGEThe Sail image and version to run
SAIL_DATABASE_PASSWORDThe bundled Postgres’s password. Hex characters only.
SAIL_DOMAINSail’s domain, for the bundled Caddy
SAIL_SANDBOX_DOMAINThe page sandbox’s domain, for the bundled Caddy
SAIL_PORT, SAIL_SANDBOX_PORTThe local ports your own proxy forwards to. Defaults 8484 and 8585.

If your identity provider or Nexus uses a certificate from your own certificate authority, give Sail a bundle with the public roots plus yours:

  1. Make a bundle: the standard public roots, followed by your CA certificate, in one PEM file.
  2. Mount it into the container, and point SSL_CERT_FILE at it:
services:
sail:
environment:
SSL_CERT_FILE: /run/secrets/ca_bundle
secrets:
- ca_bundle
secrets:
ca_bundle:
file: ./secrets/ca-bundle.pem

Sail ignores HTTP_PROXY and HTTPS_PROXY on purpose. It talks to your identity provider and Nexus directly.

Point SAIL_DATABASE_URL at your database service, such as Amazon RDS or Azure Database for PostgreSQL, in a compose.override.yaml. Use Postgres 16 or later. Sail needs the pg_trgm extension, and creates it on first start if its database user is allowed to.

backup.sh doesn’t cover an external database. Use your provider’s backups.

CheckAnswers
GET /healthzIs Sail running?
GET /readyzIs the database reachable and up to date? Returns 503 if not.

Both are on Sail’s main port, need no sign-in, and stay out of the logs. Point your load balancer or uptime monitor at /readyz.

From the server:

curl -fsS http://127.0.0.1:8484/readyz

Sail serves Prometheus metrics at /metrics on port 9484. The bundled Compose file doesn’t publish that port, so scrape it from the Compose network at http://sail:9484/metrics.

MetricWhat it tells you
sail_http_requests_total, sail_http_request_duration_secondsTraffic and response times
sail_runs_active, sail_runs_totalReplies being written now, and in total
sail_run_time_to_first_token_secondsHow long people wait for a reply to start
sail_run_pre_upstream_secondsSail’s own time before it calls the model
docker compose logs -f sail

Logs are JSON lines by default, ready for your log tool. They never contain message content or secrets, and request URLs are logged without their query strings.

Run these inside the container with docker compose exec sail sail <command>.

CommandWhat it does
sail admin recoverPrints a one-time link, valid for an hour, that makes whoever signs in with it an owner
sail migrateUpdates the database, then exits
sail healthcheckExits 0 when Sail is healthy. Docker uses it for the container’s health.
sail keygenPrints a new random secret key
sail --versionPrints Sail’s version