--- title: Replacing nginx with caddy type: post description: Caddy just makes self-hosting with SSL so painless resources: - name: feature src: images/wedding.jpg date: 2022-01-08T09:05:11+00:00 url: /2022/01/08/replacing-nginx-with-caddy tags: - open-source - self-hosting - indieweb - 100DaysToOffload --- Over the last 15+ years I've worked with a bunch of different web servers from Apache to Lighttpd to nginx. I like a hassle free life so while I'm typically an early adopter, I don't tend to move on a whim unless I'm seeing a lot of positive feedback. A lot of my peers have been recommending [Caddy](https://caddyserver.com/) for a while and I recently tried using it at work which finally convinced me to make the switch. ## Why I'm moving ### SSL Configuration is annoying I self-host a bunch of applications and up to now I've typically run them in docker and used [nginx](https://www.nginx.com/) to listen for incoming traffic to different domains and subdomains and forward traffic to the right container. This wasn't too painful because I was running on HTTP with no SSL until the internet community (quite rightly) decided that we should SSL/TLS encrypt all traffic and [LetsEncrypt](https://letsencrypt.org/) made that trend easy by giving out free signed SSL certificates to all (10+ years ago it was pretty common that you'd pay an oligarchy of big companies to sign your SSL cert). I wouldn't say configuring SSL in nginx is a tremendous PITA but it's certainly not fool proof. I'm a fully qualified fool and I've broken it many times. This process certainly got easier with [Certbot](https://certbot.eff.org/) which automatically configures your nginx certificates for you and can be run in a cron job to renew your certs on the regular but certbot [dropped support for my OS](https://community.letsencrypt.org/t/your-system-is-not-supported-by-certbot-auto-anymore/139606/4) a couple of years ago and require use of [snap](https://snapcraft.io/docs/installing-snapd) packages which until very recently have been broken on my server due to weirdness when I upgraded from an old version of Debian (I understand [their reasoning](https://community.letsencrypt.org/t/certbot-auto-no-longer-works-on-debian-based-systems/139702/7) although it is obviously a tad frustrating). ### Server configuration in general is a pain The nginx config file format is relatively verbose (compared to Caddy) and requires a lot more manual tweaking for my use case .e.g which headers need to be forwarded to the application, which . Whilst some folks might want to be able to manually tweak these config values, I do not want or need to care about them for my simple home server/self hosting set up - I'm not expecting to load balance millions of visitors to my websites or anything. ### Fewer moving parts Related to the first point really: maintaining good SSL certs in nginx requires that I have certbot correctly set up, configured and running in a cron job regularly as well as my nginx instance and my hosted apps. Caddy manages its own SSL certificates as part of the core application so I don't need to run certbot alongside it. ### In Summary Nginx is a good bit of kit and it's served me well for about a decade but I think the QoL that Caddy brings really makes switching worthwhile. I wouldn't say nginx's config system is bad or that I can't use it but I'd say it has put me off standing up new web apps because of the faff adding a new site configuration would cause. # Installing Caddy and Replacing nginx Firstly, on my debian box I followed the instructions [here](https://caddyserver.com/docs/install#debian-ubuntu-raspbian) and installed caddy via the apt mirror. Next I modify the caddy configuration file. For each domain I want to port forward I just add a simple declaration like so: ``` app.example.me { reverse_proxy 127.0.0.1:1234 } app2.example.me { reverse_proxy 127.0.0.1:1235 } app3.example.me { reverse_proxy 127.0.0.1:1236 } ``` This is so nice in comparison to nginx where I'd have to cook up a bunch of directives and pass in which ports I want it to listen on and paths to SSL keys and a 2nd configuration which listens for non-encrypted HTTP traffic just so that it can redirect users to the encrypted version (although it's not a totally fair comparison as these days certbot can do some of the hard work for you here). Then I stopped the nginx service and replaced it with caddy: ```shell sudo service nginx stop sudo service caddy start ``` It worked first time, no hassle, no fuss. If I want to add another application, I can spin it up in docker, add a CNAME domain record for it, add a 3 line configuration in my Caddyfile and restart the server.