By default, every new container/service deployment includes:
- Tag-pinned at minimum (e.g.
requarks/wiki:2.5.307, not :latest)
- TODO digest pin after first successful pull (per V00-014). Update on
every intentional version bump.
- App joins
traefik_backend for ingress (shared)
- App joins a private
*-int network for backend communication where
the backend is local to the stack (private DB sidecar). When using a
shared backend (postgres_production), traefik_backend is sufficient.
security_opt: ["no-new-privileges:true"]
read_only root filesystem where supported (TBD per service)
- Resource limits via
deploy.resources.limits (CPU + memory cap) and
reservations (CPU + memory soft-floor)
- Traefik HTTP -> HTTPS redirect router
- Let's Encrypt via the
letsencrypt certresolver
- Security headers middleware: HSTS preload, X-Frame-Options DENY,
X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin,
X-Robots-Tag for non-public services
.env next to docker-compose.yml, mode 600, owner = service operator
- Project-wide secret store:
.secrets/credentials.env (mode 600, gitignored)
- Never log or echo secrets in scripts. Sanitize stack traces.
- Single hypervisor per site, no second physical host. HA via additional
hardware is out of scope.
- All "redundancy" inside one host is virtual and does not survive host failure.
- Backups happen at the VM-image level via PBS, plus app-level dumps for
data-critical apps.
- Energy and server cost stay low.
- Non-trivial SPoFs are accepted as deliberate cost trade-offs:
- Single home pfSense
- Single RZ pfSense
- Single VPN tunnel between sites
- Single internal DNS resolver (the AD DC) — Hinweis 2026-05-04: DC mid-migration RZ → HM, target IP
10.100.100.10
- Single NAS at home