Security Hardening
Lock down your systemd services with security options.
Quick Hardening
The --hardening flag enables a sensible set of security options:
mkunit service myapp \
--exec "./server" \
--hardening \
--install
This adds the following to your unit file:
[Service]
# Filesystem protection
ProtectSystem=strict
ProtectHome=read-only
PrivateTmp=yes
ReadWritePaths=/var/lib/myapp
# Privilege restrictions
NoNewPrivileges=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
# Network restrictions (if no network needed)
# PrivateNetwork=yes
# Additional isolation
ProtectHostname=yes
ProtectClock=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RemoveIPC=yes
What Each Option Does
Filesystem Protection
| Option | Effect |
|---|---|
ProtectSystem=strict |
Makes /usr, /boot, /efi, and /etc read-only |
ProtectHome=read-only |
Makes /home, /root, /run/user read-only |
PrivateTmp=yes |
Private /tmp and /var/tmp directories |
ReadWritePaths= |
Explicitly allow writing to specific paths |
Privilege Restrictions
| Option | Effect |
|---|---|
NoNewPrivileges=yes |
Prevents gaining new privileges via setuid/setgid |
PrivateDevices=yes |
No access to physical devices |
ProtectKernelTunables=yes |
No access to /proc and /sys kernel variables |
ProtectKernelModules=yes |
Cannot load kernel modules |
Additional Isolation
| Option | Effect |
|---|---|
ProtectHostname=yes |
Cannot change hostname |
ProtectClock=yes |
Cannot change system clock |
RestrictRealtime=yes |
Cannot use realtime scheduling |
PrivateNetwork=yes |
Isolated network namespace (no network access) |
Customizing Hardening
After creating a service with --hardening, you can edit it to
fine-tune the security options:
# Create with hardening
mkunit service myapp --exec "./server" --hardening --install
# Edit to customize
mkunit edit myapp
Allow Network Access
By default, --hardening keeps network access. To explicitly deny:
[Service]
PrivateNetwork=yes
Allow Writing to Specific Directories
[Service]
ProtectSystem=strict
ReadWritePaths=/var/lib/myapp /var/log/myapp
Allow Device Access
For services that need hardware access:
[Service]
PrivateDevices=no
DeviceAllow=/dev/ttyUSB0 rw
Capability-Based Security
For services that need specific privileges without running as root:
mkunit service myapp \
--exec "./server" \
--user myapp \
--cap-add NET_BIND_SERVICE \
--cap-drop ALL \
--install
This generates:
[Service]
User=myapp
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
Common Capability Needs
| Capability | Use Case |
|---|---|
CAP_NET_BIND_SERVICE |
Bind to ports below 1024 |
CAP_NET_RAW |
Raw network access (ping, packet capture) |
CAP_SYS_TIME |
Set system clock |
CAP_CHOWN |
Change file ownership |
Security Score
Check your service's security score with systemd-analyze:
# Check security exposure score (lower is better)
systemd-analyze security myapp.service
# See detailed breakdown
systemd-analyze security myapp.service --no-pager
A well-hardened service should score below 2.0.
Example: Hardened Web Application
sudo mkunit service webapp \
--exec "/opt/webapp/bin/server" \
--workdir /opt/webapp \
--user webapp \
--group webapp \
--hardening \
--system \
--install
Then edit to allow specific paths:
[Service]
# Allow writing to data and log directories
ReadWritePaths=/var/lib/webapp /var/log/webapp
# Allow reading SSL certificates
ReadOnlyPaths=/etc/ssl/certs
Example: Hardened Database Backup
sudo mkunit service db-backup \
--exec "/usr/local/bin/backup-db.sh" \
--type oneshot \
--user backup \
--hardening \
--system \
--install
[Service]
# Allow writing to backup directory
ReadWritePaths=/var/backups/db
# Allow reading database socket
ReadOnlyPaths=/var/run/postgresql
It's easier to start with --hardening and add permissions as needed
than to try to lock down an already-permissive service. Check logs when the
service fails - permission errors will indicate what needs to be allowed.
See Also
- service command - All service options
- validate command - Check for security issues
man systemd.exec- Full security options documentation