Skip to main content

Runtime configuration

TOW uses two runtime configuration layers:

  • tow.yaml for non-secret application runtime settings.
  • .env for secrets only.

The backend reads both. Environment variables can still override matching YAML fields, but use that as a deployment escape hatch. The normal operating model is: put server configuration in tow.yaml, and put secret material in .env or your platform secret manager.

For the AI queue, periodic operating runner, and background job behavior controlled by these settings, see Background AI system.

.env

Start from the example file:

cp .env.example .env

The .env file should contain secrets and, when using the optional authentik Compose profile, bootstrap values needed before the app can read tow.yaml:

VariablePurpose
APP_SECRETSession and OIDC state signing secret. Generate a deployment-specific random value, for example with openssl rand -base64 48. The default placeholder is rejected at startup.
DATABASE_URLBackend database connection string.
POSTGRES_PASSWORDDocker Postgres password when using Compose defaults.
OPENAI_API_KEYEnables OpenAI model and embedding calls.
EXA_API_KEYEnables optional web search tools.
SMTP_USERNAME, SMTP_PASSWORDOptional SMTP credentials.
OIDC_CLIENT_SECRETRequired when auth.mode: oidc; the OIDC client secret from authentik or the chosen identity provider.
PUBLIC_APP_URLOptional authentik bootstrap input; app runtime should still set runtime.public_app_url in tow.yaml.
AUTHENTIK_BOOTSTRAP_TOKENOptional authentik bootstrap API token used by the Compose one-shot setup job.
AUTHENTIK_BOOTSTRAP_PASSWORDOptional initial authentik admin password for the bundled authentik profile.
AUTHENTIK_BOOTSTRAP_EMAILOptional initial authentik admin email for the bundled authentik profile.

Bootstrap and deployment wiring such as published ports, docs URL, proxy target, and TOW_CONFIG_PATH belong in Docker Compose, your process manager, or your platform configuration. Authentik bootstrap values are present in .env.example so the optional Compose profile can be started consistently, but production operators should still treat token, password, and secret values as secrets.

warning

Never commit production .env files. They contain secrets.

tow.yaml

Create a local YAML file from the example when running outside Docker:

cp config/tow.example.yaml config/tow.yaml

In Docker, TOW_CONFIG_PATH is set to:

/app/data/tow.yaml

The example YAML includes:

runtime:
app_name: TOW
backend_cors_origins:
- http://localhost:3000
- http://localhost:8000

ai:
openai_reasoning_model: gpt-5.2
openai_fast_model: gpt-5.2
openai_embedding_model: text-embedding-3-small
embedding_dim: 1536
processes: {}

security:
session_cookie_name: tow_session
session_cookie_secure: false
session_max_age_seconds: 2592000

auth:
mode: builtin
oidc:
issuer:
client_id:
scopes:
- openid
- profile
- email
username_claim: preferred_username
email_claim: email
groups_claim: groups
require_email_verified: false

email:
transport: console
from_address: TOW <noreply@example.com>
reply_to:
smtp:
host:
port: 587
tls_mode: starttls

Server admins can edit YAML-backed values from Admin, Server Settings. Those edits write to the configured YAML file.

Email transport, SMTP host, SMTP port, sender address, upload limits, session policy, authentication mode, OIDC issuer and claim names, AI model names, Agent baseline, CORS origins, and background job cadence all belong here.

Authentication mode

TOW supports two authentication modes:

ModeBehavior
builtinLocal email/password login and invite-based registration. This is the default for simple installs.
oidcBuilt-in login and registration are disabled. Users authenticate through authentik or another OIDC provider, then TOW creates its normal signed session cookie.

Choose the mode before first boot. In builtin mode, the first registered user becomes the server admin and organisation owner. In oidc mode, the first successful OIDC login becomes the server admin and organisation owner. Later OIDC users must either have an existing linked identity or use an invite whose email matches the provider email claim.

Public self-service signup is opt-in. When auth.signup.enabled is true, users can create accounts from /login without an invite. TOW sends its own email verification link before creating a browser session. After verification, TOW first applies a valid invite, then joins exactly one organisation with a verified matching email domain, and otherwise creates a new workspace for the user.

Public signup requires a working runtime.public_app_url and email delivery. For OIDC/authentik mode, TOW still sends its own verification email even when the identity provider includes an email_verified claim. If new users do not already have identity-provider accounts, configure auth.signup.oidc_start_url to an authentik enrollment flow, for example https://auth.example.com/if/flow/tow-public-enrollment/. The bundled authentik bootstrap creates that flow when SIGNUP_ENABLED=true is present in the bootstrap job environment. auth.signup.enabled: true in tow.yaml enables TOW at runtime, but the one-off authentik-bootstrap container does not read tow.yaml; put SIGNUP_ENABLED=true in .env or pass it to the bootstrap command when creating/updating the Authentik flow. TOW will send unknown public-signup emails there first and pass authentik a next parameter that returns to the OIDC authorization flow.

For OIDC mode, configure these YAML values:

runtime:
public_app_url: https://tow.example.com

auth:
mode: oidc
signup:
enabled: false
oidc_start_url: https://auth.example.com/if/flow/tow-public-enrollment/
verification_token_ttl_hours: 24
resend_cooldown_seconds: 60
oidc:
issuer: https://auth.example.com/application/o/tow/
client_id: tow
scopes:
- openid
- profile
- email
username_claim: preferred_username
email_claim: email
email_verified_claim: email_verified
groups_claim: groups
require_email_verified: false
provider_logout_enabled: false

Set OIDC_CLIENT_SECRET in .env or your secret manager. OIDC mode also requires a non-default APP_SECRET of at least 32 characters. runtime.public_app_url and the OIDC issuer must use HTTPS except for localhost development; the issuer must match the OIDC discovery document exactly. For authentik, the issuer is normally the provider URL under /application/o/<slug>/. auth.oidc.provider_logout_enabled is opt-in; when enabled and the provider advertises end_session_endpoint, logging out of TOW redirects through the provider and then back to /login?logged_out=1.

TOW stores authentik/OIDC claims on the linked identity record for audit and future mapping, but it does not map provider groups to roles automatically. TOW still owns organisations, memberships, roles, permissions, and application audit behavior.

Precedence

Configuration precedence is:

PrioritySource
HighestExplicit runtime values passed by code.
HighEnvironment variables.
Medium.env values loaded by the backend process.
Lowtow.yaml.
LowestBuilt-in defaults.
warning

If a non-secret environment variable is set, the matching YAML value is ignored. This is the most common reason a Server Settings change appears to save but does not change runtime behavior after restart. Prefer removing the override and managing the value in YAML.

Restart requirements

Most runtime settings are read when the backend process starts. After changing YAML or environment values:

  1. Restart the backend.
  2. Confirm /api/health responds.
  3. Sign in and confirm expected behavior.

For Docker Compose:

docker compose restart backend

If you changed frontend build-time values such as VITE_API_BASE_URL or VITE_DOCS_URL in your deployment platform, rebuild the frontend image as well.

Production baseline

Before production use:

  • Replace the default APP_SECRET.
  • Use a strong Postgres password.
  • Set session_cookie_secure: true in tow.yaml for HTTPS.
  • Configure email delivery in tow.yaml with SMTP, file, disabled, or console transport.
  • Use a durable TOW_CONFIG_PATH in your deployment configuration.
  • Preserve /app/data or the configured upload and YAML paths.
  • Confirm VITE_DOCS_URL points to the deployed customer-facing docs, if you want the app to show the Documentation link.