Configuration reference
Every environment variable the self-hosted deployment reads — what it does, what happens if you get it wrong, and whether changing it needs a restart.
The all-in-one image configures itself and needs none of this. Everything below applies to the Compose deployment, where you own .env.
Required
| Variable | Default | Restart needed | What it does |
|---|---|---|---|
BUSABASE_IMAGE | busabase/busabase-premium:latest | yes | Which image to run. Trials use the public :trial tag; licensed customers are moved to the private registry. |
APP_URL | — | yes | The address users actually type, scheme and port included. |
APP_PORT | 3000 | yes | Host port published for the app. |
POSTGRES_USER | busabase | yes | Database user. |
POSTGRES_PASSWORD | — | yes | Database password. Generate it, do not choose it. |
POSTGRES_DB | busabase | yes | Database name. |
S3_ACCESS_KEY | busabase | yes | Object-storage key. Must match seaweed-s3.json. |
S3_SECRET_KEY | — | yes | Object-storage secret. Must match seaweed-s3.json. |
S3_BUCKET | busabase | yes | Bucket name; created automatically. |
BETTER_AUTH_SECRET | — | yes | Signs session cookies. Leaking it lets anyone forge a login. |
APP_URL is the one people get wrong. Sign-in cookies are issued against it, so if it does not match what the browser shows — http vs https, a missing port, an IP instead of the hostname — signing in appears to succeed and then bounces straight back to the login page. There is no error message, because from the server's point of view nothing failed.
Optional
| Variable | Default | Restart needed | What it does |
|---|---|---|---|
IMAGE_REGISTRY | docker.io | yes | Pull the Postgres and SeaweedFS images from an internal mirror instead. |
SYSTEM_ADMIN_EMAIL | admin@example.com | yes | Which account gets the system admin console. |
SEAWEEDFS_VOLUME_LIMIT_MB | 1024 | yes | Size at which SeaweedFS rolls to a new volume file. Raise it for large attachment estates. |
Set for you
These are injected by the Compose file or the image. You do not normally set them, but knowing they exist explains behaviour you might otherwise find surprising.
| Variable | Value | Why |
|---|---|---|
BUSABASE_EDITION | self-hosted | Removes billing, the waitlist and the public marketing pages. Read once at boot — deliberately not an admin-toggleable flag, because flipping it back would re-expose the billing surfaces. |
PG_DATABASE_URL | built from the POSTGRES_* values | Point this at your own Postgres to use external infrastructure. |
STORAGE_URL | built from the S3_* values | One URL rather than separate variables. minio:// means "S3, path-style, no TLS" — the protocol, not the vendor. |
REDIS_URL | lmdb:///data/cache | An embedded LMDB cache with in-process pub/sub. A separate Redis buys nothing at single-replica scale, and Redis 7.4+ is RSALv2/SSPL, which carries redistribution constraints we would rather not pass on to you. |
Every variable here needs a restart to take effect. There is no runtime reload: the values are read at boot, which is what makes a running instance's configuration reproducible from its .env alone.
Generated, not configured
The all-in-one image generates its own Postgres password, object-storage keys and session secret on first boot and writes them to /data/.credentials with mode 600. They are not in the image, so two people pulling the same image do not share secrets.
Back that file up. It is the only copy.