For systemd services, there's also the option to use the service unit directives that systemd provides to limit caps (CapabilityBoundingSet, NoNewPrivileges, etc), filesystem access (ProtectSystem, ReadWritePaths, etc), other "system" access (ProtectProc, PrivateUsers, RestrictNamespaces, etc) and syscalls (SystemCallFilter). I find these an easier and more direct way to harden than writing apparmor / selinux profiles.
`systemd-analyze security <service unit name>` gives a nice list of things to consider tweaking. You don't have to fix everything or pay attention to the exposure ratings, just use it as a guide.
I did this for chrony, haproxy, nginx, tor and unbound on my Debian router. I also have some timer units to run scripts to update DNS blocklists and such, which have the same kind of hardening. For the services, some of them have caveats and can't be fully hardened, eg unbound needs PrivateUsers=no because it fails if it can't find an unbound:unbound user to switch to, even if it was already started as unbound:unbound by systemd. And SystemCallFilter makes it easy to get overzealous and only allow the exact set of syscalls that you see the service making, only to have a service update or glibc update that starts making a new syscall and requires another round of debugging, so do it in moderation :)
`systemd-analyze security <service unit name>` gives a nice list of things to consider tweaking. You don't have to fix everything or pay attention to the exposure ratings, just use it as a guide.
I did this for chrony, haproxy, nginx, tor and unbound on my Debian router. I also have some timer units to run scripts to update DNS blocklists and such, which have the same kind of hardening. For the services, some of them have caveats and can't be fully hardened, eg unbound needs PrivateUsers=no because it fails if it can't find an unbound:unbound user to switch to, even if it was already started as unbound:unbound by systemd. And SystemCallFilter makes it easy to get overzealous and only allow the exact set of syscalls that you see the service making, only to have a service update or glibc update that starts making a new syscall and requires another round of debugging, so do it in moderation :)