Upgrading to Caddy 2

Caddy recently released a complete rewrite as Caddy 2. They also finally released an official Docker image! So it is time to upgrade my home server to use version 2.

I run Caddy as an entry-point into my home network on ports 80 and 443. Based on various subdomains, I reverse proxy to other internal servers. For example, in my Caddyfile, I send traffic from clobber.epicbits.dev to localhost:2015.

clobber.epicbits.dev {
    proxy / 127.0.0.1:2015 {
        header_upstream Host {host}
        header_upstream X-Real-IP {remote}
        header_upstream X-Forwarded-Proto {scheme}
    }
}

Caddy 2 builds in header forwarding so we can simplify this a lot.

clobber.epicbits.dev {
    reverse_proxy 127.0.0.1:2015
}

Reverse proxy to another internal Caddy 2 server

One nuance I ran into was reverse proxying to another internal Caddy 2 server. By default, Caddy 2 serves traffic over HTTPS. The default Docker image exposes ports 80 and 443 and will forward any traffic from port 80 to port 443.

When I first configured my reverse proxy, one of my subdomains kept going in an infinite redirect. This was because the proxy was receiving traffic over HTTPS, but was then forwarding it via HTTP. The internal server was then forwarding the traffic back to HTTPS, putting us in an infinite loop!

First, for the internal Caddy server, I configured it to listen to traffic over HTTP and disregard HTTPS by explicitly allowing only HTTP domains in the Caddyfile.

http://127.0.0.1, http://games.epicbits.dev

Then, in the reverse proxy, I explicitly configured it to only send traffic over HTTP.

games.epicbits.dev {
    reverse_proxy http://127.0.0.1:3019
}

Conclusion

Caddy has been super fun to work with. It is simple to setup and delightfully takes care of auto-magic encrypted connections for us.