4.9 KiB
+++ draft = false title = "Automating Caddy on my DigitalOcean Droplet" date = "2023-01-05" author = "Nick Dumas" authorTwitter = "" #do not include @ cover = "" tags = ["webdev", "devops"] keywords = ["", ""] description = "Automation ambitions fall flat" showFullContent = false +++
Defining units of work
I've got a few different websites that I want to run: this blog, my portfolio, and my about page which acts as a hub for my other sites, my Bandcamp, and whatever else I end up wanting to show off.
To keep things maintainable and reproducible, I decided to stop attempting to create a monolithic all-in-one configuration file. This made it way harder to keep changes atomic; multiple iterations on my blog started impacting my prank websites, and it became harder and harder to return my sites to a working state.
Proof of concept
The first test case was my blog because I knew the Hugo build was fine, I just needed to get Caddy serving again.
A static site is pretty straightforward with Caddy:
blog.ndumas.com {
encode gzip
fileserver
root * /var/www/blog.ndumas.com
}
And telling Caddy to load it:
curl "http://localhost:2019/load" \
-H "Content-Type: text/caddyfile" \
--data-binary @blog.ndumas.com.caddy
This all works perfectly, Caddy's more than happy to load this but it does warn that the file hasn't be formatted with caddy fmt
:
[{"file":"Caddyfile","line":2,"message":"input is not formatted with 'caddy fmt'"}]
The loop
Here's where things went sideways. Now that I have two unit files, I'm ready to work on the tooling that will dynamically load my config. For now, I'm just chunking it all out in bash
. I've got no particular fondness for bash
, but it's always a bit of a matter of pride to see whether or not I can.
# load-caddyfile
#! /bin/bash
function loadConf() {
curl localhost:2019/load \
-X POST \
-H "Content-Type: text/caddyfile" \
--data-binary @"$1"
}
loadConf "$1"
# load-caddyfiles
#! /bin/bash
source load-caddyfile
# sudo caddy stop
# sudo caddy start
for f in "$1/*.caddy"; do
echo -e "Loading $(basename $f)"
loadConf "$f"
echo
done
After implementing the loop my barelylegaltrout.biz site started throwing a 525 while blog.ndumas.com continued working perfectly. This was a real head scratcher, and I had to let the problem sit for a day before I came back to it.
After some boring troubleshooting legwork, I realized I misunderstood how the /load
endpoint works. This endpoint completely replaces the current config with the provided payload. In order to do partial updates, I'd need to use the PATCH
calls, and look who's back?
can't escape JSON
The PATCH
API does let you do partial updates, but it requires your payloads be JSON which does make sense. Because my current set of requirements explicitly excludes any JSON ( for now ), I'm going to have to ditch my dreams of modular code.
Not all my code has gone to waste, though. Now that I know POST
ing to to /load
overwrites the whole configuration, I don't need to worry about stopping/restarting the caddy process to get a clean slate. load-caddyfile
will let me keep iterating as I make changes.
Proxies
In addition to the static sites I'm running a few applications to make life a little easier. I'll showcase my Gitea/Gitlab and Asciinema configs. At the moment, my setup for these are really janky, I've got a tmux
session on my droplet where I've manually invoked docker-compse up
. I'll leave cleaning that up and making systemd units or something proper out of them for a future project.
Reverse proxying with Caddy is blessedly simple:
cast.ndumas.com {
encode gzip
reverse_proxy localhost:10083
}
code.ndumas.com {
encode gzip
reverse_proxy localhost:3069
}
With that, my gitea/gitlab is up and running along with my Asciinema instance is as well:
Back to Square One
After finally making an honest attempt to learn how to work with Caddy 2 and its configurations and admin API, I want to take a swing at making a systemd unit file for Caddy to make this a proper setup.
Finally
Here's what's currently up and running:
I've had loads of toy projects over the years ( stay tuned for butts.ndumas.com ) which may come back, but for now I'm hoping these are going to help me focus on creative, stimulating projects in the future.
The punchline is that I still haven't really automated Caddy; good thing you can count on tmux
The final code can be found here. Nothing fancy, but troublesome enough that it's worth remembering the problems I had.