Production with Compose
The four-service Compose deployment — Postgres, object storage, a one-shot migration job and the app — plus TLS, external databases, and the credential trap that breaks attachment uploads.
The all-in-one image is one container's lifecycle for everything. That is the right trade for a trial and the wrong one for production: you cannot restart the app without restarting the database, and you cannot scale, back up, or upgrade the pieces independently.
The Compose deployment splits it into four:
| Service | What it is | Notes |
|---|---|---|
postgres | Postgres 16 | Its own named volume |
seaweedfs | Object storage for attachments | Apache-2.0 licensed, S3-compatible |
migrate | One-shot migration job | Runs to completion, then exits |
app | Busabase itself | Waits for all three above |
Why migrations are their own service
migrate runs once and exits; app declares condition: service_completed_successfully on it. This matters as soon as you run more than one app replica: if each replica ran migrations at start-up, they would race, and the loser fails in a way that looks like a corrupt schema rather than a lock conflict.
Setting it up
git clone https://github.com/busabase/busabase-premium.git
cd busabase-premium/compose
./init.sh
BUSABASE_IMAGE=busabase/busabase-premium:latest docker compose up -dRun init.sh rather than editing .env by hand. The S3 credentials appear in two places — .env for the app and seaweed-s3.json for the storage service — and they must match. Filling them in manually and missing one is the single most common self-inflicted failure here, and its symptom is misleading: the app starts perfectly, signs you in perfectly, and then every attachment upload fails.
init.sh refuses to overwrite an existing .env. That is deliberate — regenerating credentials against a database that already has data locks you out of it.
TLS and reverse proxy
Nothing in the Compose file terminates TLS. Put your own proxy in front of the app port and set APP_URL to the address users actually type:
server {
listen 443 ssl;
server_name busabase.company.internal;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Busabase streams agent output and uses websockets for live updates.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}
client_max_body_size 100m;
}proxy_buffering off and the Upgrade headers are not optional. With buffering on, agent responses arrive in one lump at the end of the turn instead of streaming, which reads as "the agent hung". client_max_body_size must be at least as large as your largest attachment, or uploads fail at the proxy before Busabase ever sees them.
APP_URL has to match the public address exactly, including scheme and port. Sign-in cookies are issued against it, so a mismatch produces a sign-in that appears to succeed and then bounces straight back to the login page.
Using your own Postgres or S3
Both services in the Compose file exist for convenience, not necessity. To use infrastructure you already operate, point the app at it and remove the local service:
PG_DATABASE_URL=postgresql://user:password@your-host:5432/busabase
STORAGE_URL=minio://ACCESS_KEY:SECRET_KEY@your-s3-host:9000/bucket?auto_create=true&ssl=falseStorage is configured as one URL, not a set of separate variables. The minio://
scheme is an internal tag meaning "S3, path-style addressing, no TLS" — it
describes the protocol, not the vendor, and is correct for SeaweedFS, MinIO and
anything else S3-compatible. Use ssl=true and drop the port for a TLS
endpoint.
If you do this, drop postgres / seaweedfs from depends_on too, or Compose will wait forever for a service it is no longer starting. Keep migrate — it still has to run against whichever database you chose.
Any S3-compatible store works. If yours is behind a proxy that rewrites or strips headers, see the checksum note in Troubleshooting.
Next
Quickstart
Install Busabase on your own server with one command, check it actually worked, and activate your licence — including on a network with no internet access.
Kubernetes (Helm)
Install Busabase Premium with Helm — what the chart does, the two values that break attachments and sign-in when they are wrong, and when to bring your own Postgres and S3.