Moving from nginx to Caddy master
authorJoann Mõndresku <joann@cernodile.com>
Sun, 3 Sep 2023 10:09:13 +0000 (13:09 +0300)
committerJoann Mõndresku <joann@cernodile.com>
Sun, 3 Sep 2023 10:09:13 +0000 (13:09 +0300)
content/posts/moving-from-nginx-to-caddy.md [new file with mode: 0644]

diff --git a/content/posts/moving-from-nginx-to-caddy.md b/content/posts/moving-from-nginx-to-caddy.md
new file mode 100644 (file)
index 0000000..898c691
--- /dev/null
@@ -0,0 +1,137 @@
+---
+title: "Moving from nginx to Caddy"
+date: 2023-09-03T13:00:00+03:00
+description: "I describe my journey into using Caddy and the great config truncation from 2000+ lines by 20x"
+tags: [site, news]
+type: blog
+draft: false
+---
+
+# Backstory
+I'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
+perfectly 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
+to 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
+an extent - I was complacent with my setup. Until I took a deeper dive into Caddy.
+
+One Saturday night (...yesterday as of writing this post), BieHDC brought to my attention that Caddy has a nginx configuration adapter.
+I 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.
+
+## The nginx-adapter
+I started off with building the [nginx adapter for Caddy](https://github.com/caddyserver/nginx-adapter) which took a while.
+Very 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.
+You 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
+one 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
+were not supported, but very essential to the work of my services.
+
+I shelved the nginx-adpater for good at this point, after wasting an hour with it.
+
+## The story doesn't end
+While 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
+documentation 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
+so I wouldn't start to bash on it going forward from a bad experience on a beta-phase config adapter.
+
+In 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:
+```
+http://based.quest, based.quest {
+       root * /var/www/based.quest/html
+       file_server
+}
+
+breezewiki.based.quest {
+       reverse_proxy localhost:10416
+}
+
+rimgo.based.quest {
+       reverse_proxy localhost:3000
+}
+
+proxitok.based.quest {
+       reverse_proxy localhost:8999
+}
+
+quetre.based.quest {
+       reverse_proxy localhost:3333
+}
+```
+
+Yes, 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
+turned 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
+I 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
+that's beside the point).
+
+## The main server
+I 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
+of nginx config to a Caddyfile. I delved into documentation for over an hour, searching for answers for any immediate question I had.
+
+You 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:
+```
+(errors) {
+       handle_errors {
+               @custom_err file /err-{err.status_code}.html /err.html
+               handle @custom_err {
+                       rewrite * {file_match.relative}
+                       file_server
+               }
+               respond "{err.status_code} {err.status_text}"
+       }
+}
+(php-fpm) {
+       encode gzip
+       php_fastcgi unix//run/php/php7.4-fpm.sock {
+               try_files {path} {path}/index.php =404
+       }
+       file_server
+}
+(cache-static) {
+       @static {
+               file
+               path *.ico *.css *.js *.gif *.webp *.avif *.jpg *.jpeg *.png *.svg *.woff *.woff2
+       }
+       header @static Cache-Control max-age=1209600
+}
+```
+You can find most of this on the official documentation, but thought it may be useful to consolidate it here for your convenience.
+
+Migrating 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:
+```
+http://cernodile.com, cernodile.com, cernodile.com:8448 {
+       header /.well-known/matrix/* Content-Type application/json
+       header /.well-known/matrix/* Access-Control-Allow-Origin *
+       respond /.well-known/matrix/server `{"m.server": "cernodile.com"}`
+       respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://cernodile.com"}}`
+       reverse_proxy /_matrix/* localhost:8008
+       reverse_proxy /_synapse/* localhost:8008
+       # [...]
+}
+```
+
+The 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
+repository and left it as `"cernodile.com:443"` whereas my **original** well-known record was just `"cernodile.com"`.
+
+There 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),
+I 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
+for 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:
+```
+git.based.quest {
+       root * /usr/share/gitweb
+       try_files {uri} index.cgi
+       handle /static/* {
+               file_server
+       }
+       reverse_proxy unix//var/run/fcgiwrap.socket {
+               transport fastcgi {
+                       env GITWEB_CONFIG /etc/gitweb.conf
+                       split .cgi
+               }
+       }
+}
+```
+
+## Closing thoughts
+After 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.
+I 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.
+This 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
+20x less configuration for your webserver.
+
+Thank you for reading
+- Cernodile