← Home

Switching from nginx to caddy

21 March, 2025 - Categories: homelab

Yesterday I finally switched my reverse proxy for my homeloab from nginx to caddy.

Nginx has worked well for many years, once I figured out how to configure the reverse proxy stuff it was easy enough to add more services and point them at the right virtual machine or later container.

However, the configuration was always a bit annoying to deal with. Especially with certbot in the mix for https, my process looked like this:

i kept meaning to set up an ansible playbook for this but... it doesn't happen quite often enough to make it worthwhile, especially as a bunch of services required special little additions to the config to actually get them to work. i also never decided on a single source of truth for my homelab...

Anyway, now with caddy it's much simpler:

that's it. https works out of the box (if dns is set up properly, but adding a dns entry for a subdomain is the same in both setups) and the actual configuration is WAY smaller.

In fact, when changing the server initially, i copied some of the configuration over for setting certain headers and handling websockets, mainly for Jitsi Meet, and that broke things. Removing the extra config and simply using the reverse_proxy directive in the caddyfile seems to have made everything work perfectly fine.

in fact, here's some examples. the certbot command (still containing some unused domains):

NOTE: sorry formatting will be fixed soon

certbot certonly --webroot -w /var/www/html -d shinymail.ch,shiny.space,meet.shiny.space,forge.shiny.space,trilium.shiny.space,caldav.shiny.space,wiki.shiny.space,pics.shiny.space,photos.shiny.space,nocobase.shiny.space,rocketchat.shiny.space,play.shiny.space,jellyfin.shiny.space,grafana.shiny.space,api.shiny.space,blog.shiny.space,www.shiny.space --expand

fun and readable, right? i'm sure making a script or putting it in a config file or whatever would be better, but... yeah, with caddy you just don't even have to think about it.

here's a snippet for the old blog:

server { listen 443 ssl;

server_name blog.shiny.space;
location /.well-known {
	root /var/www/html;
	try_files $uri $uri/ = 404;
}
location / {
	proxy_pass http://10.0.0.30:57420;
}

}

the well-known stuff is necessary to make certbot work - ssl/tls is terminated at the reverse proxy, so the requests for these files should not be proxied.

here's the config for the blog you're reading now (as of 2025):

blog.shiny.space { reverse_proxy 10.0.0.30:57420 }

yes. that's it. let's look at jitsi meet:

´´´server { listen 443 ssl;

server_name meet.shiny.space;
client_max_body_size 500M;
location /.well-known {
	root /var/www/html;
	try_files $uri $uri/ = 404;
}
location /xmpp-websocket {
	proxy_pass http://10.0.0.30:8000;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection "upgrade";
}
location /colibri-ws {
	proxy_pass http://10.0.0.30:8000;
	proxy_http_version 1.1;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection "upgrade";
}
location /http-bind {
	proxy_pass http://10.0.0.30:8000;
	proxy_http_version 1.1;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection "upgrade";
}
location / {
	proxy_pass http://10.0.0.30:8000;
}

} ´´´

and here's caddy's version:

meet.shiny.space { request_body { max_size 500MB }

reverse_proxy 10.0.0.30:8000

}