$ systemd-analyze security service-name
It prints out a long list of hardening flags that can be applied inside of your service, like so: NAME DESCRIPTION EXPOSURE
PrivateNetwork= Service has access to the host's network 0.5
User=/DynamicUser= Service runs as root user 0.4
CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP) Service may change UID/GID identities/capabilities 0.3
CapabilityBoundingSet=~CAP_SYS_ADMIN Service has administrator privileges 0.3
...
Here's what I typically use for a .NET 5 application: WorkingDirectory = /opt/appname/app
ReadWritePaths = /opt/appname/data
UMask = 0077
LockPersonality = yes
NoNewPrivileges = yes
PrivateDevices = yes
PrivateMounts = yes
PrivateTmp = yes
PrivateUsers = yes
ProtectClock = yes
ProtectControlGroups = yes
ProtectHome = yes
ProtectHostname = yes
ProtectKernelLogs = yes
ProtectKernelModules = yes
ProtectKernelTunables = yes
ProtectSystem = strict
RemoveIPC = yes
RestrictAddressFamilies = AF_UNIX AF_INET AF_INET6
RestrictNamespaces = yes
RestrictRealtime = yes
RestrictSUIDSGID = yes
SystemCallArchitectures = native
ProtectProc = invisible
CapabilityBoundingSet =
SystemCallFilter = ~@clock @module @mount @raw-io @reboot @swap @privileged @cpu-emulation @obsolete
ReadWritePaths should be replaced with a combination of DynamicUser + writing local persistent data to $STATE_DIRECTORY, but I'm too lazy to do that yet.See systemd.exec(5) for more.