Caddy — Setup
Reverse proxy and TLS termination for all homelab services. Installed as a system package (not Docker) on LXC 105 (infra-pool). Handles automatic HTTPS via Let's Encrypt, with Cloudflare wildcard DNS pointing
*.eva-00.networkto the home IP.
Infrastructure
| Host | Internal | URL |
|---|---|---|
| System package (LXC 105) | 192.168.1.200:80, :443 | All *.eva-00.network services |
File Paths
| Path | Contents | Backed up? |
|---|---|---|
/etc/caddy/Caddyfile |
Main config (reverse proxy routes) | Yes — Backrest app-configs plan SCPs this nightly |
/var/lib/caddy/.local/share/caddy/ |
TLS certs, ACME tokens, OCSP staples | No — auto-regenerated by Caddy on startup |
/var/lib/caddy/.config/caddy/autosave.json |
Caddy's internal autosave of loaded config | No — regenerated from Caddyfile |
Note: Caddy is a system package, so config lives at /etc/caddy/ — not /opt/caddy/ like Docker-based services.
Observability
Logs
Caddy logs are collected via Grafana Alloy journald scraping and shipped to Loki.
| Query | Purpose |
|---|---|
{job="caddy", unit="caddy.service"} |
Caddy HTTP/TLS logs (JSON) |
{job="caddy", unit="caddy.service"} \| json \| level="error" |
Errors only |
{job="caddy"} |
All LXC journal entries (not just Caddy) |
Access: Grafana → Explore → Loki → Enter query
Metrics
Caddy does not export Prometheus metrics in this deployment. Use Loki logs to diagnose issues.
IaC
| Artifact | Path |
|---|---|
| Playbook | ansible/playbooks/caddy.yml |
| Workflow | .forgejo/workflows/caddy.yml |
| Caddyfile | services/caddy/Caddyfile |
Secrets
Caddy has no Vault secrets. TLS certificates are auto-provisioned via Let's Encrypt ACME challenge.
How routing works
- Cloudflare wildcard DNS
*.eva-00.networkresolves to the home IP - Router port-forwards 80/443 to LXC 105 (192.168.1.200)
- Caddy matches the hostname in the Caddyfile and reverse-proxies to the internal LXC IP
- TLS is terminated at Caddy — internal traffic is plain HTTP
Adding a new service route
- Add a
reverse_proxyblock toservices/caddy/Caddyfile - Push to
main→ triggers thecaddy.ymlworkflow - Caddy reloads automatically (zero-downtime reload)