--- title: "Caddy Reverse Proxy Config" description: "Caddy configuration reference replacing Nginx Proxy Manager on 10.10.0.16. Documents all 22 proxied services (public and internal-only), DNS-01 wildcard certs via Cloudflare, feature comparison with NPM, and management commands." type: reference domain: server-configs tags: [caddy, reverse-proxy, cloudflare, dns-01, wildcard-cert, docker, caddyfile] --- # Caddy Reverse Proxy - NPM Replacement Caddy configuration to replace Nginx Proxy Manager (NPM) on `10.10.0.16` for the manticorum.com homelab. ## Why Caddy - **Single config file** instead of a web UI + SQLite database - **Automatic HTTPS** with built-in Let's Encrypt and zero-downtime renewal - **Wildcard cert via DNS-01** replaces 22 individual HTTP-01 certs - **HTTP/3 (QUIC)** support out of the box - **WebSocket proxying** works automatically without per-host toggles - **Git-friendly** - the entire proxy config is a single version-controlled file ## Architecture ``` Clients -> Pi-hole DNS (10.10.0.16) -> Caddy (10.10.0.16:443) -> Backend services ``` Caddy replaces NPM in the same position. Pi-hole sync script updated to parse the Caddyfile instead of NPM's SQLite database. ## Files | File | Purpose | |------|---------| | `Caddyfile` | Main reverse proxy configuration (all 22 proxy hosts) | | `docker-compose.yml` | Container deployment | | `Dockerfile` | Custom Caddy build with Cloudflare DNS plugin | | `.env.example` | Required environment variables | | `scripts/caddy-pihole-sync.sh` | Pi-hole DNS sync (replaces npm-pihole-sync.sh) | ## Proxied Services ### Public (no IP restriction) | Domain | Backend | Notes | |--------|---------|-------| | sbadev.manticorum.com | 10.10.0.33:801 | CORS header added | | sbanews.manticorum.com | 10.10.0.88:2368 | Ghost blog | | pddev.manticorum.com | 10.10.0.42:813 | Paper Dynasty dev | | foundry.manticorum.com | 10.10.0.223:30000 | Foundry VTT | | pds.manticorum.com | 10.10.0.42:810 | PD staging | | n8n.manticorum.com | 10.10.0.210:5678 | 300s timeouts | | gameplay-demo.manticorum.com | 10.0.0.206:3000 | | | gameplay-api-demo.manticorum.com | 10.0.0.206:8000 | | | memos.manticorum.com | 10.10.0.222:5230 | | | notes.manticorum.com | 10.10.0.222:8000 | NoteDiscovery | | vagabond.manticorum.com | 10.10.0.223:30000 | Foundry VTT alt | | pocket.manticorum.com | 10.0.0.233:80 | | | git.manticorum.com | 10.10.0.225:3000 | Gitea | | omnitools.manticorum.com | 10.10.0.210:8080 | | | termix.manticorum.com | 10.10.0.210:8180 | | | status.manticorum.com | 10.10.0.227:3001 | Uptime Kuma | | jellyfin.manticorum.com | 10.10.0.226:8096 | | ### Internal Only (10.0.0.0/23, 10.10.0.0/24, home IP) | Domain | Backend | |--------|---------| | radarr.manticorum.com | 10.10.0.221:7878 | | sonarr.manticorum.com | 10.10.0.221:8989 | | jellyseer.manticorum.com | 10.10.0.221:5055 | | openclaw.manticorum.com | 10.10.0.224:18789 | ## What Changed from NPM | Feature | NPM | Caddy | |---------|-----|-------| | SSL certs | 22 individual LE certs (HTTP-01) | 1 wildcard cert (DNS-01 via Cloudflare) | | WebSocket | Per-host toggle | Automatic | | HTTP/2 | Per-host toggle | Always on | | HTTP/3 | Not supported | Built-in | | HSTS | Per-host toggle | Automatic with HTTPS | | Config format | SQLite DB + web UI | Caddyfile (text) | | Admin panel | Port 81 web UI | SSH + text editor / Caddy API on :2019 | | "Block exploits" | Built-in toggle | Rely on Cloudflare WAF | | Real IP from CF | Manual nginx.conf edit | `trusted_proxies` in global block | | Pi-hole sync | Scrapes SQLite DB | Parses Caddyfile | ## Management ```bash # SSH to host ssh pihole # Validate config docker exec caddy caddy validate --config /etc/caddy/Caddyfile # Reload after editing (zero downtime) docker exec caddy caddy reload --config /etc/caddy/Caddyfile # View logs docker logs caddy -f # Check cert status docker exec caddy caddy list-modules # verify cloudflare module loaded curl -s localhost:2019/config/ | jq . # full runtime config via API # Rebuild container (after Dockerfile changes) cd ~/caddy && docker compose up -d --build ```