brainsteam.co.uk/brainsteam/content/posts/2022/01/08-01-replace-nginx-caddy/index.md

76 lines
4.6 KiB
Markdown

---
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.