When to use this vs. the Terraform module
Architecture
Everything runs as Docker containers on a single host. The nginx LB routes traffic and terminates TLS. Docker’s restart policy and systemd keep the stack running across reboots.Prerequisites
Sizing guide
ClickHouse is the memory consumer. If you run out, increase
CLICKHOUSE_MEMORY_LIMIT before resizing the VM.
Step 1: Provision the VM
Use any cloud provider or on-prem hypervisor. Example for AWS:- GCP:
e2-standard-2with 100 GB balanced persistent disk - Azure:
Standard_B2mswith 100 GB Premium SSD - Hetzner:
CPX31(4 vCPU / 8 GB, ~€15/mo) - On-prem: any Linux box meeting the specs above
Step 2: Install Docker
SSH into the VM and install Docker:Step 3: Clone and configure
.env for production. At minimum, change these:
.env:
SAML SSO, audit logs, and executive dashboards are included in the open-source distribution. See Configuration. For mounted credentials and private keys, use the documentedNAME_FILEinputs instead of placing secret contents in.env.
Step 4: Set up TLS
This guide uses the source Compose stack. Everylocalhost:80 example below refers to that stack’s nginx load balancer. Do not expose its HTTP listener directly to remote clients. For downloadable server-package bindings, see Requirements.
Option A: Caddy (simplest — automatic HTTPS)
/etc/caddy/Caddyfile:
Option B: Certbot + nginx production config
Option C: Behind a cloud load balancer
If your VM sits behind an AWS ALB, GCP HTTPS LB, or Cloudflare, terminate TLS there and proxy to port 80 on the VM. No TLS config on the VM itself.Step 5: Start the stack
Step 6: Survive reboots
Docker’srestart: unless-stopped policy (already set in docker-compose.yml) handles container restarts. To ensure Docker itself starts on boot:
Step 7: Set up automated backups
Create a backup script:Step 8: First login
Install the CLI on your local machine:Upgrades
Monitoring
Prometheus and Grafana are optional. Start the core stack with Prometheus only:http://your-server:3001 when the Grafana profile is enabled.
For basic alerting without Grafana, add a health check cron:
Security hardening
The security assurance case describes the deployment trust boundaries and residual risks. Before exposing to the internet:- Remove all
DEMO_*env vars from.env - Set a strong
SECRET_KEY - Restrict SSH access (key-only, no password auth)
- Configure a firewall (
ufw allow 80,443/tcp && ufw enable) - Set up SSO if available
- Enable automatic security updates (
sudo apt install unattended-upgrades) - Bind database ports to localhost only (already done in
docker-compose.ymlvia127.0.0.1:prefix)
Scaling up
When you outgrow a single node:Next
- Configuration — all environment variables
- Backup and restore — detailed restore procedures
- Upgrades — safe upgrade and rollback flow
- Troubleshooting — common issues

