Why should you care about the security of individual services?
Most of us just install Nginx, a database, or a Node.js app and leave it at that, as long as it works. However, in reality, many default services hold “excessive” privileges. If an app suffers from an RCE (Remote Code Execution) vulnerability, a hacker will immediately inherit those permissions. If the service is running as root, your entire server essentially falls into the wrong hands.
After six months of using systemd-analyze security to audit production systems, I’ve found it to be an incredibly powerful tool. It doesn’t just point out vulnerabilities; it provides a specific score. You’ll know exactly where to “lock down” to minimize the risk of privilege escalation.
Quick Start: Score your system security in 5 minutes
You don’t need to install any third-party tools. This utility is already available in systemd-based distributions like Ubuntu, CentOS, or Debian. To quickly check the security status of all running services, run the command:
systemd-analyze security
The output is a summary table containing: UNIT (service name), EXPOSURE (risk level), and STATUS. The score ranges from 0.0 to 10.0. A score of 0.0 means the service is thoroughly sandboxed, while 10.0 is a red alert level.
To take a closer look at a specific service, such as nginx.service, use the command:
systemd-analyze security nginx.service
At this point, systemd will list a detailed checklist with dozens of criteria. Passed items show a (✓), while failed ones show (✗). This serves as your roadmap to begin hardening your system.
Explaining the most “valuable” security parameters
The analysis table might overwhelm you with its many parameters. However, focus on these 5 key items to lower your security score the fastest:
- PrivateTmp: When enabled (yes), the service gets its own private
/tmpdirectory. App A cannot see or interfere with App B’s temporary files. - ProtectSystem: This mode prevents the service from overwriting sensitive directories such as
/usr,/boot, or/etc. - NoNewPrivileges: Ensures that child processes can never gain higher privileges than the parent process, blocking sudo-trick attacks.
- CapabilityBoundingSet: Instead of allowing full root privileges, you grant only the minimum kernel capabilities the service needs.
- ProtectHome: Prevents the service from “reaching into” personal data in the
/homeand/rootdirectories.
Practical Guide: Hardening permissions for a Python service
Suppose I have a custom Python app currently scored at 9.6 (UNSAFE). To harden it, I’ll use the systemctl edit command instead of directly editing the file in /lib/systemd/system/. This ensures the configuration isn’t lost when you update packages.
sudo systemctl edit my-python-app.service
Add the following configuration to the [Service] section:
[Service]
# Never run as root
User=myuser
Group=mygroup
# Enable sandboxing
PrivateTmp=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
MemoryDenyWriteExecute=yes
# Only allow port binding if needed (e.g., port 80/443)
# CapabilityBoundingSet=CAP_NET_BIND_SERVICE
Save and apply the new configuration with the commands:
sudo systemctl daemon-reload
sudo systemctl restart my-python-app.service
Check again with systemd-analyze security, and you’ll see the score drop significantly below 3.0 (SAFE level). This is an impressive result after just a few lines of configuration.
Real-world experience for production deployment
Over-tightening security often leads to “Permission Denied” errors. Don’t rush. Apply a “fix-as-you-go” strategy.
First, enable features one by one. After each change, use the command journalctl -u my-service -f to monitor logs in real-time. If the app cannot write files or connect to the database, you’ll immediately know which option caused it.
Second, don’t obsess over an absolute 0.0 score. Some specific services must retain high privileges to function normally. The ultimate goal is to reduce the attack surface, not to make things difficult for yourself.
Finally, when creating a dedicated user to run the service, use tools like a password generator to ensure high password complexity. This helps prevent brute-force attacks against the service account.
Conclusion
systemd-analyze security is a powerful ally in understanding your server’s “health.” Spending 15 minutes fine-tuning these parameters will make your system many times harder to breach. Good luck with your secure configuration, and may you have many peaceful nights of sleep!

