aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/blog/2024-08-18-user-services-with-systemd.md96
1 files changed, 96 insertions, 0 deletions
diff --git a/content/blog/2024-08-18-user-services-with-systemd.md b/content/blog/2024-08-18-user-services-with-systemd.md
new file mode 100644
index 0000000..0486919
--- /dev/null
+++ b/content/blog/2024-08-18-user-services-with-systemd.md
@@ -0,0 +1,96 @@
++++
+title = "User Services With Systemd"
+date = "2024-08-18T19:05:10-04:00"
+
+tags = ["systemd","selfhosting"]
++++
+
+# Your very own `systemd`
+
+Recently, I've started using `systemd` order to manage personal services on my servers.
+
+Before that, I had either set up system-wide unit files or, for more ad-hoc services, started the process inside of a `screen` session, then detaching, hoping the process didn't crash overnight.
+
+Using `systemd` instead is way better, since you get stuff like `journalctl` to view logs and `RestartAlways` keep things running. Also, all configuration lives in `$HOME` making it easy to edit and back up.
+
+In this post, I will show you how to set this up on any modern Debian-based system (or any distro that uses `systemd`, really).
+
+_Debian 12.6 (bookworm) was used at the time of writing this post._
+
+# Caveats
+
+There are a few things to note with this approach:
+
+* User units **cannot** depend on system-wide units, or vice versa. For example, your user service cannot depend on system-wide `redis-server`. To specify dependencies between your services, you'll need to run all of those dependencies as user services.
+
+* User units are run without privileges so naturally they can't do `root` things like edit files outside of `$HOME` and listen below port `1024`.
+
+* Environment variables set in `~/.zshrc`, `~/.bashrc`, etc are not inherited. See the [environment variables section](https://wiki.archlinux.org/title/Systemd/User#Environment_variables) for more information on how to set/import environment variables for user units.
+
+# Getting Started
+
+## Enable linger for your user
+
+By default, `systemd` user instances are only started after the first login of that user then killed once their last session is closed. This behavior makes sense in a desktop environment but not so much for a server environment where you typically want your daemons running at all times.
+
+In order to change this behavior, you have to enable _linger_ for your user by running the following:
+
+ $ loginctl enable-linger
+
+You can verify if lingering is enabled by ensuring the column for `LINGER` says `yes` for your user when running:
+
+ $ loginctl list-users
+
+## Create configuration directory
+The [unit files](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html) for our services will live in `$HOME/.config/systemd/user/`. Ensure it's created using by using `mkdir -p`, like so:
+
+ $ mkdir -p $HOME/.config/systemd/user/
+
+## Setting up an example service
+
+We can now place this `example.service` unit in `$HOME/.config/systemd/user/`:
+
+```
+[Unit]
+Description=Example Service
+
+[Service]
+Restart=always
+RestartSec=1s
+WorkingDirectory=/home/me/my-service-dir
+ExecStart=racket hello-world-server.rkt
+
+[Install]
+WantedBy=default.target
+```
+
+### Start service on boot
+
+This starts `example` as soon as your copy `systemd` is launched (which should be at boot, since we enabled lingering):
+
+ $ systemctl --user enable example
+
+### Starting, Stopping and Status
+
+You can now run the same `systemctl` commands you are used to, except they are run as your user (instead of root) and now require the `--user` argument:
+
+ $ systemctl --user start example
+
+ $ systemctl --user stop example
+
+ $ systemctl --user status example
+
+ $ systemctl --user restart example
+
+### Logs
+
+Similar to `systemctl`, you'll need to pass `--user` to `journalctl`:
+
+ $ journalctl --user --unit=example
+
+
+# More information
+
+You can read more about this feature on the [Arch Linux Wiki: systemd/User](https://wiki.archlinux.org/title/Systemd/User).
+
+