Some checks failed
CI / Unit & Component Tests (push) Failing after 7m31s
CI / OCR Service Tests (push) Successful in 49s
CI / Backend Unit Tests (push) Failing after 3m30s
CI / Unit & Component Tests (pull_request) Failing after 6m55s
CI / OCR Service Tests (pull_request) Successful in 51s
CI / Backend Unit Tests (pull_request) Failing after 3m31s
- docs/infrastructure/production-compose.md: trimmed to VPS sizing, cost breakdown, and Hetzner ecosystem rationale. The inline compose spec (overlay + Hetzner OBS in prod) is retired; the live file is now docker-compose.prod.yml at the repo root and the Caddyfile lives at infra/caddy/Caddyfile. Observability stack is called out as a not-yet-deployed gap (issue #498). - docs/architecture/c4/l2-containers.puml: adds Caddy as a named reverse-proxy container with the two port paths and notes the archiv-app service-account split on MinIO access. Refs #497. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
71 lines
3.4 KiB
Markdown
71 lines
3.4 KiB
Markdown
# Production Docker Compose & Infrastructure
|
||
|
||
This document covers VPS sizing, monthly cost, and the Hetzner ecosystem rationale. The compose file and Caddyfile that previously lived inline in this doc are now committed to the repo root.
|
||
|
||
> **Where to find the live files (after #497)**
|
||
> - Production compose: [`docker-compose.prod.yml`](../../docker-compose.prod.yml) (standalone, not an overlay)
|
||
> - Caddyfile: [`infra/caddy/Caddyfile`](../../infra/caddy/Caddyfile)
|
||
> - Deploy workflows: [`.gitea/workflows/nightly.yml`](../../.gitea/workflows/nightly.yml) and [`.gitea/workflows/release.yml`](../../.gitea/workflows/release.yml)
|
||
> - Bootstrap checklist, secrets, rollback procedure: [`docs/DEPLOYMENT.md`](../DEPLOYMENT.md)
|
||
|
||
The original spec in this doc proposed an overlay pattern (`docker compose -f docker-compose.yml -f docker-compose.prod.yml`) with MinIO disabled in production in favour of Hetzner Object Storage. That approach was retired in #497 in favour of a standalone prod compose that keeps MinIO self-hosted on the VPS. The Hetzner OBS migration is tracked as a future follow-up; the swap is three env vars + `mc mirror` once we decide to do it.
|
||
|
||
---
|
||
|
||
## Observability stack — not yet deployed
|
||
|
||
Prometheus, Loki, Grafana, Alertmanager, Uptime Kuma, GlitchTip and ntfy are **not** part of the production deployment that #497 landed. They are tracked as follow-up issue #498.
|
||
|
||
When that lands the observability containers will join `docker-compose.prod.yml` under a dedicated profile so they can be operated alongside the application stack without affecting the application containers' restart cycle.
|
||
|
||
---
|
||
|
||
## VPS Sizing Recommendations
|
||
|
||
### Recommended: Hetzner CX32
|
||
|
||
**Specs**: 4 vCPU, 8 GB RAM, 80 GB SSD · **Cost**: 17 EUR/mo
|
||
|
||
Sufficient for the application stack (Postgres, MinIO, OCR with `mem_limit: 12g`, backend, frontend, Caddy) on a CX32 today. Once the observability stack lands (Prometheus/Loki/Grafana/Alertmanager add ~2 GB) consider a CX42.
|
||
|
||
### When to Upgrade: Hetzner CX42
|
||
|
||
**Specs**: 8 vCPU, 16 GB RAM · **Cost**: 29 EUR/mo
|
||
|
||
Upgrade when:
|
||
- Observability stack adds memory pressure (Loki + Grafana with >30 days retention)
|
||
- OCR throughput needs scaling beyond a single-node Surya/Kraken setup
|
||
- Real user load profiled in Grafana shows response-time degradation
|
||
|
||
Never upgrade the VPS tier before profiling — most perceived performance issues are application bugs, not resource constraints.
|
||
|
||
---
|
||
|
||
## Monthly Cost Breakdown (production v1)
|
||
|
||
| Service | Cost |
|
||
|---|---|
|
||
| Hetzner CX32 VPS | 17.00 EUR |
|
||
| Hetzner DNS | 0.00 EUR |
|
||
| Hetzner SMTP relay | ~1.00 EUR |
|
||
| **Total** | **~18 EUR/mo** |
|
||
|
||
MinIO data lives on the VPS disk (no Object Storage line item yet). The Hetzner OBS migration would add ~5 EUR/mo at ~200 GB.
|
||
|
||
Equivalent SaaS stack: 200–300 EUR/mo.
|
||
|
||
---
|
||
|
||
## Hetzner Ecosystem Rationale
|
||
|
||
Everything possible runs on Hetzner. One provider, one bill, GDPR-compliant by default (German company, EU data centres).
|
||
|
||
| Service | Use today |
|
||
|---|---|
|
||
| **VPS (Cloud Servers)** | The whole application stack |
|
||
| **DNS** | Free, supports A/AAAA/CNAME/MX/TXT, API-accessible for Caddy ACME |
|
||
| **Firewall** | Network-level firewall (in addition to host `ufw`) |
|
||
| **Snapshots** | Quick VPS rollback after a bad deploy (0.013 EUR/GB/mo) |
|
||
| **SMTP relay** | Transactional email from `noreply@raddatz.cloud` |
|
||
| **Object Storage** | Not used today — MinIO stays on-VPS. Available when we decide to migrate |
|