Self-Hosted Installation
Run the full BuildButler stack on your own infrastructure via npm or Docker.
Run the full BuildButler stack — dashboard, API, and AI assistant — on your own infrastructure. No cloud account required.
Requirements
- Node.js 22+ (npm) or Docker
- PostgreSQL 15+ — a single PostgreSQL server is enough; BuildButler creates both required databases automatically on first run
- A BuildButler license key (
BB-XXXX-XXXX-XXXX-XXXX) — obtain one at buildbutler.dev
Install via npm
Create a .env file:
Start the server:
Open http://localhost:3000 and register your first account.
Install via Docker
If PostgreSQL is running on your local machine, use host.docker.internal instead of localhost.
Database setup
BuildButler needs two PostgreSQL databases — one for org data (builds, tests, dashboards) and one for the control plane (users, sessions, API keys). Both are created automatically on first startup.
The control database defaults to the same host as DATABASE_URL with _control appended:
DATABASE_URL | Auto-derived control DB |
|---|---|
postgresql://host/buildbutler | postgresql://host/buildbutler_control |
Set CONTROL_DATABASE_URL explicitly only if the control database needs to live on a different server.
Schema migrations also run automatically on every startup — no manual migration step needed.
Docker Compose (with PostgreSQL)
For a production setup with SSL, see Docker Compose with Caddy in the SSL Setup section below.
Configuration
Required
| Variable | Description |
|---|---|
DATABASE_URL | PostgreSQL connection string |
JWT_SECRET | Random secret for signing auth tokens — generate with openssl rand -hex 32 |
Optional
| Variable | Description |
|---|---|
CONTROL_DATABASE_URL | Control plane database. Defaults to DATABASE_URL host with _control suffix. |
BUILDBUTLER_LICENSE_KEY | License key. Without one the server runs with a 7-day grace period then restricts data ingest. |
PORT | Port to listen on (default: 3000) |
ALLOWED_ORIGINS | Comma-separated CORS origins — set to your public URL when behind a reverse proxy |
RESEND_API_KEY | Resend API key for password reset and invite emails |
LLM_ENCRYPTION_KEY | 32-char key to encrypt stored AI provider API keys — generate with openssl rand -hex 16 |
Object storage (optional)
Artifact uploads require an S3-compatible object store. If not configured, artifact endpoints return 503 but all other features work.
| Variable | Description |
|---|---|
S3_BUCKET | Bucket name |
S3_ENDPOINT | Override endpoint for MinIO, Cloudflare R2, etc. Leave unset for AWS S3. |
S3_ACCESS_KEY | Access key ID |
S3_SECRET_KEY | Secret access key |
S3_REGION | Region (default: us-east-1, use auto for R2) |
CLI flags
| Flag | Description |
|---|---|
--port <number> | Override the port |
--noauth | Disable authentication — all visitors have full admin access. For local dev or VPN-isolated installs only. |
Reverse proxy
Caddy (automatic TLS):
nginx:
Then set ALLOWED_ORIGINS=https://buildbutler.yourcompany.com.
SSL Setup
Caddy (recommended)
Caddy handles TLS automatically via Let's Encrypt — no certificate management needed.
Start Caddy and it fetches and renews the certificate automatically.
nginx + Certbot
nginx config:
Docker Compose with Caddy
A complete production setup with PostgreSQL, BuildButler, and Caddy handling TLS automatically.
docker-compose.yml:
Caddyfile:
Start everything:
Caddy fetches and renews the TLS certificate automatically. Replace buildbutler.yourcompany.com with your actual domain — it must be publicly reachable for Let's Encrypt to issue a certificate.
Using a company-issued certificate
If your organisation provides its own TLS certificate (e.g. from an internal CA or a purchased cert), you can use it with Caddy instead of Let's Encrypt.
Mount the certificate files into the Caddy container and reference them in the Caddyfile:
docker-compose.yml — add a volume mount for your certs:
Place your certificate files in a certs/ folder next to docker-compose.yml:
Caddyfile — point to the certificate files:
If you are not using Docker and running Caddy directly on the host, the paths are local filesystem paths:
When tls is set to explicit file paths, Caddy uses those files and does not contact Let's Encrypt. Certificate renewal is your responsibility — replace the files and run caddy reload (or restart the container) when the cert is renewed.
Upgrading
npm:
Docker:
Migrations run automatically on startup. BuildButler displays an upgrade banner in the sidebar when a newer version is available.
AI assistant
The AI assistant requires an external LLM provider key.
- Go to Settings → AI
- Choose your provider: OpenAI, Anthropic, or Google
- Enter your API key and select a model
Recommended models:
| Provider | Model |
|---|---|
| Anthropic | claude-sonnet-4-6 |
| OpenAI | gpt-4o-mini |
gemini-2.0-flash |
Set LLM_ENCRYPTION_KEY before saving any API keys — without it keys are stored in plaintext.