diff --git a/content/posts/cooklang-server-and-systemd/index.md b/content/posts/cooklang-server-and-systemd/index.md index 125c8de..b2b2b71 100644 --- a/content/posts/cooklang-server-and-systemd/index.md +++ b/content/posts/cooklang-server-and-systemd/index.md @@ -10,11 +10,11 @@ keywords: ["", ""] summary: "Hosting your own cooklang server is (mostly) easy with the help of systemd and some intermediate-level service configuration." showFullContent: false tags: -- systemd -- cooklang +- systemd +- cooklang --- ## Cooklang -Recently I became aware that [cooklang](https://cooklang.org)'s CLI has a built in `server` [subcommand](https://cooklang.org/cli/help/#server), giving you a web interface for viewing your recipes and generating shopping lists. +Recently I became aware that [cooklang](https://cooklang.org)'s CLI has a built in `server` [subcommand](https://cooklang.org/cli/help/#server), giving you a web interface for viewing your recipes and generating shopping lists. Up until now, I've kept my recipes in [Obsidian](https://obsidian.md) which is great but Markdown has its limitations. The value-add for using Cooklang and its builtin web server is that I can easily build shopping lists for recipes and share them with friends and loved ones with a simple direct link. ## The systemd unit @@ -22,7 +22,7 @@ Starting the cooklang server is very straightforward: `cook server`, or `cook se `systemd` uses [unit files](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html) to configure resources it's responsible for. There's a lot going on in unit files so I've added as many comments as I could to explain what each lines does. Here, we're configuring a [service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html) which specifically describes a *process* that systemd is responsible for maintaining. -``` +{{< highlight >}} [Unit] # Describe your unit. This is displayed in various system utilities for human administrators to understand what they're looking at. Description="cooklang web server" @@ -51,22 +51,22 @@ Restart=always [Install] # WantedBy is part of systemd's dependency-chain configuration. multi-user.target is marked as available when the kernel/OS pass from single-user mode to multi-user mode, effectively meaning that the system is ready to start doing stuff other than bootstrapping the hardware and kernel. In short, "when the machine boots up, start me". WantedBy=multi-user.target -``` +{{< /highlight >}} With this unit file in place, my [recipes site](https://cook.ndumas.com) comes to life, with the help of a new block in my caddyfile: -``` +{{< highlight >}} cook.ndumas.com { encode gzip reverse_proxy localhost:9080 } -``` +{{< /highlight >}} ### Cooklang can't handle new recipe files Unfortunately, there's a catch. It looks like the cooklang server can't gracefully handle the addition of new recipes; the UI will display the recipe name but throw an error about invalid JSON when you attempt to navigate to that recipe's page. This seems like a pretty egregious bug/oversight but luckily, systemd is exceedingly clever and already has [a solution](https://www.freedesktop.org/software/systemd/man/latest/systemd.path.html) for this baked in. Using systemd path units, you can tell systemd to perform actions based on the existence or modification/deletion of specified files or directories. The full solution involves creating two additional unit-files: `cooklang-watcher.service` and `cooklang-watcher.path`. As above, I'll annotate the (new) directives to explain their functionality. #### `cooklang-watcher.service` -``` +{{< highlight >}} [Unit] Description=cooklang server restarter After=network.target @@ -81,10 +81,10 @@ ExecStart=/usr/bin/systemctl restart cooklang.service [Install] WantedBy=multi-user.target -``` +{{< /highlight >}} #### `cooklang-watcher.path` -``` +{{< highlight >}} [Unit] Description="Monitor /home/cook/recipes for changes" @@ -97,7 +97,7 @@ PathModified=/home/cook/recipes [Install] WantedBy=multi-user.target -``` +{{< /highlight >}} ### Conclusion -This is by far the most advanced `systemd` setup I've rolled from scratch and I'm really pleased with how it came together. I don't know if I'll stick with cooklang long-term but from an administrator/operator perspective the tools offered everything I needed to handle all the edge cases. Now I can start converting my recipes from Markdown. \ No newline at end of file +This is by far the most advanced `systemd` setup I've rolled from scratch and I'm really pleased with how it came together. I don't know if I'll stick with cooklang long-term but from an administrator/operator perspective the tools offered everything I needed to handle all the edge cases. Now I can start converting my recipes from Markdown.