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.
How settings work
Section titled “How settings work”- 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
_FILEto its name and give the path, such asSAIL_SECRET_KEY_FILE=/run/secrets/sail_secret_key. Use files for secrets, so they don’t show up indocker 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: prettySettings
Section titled “Settings”Required
Section titled “Required”| Setting | What it is |
|---|---|
SAIL_PUBLIC_URL | The address people use, such as https://sail.example.com. HTTPS, except http://localhost for a trial. |
SAIL_DATABASE_URL | The Postgres connection. The bundled Compose file builds it from SAIL_DATABASE_PASSWORD. |
SAIL_SECRET_KEY | 32 random bytes, base64. Seals stored secrets. Make one with openssl rand -base64 32. |
Sign-in
Section titled “Sign-in”| Setting | Default | What 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_CLAIM | groups | The ID-token claim that holds groups |
SAIL_OIDC_SCOPES | openid email profile | Scopes 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.
| Setting | What it does |
|---|---|
SAIL_NEXUS_URL | Your Nexus address, for a token connection |
SAIL_NEXUS_TOKEN | A Nexus access token. Use the _FILE form. |
Leave both unset to pair from the browser instead. See Connect Nexus.
Network and security
Section titled “Network and security”| Setting | Default | What 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_CONTACT | Msty’s | Contacts for your /.well-known/security.txt, such as mailto:security@example.com |
SAIL_SECURITY_POLICY | Msty’s | Your disclosure policy’s address, for security.txt |
SAIL_SECURITY_EXPIRES | 180 days ahead | When your security.txt expires |
Running
Section titled “Running”| Setting | Default | What it does |
|---|---|---|
SAIL_LISTEN | 0.0.0.0:8484 | Where Sail listens inside the container |
SAIL_SANDBOX_LISTEN | 0.0.0.0:8585 | Where the page sandbox listens |
SAIL_METRICS_LISTEN | 0.0.0.0:9484 in Compose | Where Prometheus metrics are served |
SAIL_STORAGE_DIR | /data/files | Where files are stored |
SAIL_DATABASE_MAX_CONNECTIONS | 20 | Database connections per Sail process |
SAIL_LOG_FORMAT | json | json for log tools, pretty for people |
SAIL_LOG | info | Log detail, such as debug,sqlx=warn |
SAIL_SHUTDOWN_GRACE_SECS | 30 | How long replies in progress may finish when Sail stops |
SAIL_UPSTREAM_IDLE_TIMEOUT_SECS | 120 | How long Sail waits on a silent Nexus or identity provider |
For the Compose file
Section titled “For the Compose file”These live in .env and are read by compose.yaml, not by Sail itself.
| Setting | What it does |
|---|---|
SAIL_IMAGE | The Sail image and version to run |
SAIL_DATABASE_PASSWORD | The bundled Postgres’s password. Hex characters only. |
SAIL_DOMAIN | Sail’s domain, for the bundled Caddy |
SAIL_SANDBOX_DOMAIN | The page sandbox’s domain, for the bundled Caddy |
SAIL_PORT, SAIL_SANDBOX_PORT | The local ports your own proxy forwards to. Defaults 8484 and 8585. |
Trust a private certificate authority
Section titled “Trust a private certificate authority”If your identity provider or Nexus uses a certificate from your own certificate authority, give Sail a bundle with the public roots plus yours:
- Make a bundle: the standard public roots, followed by your CA certificate, in one PEM file.
- Mount it into the container, and point
SSL_CERT_FILEat it:
services: sail: environment: SSL_CERT_FILE: /run/secrets/ca_bundle secrets: - ca_bundle
secrets: ca_bundle: file: ./secrets/ca-bundle.pemSail ignores HTTP_PROXY and HTTPS_PROXY on purpose. It talks to your identity provider and Nexus directly.
Use your own Postgres
Section titled “Use your own Postgres”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.
Health checks
Section titled “Health checks”| Check | Answers |
|---|---|
GET /healthz | Is Sail running? |
GET /readyz | Is 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/readyzMetrics
Section titled “Metrics”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.
| Metric | What it tells you |
|---|---|
sail_http_requests_total, sail_http_request_duration_seconds | Traffic and response times |
sail_runs_active, sail_runs_total | Replies being written now, and in total |
sail_run_time_to_first_token_seconds | How long people wait for a reply to start |
sail_run_pre_upstream_seconds | Sail’s own time before it calls the model |
docker compose logs -f sailLogs 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.
The sail command
Section titled “The sail command”Run these inside the container with docker compose exec sail sail <command>.
| Command | What it does |
|---|---|
sail admin recover | Prints a one-time link, valid for an hour, that makes whoever signs in with it an owner |
sail migrate | Updates the database, then exits |
sail healthcheck | Exits 0 when Sail is healthy. Docker uses it for the container’s health. |
sail keygen | Prints a new random secret key |
sail --version | Prints Sail’s version |