Moving from nginx to Caddy
[web-hugo.git] / content / posts / moving-from-nginx-to-caddy.md
CommitLineData
642a805d
JM
1---
2title: "Moving from nginx to Caddy"
3date: 2023-09-03T13:00:00+03:00
4description: "I describe my journey into using Caddy and the great config truncation from 2000+ lines by 20x"
5tags: [site, news]
6type: blog
7draft: false
8---
9
10# Backstory
11I've heard of [Caddy](https://caddyserver.com/) for a long while, but have always been dismissive about it - ignoring it as "yet another webserver software" when I had my
12perfectly good trusty nginx to rely on for many years already. Over the years, my nginx config has become somewhat bloated and even take a while
13to do restarts on due to the complexity of said config. I did attempt to resolve it by reducing amount of expensive routines - which did help to
14an extent - I was complacent with my setup. Until I took a deeper dive into Caddy.
15
16One Saturday night (...yesterday as of writing this post), BieHDC brought to my attention that Caddy has a nginx configuration adapter.
17I thought to myself why not try it out if it's really plug-and-play and try to see what all the fuss is about. What followed this was all worth it.
18
19## The nginx-adapter
20I started off with building the [nginx adapter for Caddy](https://github.com/caddyserver/nginx-adapter) which took a while.
21Very quickly after building it, I ran into issues - no matter what I did, I kept getting null routes on the generated output with no idea where it's coming from.
22You would think I would have stopped here, but I foolishly tried to make it work for something that was never meant to be, you see, I forgot to do
23one key thing before even starting this whole thing - RTFM (Read The Fucking Manual). The README had a list of directives it supported and I had a ton of which
24were not supported, but very essential to the work of my services.
25
26I shelved the nginx-adpater for good at this point, after wasting an hour with it.
27
28## The story doesn't end
29While I may have been burnt by the mischiefs of nginx-adapter, I wasn't ready to give up - by this point I had already familiarised myself with Caddy's
30documentation and reference syntax. I decided to give it a try for based.quest at very least to have a fair and honest impression of Caddy as a software
31so I wouldn't start to bash on it going forward from a bad experience on a beta-phase config adapter.
32
33In literally a few minutes, I had made it, the Caddyfile for based.quest - I present it to you in all its glory in this blogpost:
34```
35http://based.quest, based.quest {
36 root * /var/www/based.quest/html
37 file_server
38}
39
40breezewiki.based.quest {
41 reverse_proxy localhost:10416
42}
43
44rimgo.based.quest {
45 reverse_proxy localhost:3000
46}
47
48proxitok.based.quest {
49 reverse_proxy localhost:8999
50}
51
52quetre.based.quest {
53 reverse_proxy localhost:3333
54}
55```
56
57Yes, you are seeing this right - **this little configuration only needed**. I was shocked. All this time I had been writing more for no reason, because I
58turned a blind eye to the alternative that was right in front of me for many years - I've seen the name, I've seen it used in several applications that
59I host under Docker, but never gave it a shot until it was pointed out to me that an adapter exist to load nginx configs (which obviously didn't work out, but
60that's beside the point).
61
62## The main server
63I wasn't going to stop with only based.quest server - after seeing the potential, I took on the seemingly herculean task of porting my main server's 2000+ lines
64of nginx config to a Caddyfile. I delved into documentation for over an hour, searching for answers for any immediate question I had.
65
66You may find what I wrote useful for your own configs, so here are (not fully mine) templates you can use for building your own Caddy virtualhosts:
67```
68(errors) {
69 handle_errors {
70 @custom_err file /err-{err.status_code}.html /err.html
71 handle @custom_err {
72 rewrite * {file_match.relative}
73 file_server
74 }
75 respond "{err.status_code} {err.status_text}"
76 }
77}
78(php-fpm) {
79 encode gzip
80 php_fastcgi unix//run/php/php7.4-fpm.sock {
81 try_files {path} {path}/index.php =404
82 }
83 file_server
84}
85(cache-static) {
86 @static {
87 file
88 path *.ico *.css *.js *.gif *.webp *.avif *.jpg *.jpeg *.png *.svg *.woff *.woff2
89 }
90 header @static Cache-Control max-age=1209600
91}
92```
93You can find most of this on the official documentation, but thought it may be useful to consolidate it here for your convenience.
94
95Migrating Matrix is super easy, but be attentive to details, they provide the Caddyfile samples on their own repository already - here is my final variant of it:
96```
97http://cernodile.com, cernodile.com, cernodile.com:8448 {
98 header /.well-known/matrix/* Content-Type application/json
99 header /.well-known/matrix/* Access-Control-Allow-Origin *
100 respond /.well-known/matrix/server `{"m.server": "cernodile.com"}`
101 respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://cernodile.com"}}`
102 reverse_proxy /_matrix/* localhost:8008
103 reverse_proxy /_synapse/* localhost:8008
104 # [...]
105}
106```
107
108The reason I ask you to be attentive to details is because I broke my federation with it. Notice the /matrix/server field. I had copied the sample from Synapse
109repository and left it as `"cernodile.com:443"` whereas my **original** well-known record was just `"cernodile.com"`.
110
111There were 2 blockers when migrating my services to Caddy. PeerTube and Gitweb. Unfortunately for PeerTube, since [PeerTube does not support anything else than nginx](https://docs.joinpeertube.org/install/any-os#webserver),
112I had to keep one nginx virtualhost up and use reverse_proxy directive against it. As for Gitweb which doesn't supply any other configuration than
113for Apache, I did manage to port it over to Caddy by adapting generic fastcgi adapter in a way that works for Gitweb, feel free to use it as well:
114```
115git.based.quest {
116 root * /usr/share/gitweb
117 try_files {uri} index.cgi
118 handle /static/* {
119 file_server
120 }
121 reverse_proxy unix//var/run/fcgiwrap.socket {
122 transport fastcgi {
123 env GITWEB_CONFIG /etc/gitweb.conf
124 split .cgi
125 }
126 }
127}
128```
129
130## Closing thoughts
131After all this effort, I am down to 108 lines on my Caddyfile from 2000+ lines on nginx. The performance is as great as ever with no hickups noticed.
132I want to thank BieHDC for bringing this to my attention, I wouldn't have probably gone down this rabbit hole if it weren't for the nginx adapter.
133This experience was all the worth it and I suggest you give Caddy a try if you are currently running an nginx site - you won't regret having to write
13420x less configuration for your webserver.
135
136Thank you for reading
137- Cernodile