I've been using Nginx Proxy Manager for quite a while now as a way to access my self-hosted services with valid SSL certificates over Tailscale. I have my own domain that I use with subdomains pointing to individual services, and it works very well. For applications that require HTTPS, such as Home Assistant for some features, it's absolutely perfect. However, I'd heard a lot about Caddy, and as I migrate some of my more essential home services to my mini PC Proxmox host, I decided to migrate my reverse proxies to the new host in Caddy instead of Nginx.
There are a few reasons why I did it, and most of them are genuinely practical reasons that make it better in my use case. I deployed Caddy in a Proxmox LXC, but all of these reasons apply universally to Caddy.
5 Learning something new
I like to keep up to date
More than anything, I was interested in switching to Caddy just to learn something new. I like to keep up to date with technology, and I've seen many others take the plunge in switching to Caddy over the years, both as a reverse proxy and even just as a web server. It's a good way to learn something new, especially given that I had previously been using the GUI-based Nginx Proxy Manager before.
Was there a learning curve? For sure. Previously, Nginx Proxy Manager on my TrueNAS machine handled basically everything for me. There was very little to actually do, and it was impressively easy to deploy new subdomains with an SSL certificate ready to go via Let's Encrypt. I wanted to take back some of that control and learn while doing so, and Caddy was a great way to do both at the same time.
7 reasons Proxmox is now non-negotiable for my home servers
After this, there’s no looking back
4 One easy-to-use config file
And a relatively easy configuration, too
In Caddy, there's just one easy-to-use config file in /etc/caddy, called "Caddyfile". It contains all of your reverse proxies and SSL-related settings, so that renewals can be automated. What that also means, though, is that this one file can be transported anywhere, making it super easy to backup to something like a Git repository and pull it elsewhere when you need it. While Nginx is pretty simple in terms of deploying new reverse proxies, adding a new reverse proxy with Cloudflare is even easier. Plus, this means that migrating Caddy to a new host in the future is a lot easier than the convoluted method required to migrate Nginx Proxy Manager.
To give you an idea, I export my Cloudflare API token as an environment variable, and my Caddyfile simply has "acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}" at the beginning, alongside a declaration of my email. Every reverse proxy after that can be defined in the following format;
example.ie {
reverse_proxy http:// It's literally just three lines, and Caddy will automatically see the new site and fulfill a DNS challenge to prove ownership of the domain for a Let's Encrypt SSL certificate. Some domains may require a few additions, but I've already been using this exact three-liner with Home Assistant without any issues. All I needed to do was add my host's IP to the allowed proxies list.
It takes a bit more setup than Nginx Proxy Manager to get Caddy up and running, but the time saved after that is significant. The only difficulty I had in deploying this setup was getting Tailscale running in the LXC, but I was able to by adding the following lines to my LXC configuration in the Proxmox host:
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
This allows the LXC to access /dev/tun in the host, so that a VPN can be used. I later learned that there's a Proxmox helper script to add Tailscale to an existing LXC, but hey, it was still good to work out how to do it myself!
3 HTTP/3 and QUIC support
Caddy supported it five years ago
Nginx supports HTTP/3 and QUIC... technically. It's a compile-time extra added with the --with-http_v3_module build flag, and it's deemed "experimental". In contrast, Caddy added support for HTTP/3 and QUIC in May 2020, a little over five years ago now. QUIC basically merges the strengths of both TCP and UDP, and TLS is a component of the communication rather than an additional layer on top. Sure, you could argue that it doesn't really matter for most people, but it's generally a good idea to be on the latest and most secure versions when dealing with web protocols.
QUIC is specifically beneficial for unreliable networks, thanks to its zero round-trip time at both packet and cryptographic levels. Latency is massively reduced (comparatively speaking) when compared against TCP, which uses a three-way handshake. Most users won't ever notice the improvement, but there is a technical improvement, and it's somewhat strange that the capability is still gated behind a build flag in Nginx. Plus, there are big benefits when accessing over a mobile network that may be susceptible to jitter and packet loss.
To use this over Tailscale, you may need to increase the MTU value with TS_DEBUG_MTU, as the default Tailscale MTU is 1280, and your browser may fall back to HTTP/2 in order to prevent fragmentation in packets when those packets exceed the MTU value.
2 Modules are really easy to use
One-liner commands
If you want to use a specific service not natively supported by Caddy, it's really easy to implement yourself using xcaddy. This tool can build Caddy with modules (plugins, basically), and if the term "build" scares you, it's actually really, really easy. For example, Cloudflare isn't natively supported as a part of Caddy, but I was able to easily add support with just one command:
xcaddy build --with github.com/caddy-dns/cloudflare
Once it finished, I simply moved the new "caddy" file to /usr/bin, and it just worked. It took five minutes, if even, and I immediately had Cloudflare support working as a part of Caddy. There are a lot of modules supported, so be sure to have a browse through the list.
1 Support for logging in Prometheus
Make beautiful graphs!
If you use Prometheus for metrics tracking, you'll be happy to know that Caddy supports it, too! I haven't set this up yet, but you can create a beautiful Grafana dashboard to track everything that's going through your Caddy server with all the information you could ever want to know about it. It's not too complicated to get set up either, and you'll get per‑host metrics, latency histograms, and real‑time certificate stats.
For most people, this doesn't particularly matter, but it can be interesting data to collect, especially if your server is exposed to the internet rather than accessible only via a VPN.
I love Caddy already
While there was a bit of a learning curve to it, I love Caddy so much already. It's mostly easy to use, it's fast, and I know that migrating it in the future to another host will be incredibly easy. It's just one file that I can take anywhere, and with the ability to add new subdomains in literally a minute, I'm honestly disappointed I didn't make the jump sooner.
