selfhostedops-stack/caddy
Maximilian Grimm 55b2fe7646 Episode 17: updates one service at a time, a health check that asks real questions, every tag pinned
updates/health.sh: 43 checks across all services (API answers, git refs, a push
message round trip, SSO redirects and token endpoint, mesh state, backup age).
updates/update.sh: per service pull or build, snapshot, recreate, wait for the
health check, put image and data back on red and stop the run.
backup/backup.sh: online dumps for n8n, Pocket ID and tinyauth; BACKUP_TAG so
pre-update snapshots are not removed by the nightly keep-daily rule.
compose.yml and caddy/Dockerfile: exact versions instead of latest, 16, 7-alpine
and caddy:2-alpine.
2026-10-08 22:04:29 +02:00
..
Dockerfile Episode 17: updates one service at a time, a health check that asks real questions, every tag pinned 2026-10-08 22:04:29 +02:00
README.md Episode 12/13: CrowdSec next to fail2ban, and an AppSec WAF in Caddy 2026-09-16 20:34:18 +02:00

caddy/ (episode 10, extended in episode 12)

Custom Caddy image with the rate limiting plugin, the CrowdSec bouncer and the CrowdSec AppSec handler compiled in (see crowdsec/README.md).

The stock caddy:2-alpine has no rate_limit directive; it is not a runtime flag, the module must be built into the binary with xcaddy. compose.yml carries both image: and build: ./caddy, so docker compose build caddy produces selfhostedops/caddy:crowdsec locally and docker compose up -d uses it.

Do not build on a small box while the stack is running - a Go build can push a 2 GB machine into OOM and take the live services down with it. Build it elsewhere (a bigger machine, or a throwaway host) and move it over:

docker build -t selfhostedops/caddy:crowdsec ./caddy
docker save selfhostedops/caddy:crowdsec | ssh root@box docker load

Measured in episode 12: the build with all three modules took 60 s on a 12 GB build host, the image is 158 MB (the rate-limit-only image was 154 MB).

The modules are pinned to the release tag (@v0.14.1), not @main as the upstream README suggests, so a rebuild next month gives the same binary.