# open-isms self-host configuration. Save as `.env` next to compose.yaml. # # Everything above "Optional" has to be filled in before the stack will start. # Full walkthrough: docs/self-hosting.md # -------------------------------------------------------------------------- # Version # -------------------------------------------------------------------------- # `stable` follows the current release. Pin an exact version (e.g. 0.2.8) if # you would rather decide when to move. This is also how you roll back: set # the previous version here and run `docker compose up -d`. OPEN_ISMS_VERSION=stable # The revision of compose.yaml you are running. The app compares this with # what the release expects and tells you when an update also needs a change # to that file. Do not edit by hand — update it when you update the file. COMPOSE_REVISION=1 # Which optional services run. Comma-separated, no spaces. # minio bundled object store (leave out if you use real S3) # proxy Caddy on 443 with automatic HTTPS # updater the in-app update button # backup scheduled offsite backups # # Add `proxy` once your domain's DNS points at this server. It obtains real # certificates on first start, so turning it on before then fails the # certificate order rather than serving anything. COMPOSE_PROFILES=minio,backup # -------------------------------------------------------------------------- # Required # -------------------------------------------------------------------------- POSTGRES_PASSWORD= # openssl rand -base64 32 AUTH_SECRET= # openssl rand -hex 32 ERASURE_EMAIL_HASH_SALT= # The address your users actually type, including https://. AUTH_URL=https://isms.example.com NEXT_PUBLIC_APP_URL=https://isms.example.com # Nobody can finish registering without working email: sign-up verifies the # address with a one-time code. A Resend account with a verified sending # domain is a prerequisite for the first login, not an optional extra. RESEND_API_KEY= RESEND_FROM_EMAIL= # -------------------------------------------------------------------------- # Proxy profile # -------------------------------------------------------------------------- APP_DOMAIN=isms.example.com # Only with the bundled MinIO. Presigned upload URLs are signed for exactly # this host, so it has to be reachable by your users' browsers. STORAGE_DOMAIN=storage.example.com # -------------------------------------------------------------------------- # Storage # -------------------------------------------------------------------------- # Bundled MinIO: keep the minio profile on and set these three. AWS_S3_BUCKET=evidence AWS_ACCESS_KEY_ID=openisms # at least 8 characters AWS_SECRET_ACCESS_KEY= # exactly 32 bytes, base64: openssl rand -base64 32 MINIO_KMS_KEY= # The address the browser uses, and the one the server uses. Different on # purpose with bundled MinIO; identical on real S3 (leave the internal one # empty there). # # Defaults to the bundled MinIO as published by the compose file, so evidence # uploads work on a fresh install with nothing to fill in. Presigned URLs are # signed for exactly this host and the browser has to reach it, so the moment # you put the instance on a domain this becomes https://storage.example.com # or wherever MinIO actually answers. It is also what the app names in its # Content-Security-Policy, so a wrong value here blocks uploads in the browser # rather than failing on the server. AWS_S3_ENDPOINT=http://localhost:9000 AWS_S3_INTERNAL_ENDPOINT=http://minio:9000 # Real S3 instead: drop `minio` from COMPOSE_PROFILES, leave both endpoints # empty, and set AWS_S3_REGION plus your own bucket and credentials. AWS_S3_REGION=eu-north-1 # -------------------------------------------------------------------------- # Updates # -------------------------------------------------------------------------- # Not implemented yet: no application code reads this. Left here because the # compose file passes it through, and a variable that silently does nothing is # worse than one that says so. Checking for updates is manual for now, see # docs/updating.md. Planned: `notify` = one GET a day against the GitHub # releases API, no instance identifier and no telemetry. Unattended updates # are deliberately not planned for a compliance database. UPDATE_MODE=off # Only for the updater profile. openssl rand -hex 32 # Authenticates the app to the updater over the internal network. The updater # publishes no port and is not reachable from outside this stack. UPDATE_API_TOKEN= # -------------------------------------------------------------------------- # Backups # -------------------------------------------------------------------------- # Without a target, archives stay in a volume on this machine and die with it. # Full setup and the verified restore procedure: docs/backup.md BACKUP_S3_BUCKET= # Host only, no scheme. The scheme goes in the PROTO variable. BACKUP_S3_ENDPOINT= BACKUP_S3_ENDPOINT_PROTO=https BACKUP_S3_ACCESS_KEY= BACKUP_S3_SECRET_KEY= # Encrypts each archive with GPG before it leaves the machine. Keep this # passphrase somewhere other than this server: without it nobody can read the # archives, including you, and a passphrase stored only on the machine being # backed up protects nothing. BACKUP_PASSPHRASE= BACKUP_CRON=0 3 * * * BACKUP_RETENTION_DAYS=30 # Optional shoutrrr URL, notified only when a backup fails. BACKUP_NOTIFICATION_URL= # -------------------------------------------------------------------------- # Optional # -------------------------------------------------------------------------- # Each of these degrades exactly one feature if left empty. GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= # AI prefill in the intake forms XAI_API_KEY= # company lookup in the applicability wizard RAPIDAPI_KEY= # bearer token for the deadline and reminder cron endpoints CRON_SECRET= SUPPORT_EMAIL= # Cross-tenant admin tier. Most single-company installs leave this empty. PLATFORM_ADMIN_EMAILS= # Set only once you are HTTPS-only: turns on HSTS with a two-year max-age. CSP_UPGRADE_INSECURE= # -------------------------------------------------------------------------- # Network bindings # -------------------------------------------------------------------------- # Loopback by default so nothing is exposed by accident. Under the proxy # profile leave these alone. Publishing on 0.0.0.0 bypasses ufw — Docker # writes its iptables rules ahead of it — so use a provider-level firewall. APP_BIND=127.0.0.1 APP_PORT=3026 POSTGRES_BIND=127.0.0.1 POSTGRES_PORT=5432 MINIO_BIND=127.0.0.1 MINIO_PORT=9000