Vendor NAS boxes (Synology, QNAP, etc.) usually ship a GUI-driven reverse proxy that's fine for a couple of domains but gets awkward fast. Here's how to move everything to a dedicated Caddy instance instead, and the gotchas that come with it.
Before migrating, pull the full existing rule set. It's common to find more running behind a reverse proxy
than you'd expect — services pointed at localhost that have been quietly running on the NAS
itself for years with no other documentation, stale rules pointing at backends that moved or were retired
long ago, and the occasional rule with no live backend behind it at all. Confirm what's actually still in use
before deciding what to migrate versus retire.
A small dedicated VM or container running Caddy via Docker Compose is enough for dozens of domains. A basic site block:
example.com {
reverse_proxy 192.168.1.100:8080
}
Caddy handles WebSocket upgrades and sets X-Forwarded-* headers automatically — you generally
don't need to hand-replicate custom header rules from the old reverse proxy config.
If your domains are proxied through Cloudflare with "Always Use HTTPS" enabled, Caddy's automatic HTTPS will try to get a real Let's Encrypt certificate and fail in two different ways:
Fix: use a Cloudflare Origin CA certificate instead of Let's Encrypt — issued directly from the Cloudflare dashboard with no HTTP challenge involved, valid for up to 15 years, and trusted specifically by Cloudflare (which is all that matters, since Cloudflare — not the visitor's browser — is what validates your origin's certificate in Full/Full-Strict mode).
example.com {
tls /config/origin-cert.pem /config/origin-key.pem
reverse_proxy 192.168.1.100:8080
}
openssl x509
-modulus vs. openssl rsa -modulus), then delete the local copy securely once confirmed.
If your domains are proxied through a CDN to a single stable home IP, the actual traffic path is your router's port-forward rule (WAN 80/443 → LAN target), not DNS. Cutover is as simple as flipping that port-forward from the old backend's IP to the new reverse proxy's IP. Do this through your router's own admin UI rather than any automation tooling — it's a live cutover for public services, high-stakes enough to want a human directly in the loop.
Verify afterward against the real public path (not a locally-forced DNS override) — confirm every domain returns the correct response through the actual CDN → port-forward → reverse-proxy → backend chain, with the real certificate being served.