Reverse Proxy¶
How traffic reaches Sartiq services — routing, SSL, and how to add new proxy entries.
Overview¶
All external traffic to Sartiq backend services goes through a Caddy reverse proxy running as a Docker container on the backend VM. Caddy handles:
- SSL termination — automatic HTTPS via Let's Encrypt, zero configuration
- Domain routing — maps subdomains to internal services
- WebSocket proxying — automatic, no extra config needed
Configuration¶
The proxy is configured via a Caddyfile in the deployment repo:
shootify-deployment/
├── GCP-Backend-staging/
│ ├── Caddyfile ← proxy routes
│ └── docker-compose.yml ← includes caddy service
├── GCP-Backend-production/
│ ├── Caddyfile
│ └── docker-compose.yml
Current Staging Routes¶
staging-api.sartiq.com {
reverse_proxy localhost:8000
}
staging-app-admin.sartiq.com {
reverse_proxy localhost:8000
}
compute-api-staging.sartiq.com {
reverse_proxy localhost:9000
}
Adding a New Proxy Entry¶
Step 1: Edit the Caddyfile¶
Open the Caddyfile for the target environment and add a new block:
If the service runs on a different machine, use its internal IP:
Step 2: Add DNS record in Cloudflare¶
In the Cloudflare dashboard for sartiq.com:
- Type: A
- Name:
my-new-service(orstaging-my-new-servicefor staging) - Content: the backend VM's static IP (from
terragrunt output backend_external_ip) - Proxy status: DNS only (grey cloud) — Caddy handles SSL, not Cloudflare
Step 3: Deploy¶
Push the Caddyfile change to main. CI/CD will SCP it to the VM and restart Caddy. SSL certificates are obtained automatically on first request.
Alternatively, deploy manually:
Caddy detects the Caddyfile change and reloads without downtime.
Common Patterns¶
Path-based routing¶
Route different paths to different backends:
Strip a path prefix¶
Forward /api/v2/* to a backend that expects requests at /:
Add response headers¶
Redirect old domain¶
Basic auth for internal tools¶
internal-tool.sartiq.com {
basic_auth {
admin $2a$14$... # bcrypt hash
}
reverse_proxy localhost:8080
}
Generate a bcrypt hash with: caddy hash-password
Docker Compose Service¶
The Caddy service in docker-compose.yml:
services:
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data # SSL certificates
- caddy-config:/config
The caddy-data volume stores SSL certificates. Do not delete this volume — it contains your Let's Encrypt account and certificates.
Troubleshooting¶
Check Caddy logs¶
Verify Caddyfile syntax¶
Force certificate renewal¶
SSL certificate not working¶
- Ensure the DNS record exists and points to the correct IP
- Ensure ports 80 and 443 are open in the GCP firewall
- Check Caddy logs for ACME errors
Related Documentation¶
- Caddy Deep Dive — How Caddy works internally, full directive reference
- Infrastructure Overview — Server fleet and network topology
- Deployment — Deployment procedures