DigitalOcean Installation
Deploy Broch on a DigitalOcean Droplet with Docker Compose and embedded PostgreSQL. Caddy handles automatic wildcard TLS via DNS-01.
Status: In progress. The Terraform configuration is available in the GitHub repository.
Prerequisites
Section titled “Prerequisites”Complete these steps before proceeding:
- DigitalOcean account with an API token
- SSH key registered in DigitalOcean
- Terraform 1.5+
- DNS provider API token (Cloudflare recommended; Route 53 supported) for automatic TLS
- Wildcard domain & DNS — point at the reserved IP after first apply
- Identity provider app registration created
- License key obtained
TLS Certificates
Section titled “TLS Certificates”This deployment uses Caddy with DNS-01 ACME for automatic wildcard TLS — no manual certificate management. You provide your DNS provider’s API token; Caddy handles certificate issuance and renewal.
See TLS Certificates for details.
Deploy
Section titled “Deploy”Initialize Terraform and create your variables file:
terraform init
cat > terraform.tfvars <<'EOF'do_token = "dop_v1_..."ssh_key_fingerprint = "aa:bb:cc:..."deployment_name = "broch"license_key = "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX"wildcard_hostname = "tunnels.company.com"dns_provider = "cloudflare"dns_api_token = "your-cloudflare-api-token"auth_provider = "AzureAd"auth_client_id = "your-client-id"auth_client_secret = "your-client-secret"auth_tenant_id = "your-tenant-id"auth_admin_roles = "Admin"admin_email = "[email protected]"postgres_password = "a-strong-random-password"EOF
terraform applyDownload the Terraform configuration from the Broch GitHub repository.
Post-Deployment DNS
Section titled “Post-Deployment DNS”After terraform apply, create a wildcard A record pointing to the reserved IP shown in the output:
*.tunnels.company.com → 203.0.113.42 (from terraform output)Architecture
Section titled “Architecture”DigitalOcean Droplet (Ubuntu 24.04)├── Docker Compose│ ├── caddy (automatic wildcard TLS via DNS-01)│ ├── broch (port 8080)│ └── postgres:16-alpine├── Block Storage Volume (/mnt/broch-data)│ └── postgresql/ (persistent DB data)└── Reserved IP (stable DNS target)Upgrading
Section titled “Upgrading”Update image_tag in terraform.tfvars and re-apply. PostgreSQL data is preserved on the block storage volume.
terraform apply -var="image_tag=1.2.3"Backup
Section titled “Backup”ssh root@<droplet-ip> \ "cd /opt/broch && docker compose exec -T postgres pg_dump -U broch brochdb" \ > backup-$(date +%Y%m%d).sql