by godelski | 2025-09-20 23:44:39+00:00
Make sure to do

systemctl edit foo.service

The reason for this is that it creates an override file rather than edits the systemd file directly. This means you'll keep your changes even if the systemd file changes in an upgrade. Obviously also helps you roll back and make sure you got things right. Another side benefit is that you can place these on github. Also, pretty much every service should use `PrivateTmp=yes` and this is surprisingly uncommon.

Then run

systemd-analyze security foo.service

It'll give you a nice little rundown of what is restricted and what isn't. There's a short description of what each of the capabilities are, but I also like this gist[0]. The docs kinda suck (across systemd) but play around and it starts to make sense.

This stuff is surprisingly quite powerful and it's caused me to go on a systemd binge for the last year. You can restrict access to basically anything, effectively giving you near container like restrictions. You can restrict paths (and permissions to those paths), executables, what conditions will cause the service to start/stop, how much CPU and memory usage a service can grab, and all sorts of things. That last one can be really helpful when you have a service that is being too greedy, giving you effectively an extremely lightweight container.

If you want to go further, then look into systemd-nspawn and systemd-vmspawn. This will give you a "chroot on steroids" (lightweight container, which can be used in place of things like docker) and a full fledged VM, respectively. Both of these have two complementary commands: machinectl and importctl.

`machinectl` will allow you to make these things act just like services, even allowing you to define conditions in which they can autoactivate. `importctl` gives you the ability to download, import, and export these machines as images.

You can use importctl to get an image from an arbitrary url, so if a project decided to provide this in addition to (or as a replacement to) a docker image, you could have a pretty similar streamlined process. I'm no expert, but I've not run across a case where you can't use systemd as a full on replacement for docker. While it's more annoying to make these images I've found that I can get better control over them and feel a lot less like I'm fighting the system. A big advantage too is that these can run with fewer resources than docker, but this really depends on tuning. The more locked down the slower it will be, so this is only a "can" not "will" (IIRC defaults on vmspawn are slower[1])

Finally, note that all these have a `--user` flag, so you don't always need to use sudo. That itself gives a big advantage because you're automatically limiting capabilities by running it as a user service. No more fucking around with groups and all that.

Honestly, the biggest downside of systemd is the lack of documentation and the lack of wider adoption and examples to pull from. But that's a solvable problem and the exact kinda thing HN can help solve (this comment is even doing some of that as well as some others in this thread). Systemd is far from perfect and there's without a doubt a good learning curve (i.e. lack of docs), but IME it's been worth the effort.

[0] https://gist.github.com/ageis/f5595e59b1cddb1513d1b425a323db...

[1] https://github.com/systemd/systemd/issues/18370