Hardening Systemd Services
6 comments
·August 17, 2025jauntywundrkind
neuroelectron
It kind of undermines the point of systemd if people understand it.
c0balt
Idk, for packaging software and hardening existing services it is good.
systemd basically just gives you a unified interface to the different knobs of the kernel, that would otherwise have to be adjusted via scripting. That does seem to fit within the service startup/manager goal.
ryandotsmith
Are there common patterns or examples of directives that operators should be aware of?
I know the post linked to systemd docs, but I’d enjoy seeing some snippets of directives people are using to achieve this kind of hardening.
bhaney
I have a dropin called security.conf that I link in to most of my services, and then create an unsecurity.conf to disable/revert any directives not compatible with the service.
[Service]
DynamicUser=yes
PrivateTmp=true
PrivateDevices=true
PrivateNetwork=true
PrivateUsers=true
InaccessiblePaths=-/mnt/
ProtectSystem=strict
ProtectHome=true
ProtectHostname=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
ProtectClock=true
ProtectProc=invisible
ProcSubset=pid
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
NoNewPrivileges=true
RemoveIPC=true
IPAddressDeny=any
UMask=0077
SystemCallArchitectures=native
RestrictAddressFamilies=none
MemoryDenyWriteExecute=true
SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @reboot @swap @raw-io @privileged @resources
CapabilityBoundingSet=~CAP_SYS_PACCT CAP_KILL CAP_WAKE_ALARM CAP_LINUX_IMMUTABLE CAP_IPC_LOCK CAP_SYS_TTY_CONFIG CAP_SYS_BOOT CAP_SYS_CHROOT CAP_BLOCK_SUSPEND CAP_LEASE CAP_MKNOD CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_SYS_RAWIO CAP_SYS_PTRACE CAP_SYS_NICE CAP_SYS_RESOURCE CAP_NET_ADMIN CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE CAP_BPF CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
MemoryDenyWriteExecute gets set back to "no" quite a lot because interpreters like to use it for JITing, but it prevents a whole class of exploits on services where it can stay enabled.I also like to socket-activate services as often as possible so they don't need access to network interfaces. Even if a service doesn't support socket-activation itself, it can usually be shimmed in with systemd-socket-proxyd, which also provides good functionality for stopping services when there are no connections to them (they get started again by the next connection).
MartinGAugustin
[dead]
One of the incredible & fantastic superpowers of systemd. There so much isolation it can give you, rescind so many powers!
Alas this article doesn't include even the most rudimentary of examples.
Let's look at recent gnome gdm session picker changes. They now use dynamic users, rather than statically allocated ones, helping make sure the picker never gets access to things it shouldn't have (since there's no static user id that an attacker might grant access to). A nice feature from systemd in 2017. So easy to add! DynamicUser=yes and you're good! https://0pointer.net/blog/dynamic-users-with-systemd.html
This also gives you a bunch of other security options by default.
PrviateTmp=yes. ProtectHome=readonly. ProtectSystem=strict.
This is just the tiniest cut of what systemd can do to make your system more secure, how it can help you make use of the kernel to limit your process. There's so so many ways to limit programs. Limit maximum tasks, set Nice= CPUWeight=, IOWeight=, limit CapabilityBoundingSet=, TasksMax=, limit network interfaces, tie a program to certain nftables, just so many. This huge page is but a start: https://www.freedesktop.org/software/systemd/man/latest/syst... !!
Systemd makes excellent excellent use of the kernels namespacing feature to radically boost isolation of programs, to reduce their ability to impact the world in unexpected ways. Even better, you can manage multiple competing realms of apps very very effectively with a hierarchy of scopes, limiting not just program by program but putting programming into nested scopes & limiting scopes, which can insure that system critical services can remain running and adequately provisioned, even while other bulk processes might otherwise demolish the system.
It's been possible to write amazing smart daemons that do all this stuff. But shifting this up to systemd, making it a system responsibility rather than service by service reimplementing has radically enhanced the accessibility of these amazing security & provisioning capabilities built in to the kernel, and given us a shared practice & understanding. Would love to see more articles on this topic! Especially ones that cover what settings folks reach for, which this article alas failed to do at all.