Skip to the content

Documentation

Settings reference

Every setting a self-hosted Docustay reads, with its default and whether it is required.

Every setting you can give a self-hosted Docustay, as environment variables in .env (the compose file reads it). ./init.sh fills in the secrets. Anything not listed in the first tables is internal or belongs to the hosted service and should stay unset.

Secrets (init.sh makes them)

Setting Required Default What it does
KEYSTONE_DB_PASSWORD yes (generated) The password of the bundled Postgres. Used by compose to build the database URL.
KEYSTONE_TOKEN_PEPPER yes (generated) A secret mixed into every API key and session digest. Changing it signs everyone out and invalidates every API key.
KEYSTONE_LOCAL_AUTH_SECRET yes (generated) Signs the built-in sign-in tokens. Changing it signs everyone out.
KEYSTONE_SETUP_TOKEN first run (generated) The one-time key that lets you create the owner account at /setup. Unused after setup.
KEYSTONE_MASTER_KEY yes (production) (generated) Wraps the keys that seal stored secrets (webhook secrets, SMTP passwords, two-step secrets). Back it up with the database: without it sealed secrets cannot be opened.

Where things are

Setting Required Default What it does
KEYSTONE_PUBLIC_URL yes behind a domain http://localhost:8080 The address people open Docustay at, without a path. Every signing link, reset link and email starts with it.
KEYSTONE_DOCUSTAY_APP_URL no = KEYSTONE_PUBLIC_URL The address of the signed-in app, when it differs from the signing address.
KEYSTONE_DOCUSTAY_SIGN_URL no = KEYSTONE_PUBLIC_URL The address signing links start with.
DOCUSTAY_PORT no 8080 The port on this machine the web app listens on.
PORT no 8080 The port the API process listens on inside its container.
KEYSTONE_TRUSTED_PROXY_HOPS behind a proxy 0 How many reverse proxies sit in front. With 0 every visitor looks like the proxy and shares one rate limit; set 1 behind one proxy.

Database and files

Setting Required Default What it does
KEYSTONE_DB_SUPERUSER_URL yes (compose) Connection string the migration runner uses. It creates the application roles on first run.
KEYSTONE_DATABASE_URL no (derived) Connection string for the application role, when you run the database yourself.
KEYSTONE_DB_SSL no on Set to off for a database in the same private network without TLS (the bundled compose does).
KEYSTONE_PG_POOL_MAX no 10 Largest number of database connections the API keeps.
KEYSTONE_S3_ENDPOINT yes (compose) Address of the S3-compatible store that keeps signed PDFs.
KEYSTONE_S3_BUCKET yes docustay The bucket (created for you by the bundled store).
KEYSTONE_S3_ACCESS_KEY_ID yes (generated) Access key for the file store.
KEYSTONE_S3_SECRET_ACCESS_KEY yes (generated) Secret key for the file store.
KEYSTONE_S3_REGION no us-east-1 Region name some S3 providers require.
KEYSTONE_GOTENBERG_URL yes (compose) Address of the PDF converter (Gotenberg) that prints documents.

Email

Setting Required Default What it does
RESEND_API_KEY one of Resend or SMTP Your own Resend API key. Leave empty to use your own SMTP server (Settings → Email).
KEYSTONE_MAIL_SENDER no The From address used until you verify your own domain.
KEYSTONE_MAIL_DAILY_LIMIT no (none) Hard cap on emails sent per day by this install.
KEYSTONE_EMAIL_ALLOWLIST no (off) Comma list of addresses/domains mail may go to. Everything else is dropped. Use it on a test install.

Sign-in

Setting Required Default What it does
KEYSTONE_LOCAL_AUTH yes (self-host) 1 Uses the built-in sign-in (email and password). Firebase is for the hosted service only.
KEYSTONE_PASSKEYS no off Set to 1 to let people sign in with passkeys. Needs KEYSTONE_PASSKEY_ORIGINS.
KEYSTONE_PASSKEY_ORIGINS with passkeys = KEYSTONE_DOCUSTAY_APP_URL Comma list of web addresses a passkey may be used from. A passkey is tied to the address's host name.
DOCUSTAY_OIDC_ISSUER no (off) The address of your OpenID Connect provider (Keycloak, Authentik, Entra, Okta…), for example https://sso.example.com/realms/main. Setting this, the client id and the client secret turns on single sign-on.
DOCUSTAY_OIDC_CLIENT_ID no (none) The client id you made for Docustay at your provider.
DOCUSTAY_OIDC_CLIENT_SECRET no (none) The client secret for that client. Keep it as private as the other secrets in .env.
DOCUSTAY_OIDC_LABEL no your identity provider The name on the sign-in button: “Sign in with …”.
DOCUSTAY_OIDC_SCOPES no openid email profile What to ask the provider for. It must include openid and email.

Signing certificate and timestamps

Setting Required Default What it does
KEYSTONE_SIGNING_CERT_PEM no (made at first run) The certificate that seals finished documents. By default Docustay makes one for this install; set your own to use a certificate from a trusted authority.
KEYSTONE_SIGNING_CERT_PATH no Path to a PEM file instead of the value itself.
DOCUMENT_TSA_URL no (none) A trusted timestamp authority; when set, finished documents carry a trusted timestamp.

Operations

Setting Required Default What it does
KEYSTONE_METRICS_TOKEN no (metrics off) Turns on GET /metrics (Prometheus). Callers send Authorization: Bearer . At least 16 characters.
DOCUSTAY_TELEMETRY no on off stops the one anonymous daily usage ping (a random install id, the version, five counts).
DOCUSTAY_LICENSE_KEY no A Pro licence key. With it the worker checks the licence daily and unlocks Pro features.
KEYSTONE_ENVIRONMENT no production staging for a test install: live Stripe keys are refused and email goes only to the allowlist.
KEYSTONE_ALERT_EMAIL no Where the install sends operational alerts (a failing backup, a paused sender).
KEYSTONE_SELF_HOST set by compose 1 Marks this as a self-hosted install: hides hosted-only screens such as billing.

Payments (optional)

Setting Required Default What it does
KEYSTONE_STRIPE_SECRET_KEY for payment fields Your own Stripe secret key for collecting payments at signing.
KEYSTONE_STRIPE_PUBLISHABLE_KEY for payment fields The matching publishable key.
KEYSTONE_STRIPE_CHARGES_ENABLED no off A safety switch: live charges stay refused until this is on.

AI (optional)

Setting Required Default What it does
ANTHROPIC_API_KEY for AI features Your own Anthropic key. Without it the AI drafting, reviewing and chat features are hidden.
KEYSTONE_AI_DEFAULT_MODEL no (a current model) The model used for drafting.
KEYSTONE_AI_REVIEW_MODEL no (a current model) The model used for review passes.

Advanced settings

The code also reads the variables below. They tune limits and connections you will rarely need to change. Another 70 variables (plan prices and limits, and the hosted service's own accounts for Stripe Connect, Firebase, Cloudflare, domains and the like) belong to the hosted service only; a self-hosted install ignores them.

  • DOCUMENT_SIGNING_CERT_P12
  • DOCUMENT_SIGNING_CERT_PASSPHRASE
  • DOCUSTAY_API_KEY
  • FAULT_INJECT
  • GOOGLE_CALENDAR_API_BASE
  • GOOGLE_OAUTH_CLIENT_ID
  • GOOGLE_OAUTH_CLIENT_SECRET
  • GOOGLE_TOKEN_URL
  • KEYSTONE_APP_URL
  • KEYSTONE_DATA_DIR
  • KEYSTONE_DOCUSTAY_MAIL_SENDER
  • KEYSTONE_EMAIL_FROM
  • KEYSTONE_LIMITER_POOL_MAX
  • KEYSTONE_MAIL_ALERT_TO
  • KEYSTONE_MAIL_CAPTURE_SMTP
  • KEYSTONE_PRODUCT
  • KEYSTONE_VERSION
  • KEYSTONE_WORKER_DATABASE_URL
  • MICROSOFT_GRAPH_OAUTH_CLIENT_ID
  • MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET

An example .env

init.sh writes the secrets for you. Everything else is yours to set in the same file; a small install behind its own address needs only these lines on top of the generated ones:

KEYSTONE_PUBLIC_URL=https://sign.example.com
KEYSTONE_TRUSTED_PROXY_HOPS=1
KEYSTONE_MAIL_SENDER=Example Co <documents@example.com>
KEYSTONE_MAIL_DAILY_LIMIT=500

Apply a change by recreating the containers, then check the install is up and sees the new address:

docker compose up -d
curl -s https://sign.example.com/readyz
CtrlI