Docker Compose Installation
Deploy Broch on any Linux host with Docker. Works on any cloud VM, on-premises server, or bare metal — the most portable option.
Prerequisites
Section titled “Prerequisites”Complete these steps before proceeding:
- Docker Engine 24+ with Compose V2 installed
- Wildcard domain & DNS configured
- TLS certificate approach decided — Caddy automatic or bring your own
- Identity provider app registration created
- License key obtained
Step 1: Get the Files
Section titled “Step 1: Get the Files”Download the Docker Compose configuration and environment template:
curl -O https://raw.githubusercontent.com/broch-io/broch/main/deploy/docker-compose/docker-compose.ymlcurl -O https://raw.githubusercontent.com/broch-io/broch/main/deploy/docker-compose/.env.templatecp .env.template .envStep 2: Configure
Section titled “Step 2: Configure”Edit .env and set the required values:
# License key from BrochBROCH_LICENSE=XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX
# Your wildcard hostname (e.g. tunnels.company.com)API__WILDCARDHOSTNAME=tunnels.company.com
# Admin email address
# Database password (embedded PostgreSQL)POSTGRES_PASSWORD=a-strong-random-password
# Authentication provider (AzureAd, EntraExternalId, Auth0, or Okta)AUTHENTICATION__PROVIDER=AzureAdAUTHENTICATION__CLIENTID=<client-id>AUTHENTICATION__CLIENTSECRET=<client-secret>AUTHENTICATION__ADMINROLES=Admin
# Azure AD specific:AUTHENTICATION__TENANTID=<tenant-id>See Environment Variables for a complete reference.
Step 3: Configure TLS
Section titled “Step 3: Configure TLS”Choose one approach.
Option A — Caddy (automatic, recommended)
Section titled “Option A — Caddy (automatic, recommended)”Caddy obtains and renews the wildcard certificate automatically via ACME DNS-01. No manual certificate management.
Set these additional values in .env:
# DNS provider for automatic TLS (cloudflare or route53)DNS_PROVIDER=cloudflareDNS_API_TOKEN=your-dns-provider-api-tokenThen start with the Caddy override:
docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -dOption B — Bring your own certificate
Section titled “Option B — Bring your own certificate”Broch does not terminate TLS itself — it requires an ingress (reverse proxy) in front of it. The included docker-compose.yml ships with nginx for this purpose, but you can substitute Caddy in static-cert mode, Traefik, or any other reverse proxy that can terminate TLS and forward to broch-server:8080.
Place your wildcard certificate and private key in PEM format:
mkdir -p certscp /path/to/fullchain.pem certs/cert.pemcp /path/to/privkey.pem certs/key.pemThe included nginx configuration mounts certs/ automatically and handles WebSocket proxying. If you bring your own ingress, ensure it forwards Upgrade and Connection headers for WebSocket support.
Step 4: Start
Section titled “Step 4: Start”If you chose Option A (Caddy):
docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -dIf you chose Option B (BYO cert):
docker compose up -dStep 5: Verify
Section titled “Step 5: Verify”Check server health:
curl https://tunnels.company.com/healthz # liveness — 200 if runningcurl https://tunnels.company.com/health/ready # readiness — 200 after license + auth loadsThe readiness endpoint returns 503 until the server has loaded its license token and authentication configuration. This typically takes 10–30 seconds on first boot (license activation call to Broch). On subsequent restarts the token is loaded from the database immediately.
Using an External Database
Section titled “Using an External Database”For managed databases (RDS, Azure Flexible Server, etc.), see Database, then start with the external DB override:
docker compose -f docker-compose.yml -f docker-compose.external-db.yml up -dFirewall Requirements
Section titled “Firewall Requirements”| Port | Required for |
|---|---|
| 80 | HTTP → HTTPS redirect |
| 443 | HTTPS API, tunnel proxy, WebSocket transport |
Upgrading
Section titled “Upgrading”# Set IMAGE_TAG in .env to the new versiondocker compose pulldocker compose up -dDatabase migrations run automatically on startup. Active tunnel connections drop on restart — CLI clients reconnect automatically.
Backup (Embedded PostgreSQL)
Section titled “Backup (Embedded PostgreSQL)”docker compose exec postgres pg_dump -U broch brochdb > backup-$(date +%Y%m%d).sqlSchedule this to run daily and store backups off-site. Before upgrading, take a backup so you can roll back if needed.
Capacity
Section titled “Capacity”From load testing on 0.5 vCPU / 1 GB RAM:
| Users | Minimum vCPU | Minimum RAM |
|---|---|---|
| Up to 100 | 0.5 | 1 GB |
| 100–300 | 1 | 2 GB |
| 300+ | 2 | 4 GB |
Troubleshooting
Section titled “Troubleshooting”Health check returns 503
Section titled “Health check returns 503”The server hasn’t loaded its license or auth configuration yet. Check logs:
docker compose logs serverCommon causes: missing or invalid BROCH_LICENSE, incorrect auth provider settings, or the server can’t reach the Broch central server for license activation.
Tunnels won’t connect
Section titled “Tunnels won’t connect”Verify firewall allows inbound traffic on ports 80 and 443. Check that the wildcard DNS record resolves correctly.
Database connection fails
Section titled “Database connection fails”Verify POSTGRES_PASSWORD in .env matches between the postgres and server services.