Audit server security
An audit is not a one-off scan after an alert. It is a list of repeatable checks, run on a schedule and written down. Its purpose is to catch drift before it becomes an incident: a forgotten service, an open port, an unused account. Here is a routine for a Debian 13 VPS.
Inventory what runs
sudo ss -lntup
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabled
sudo crontab -l
sudo ls -l /etc/cron.d
getent passwd | awk -F: '$3 >= 1000 {print $1, $3, $6, $7}'Write down every port, service and account. Anything you cannot explain must be understood or disabled. A service whose purpose you ignore is a service you will not patch.
Use Lynis as a starting point
sudo apt install lynis
sudo lynis audit systemLynis reports a hardening index and a list of suggestions. Treat the index as a trend, not an absolute score. Prioritize warnings about SSH, the firewall, updates and permissions. The detailed report stays in /var/log/lynis.log: it describes your system, so do not publish it as-is.
Permissions, accounts and elevation
sudo find / -xdev -perm -4000 -type f 2>/dev/null
sudo find /var/www -xdev -type f -perm -o+w
getent group sudo
sudo chage -l utilisateurCompare the SUID binaries with a fresh install. A world-writable file under /var/www is an entry point. Check that every member of sudo truly needs it, and that service accounts have no interactive shell.
Updates, firewall and exposure
sudo apt update && apt list --upgradable
systemctl status unattended-upgrades
cat /var/run/reboot-required 2>/dev/null
sudo ufw status verbose
sudo fail2ban-client status sshdIn a system container the kernel is shared with the platform: kernel updates belong to the platform, not to your system. Check application packages, pending reboots and firewall rules instead. Compare open ports against the services you expect, not against a generic list.
Verify
Record each check in a dated report:
| Check | Command | Expected |
|---|---|---|
| Ports | ss -lntup |
only intended services |
| Services | systemctl list-unit-files |
no unknown enabled unit |
| SUID | find / -perm -4000 |
stable, justified list |
| Updates | apt list --upgradable |
nothing critical pending |
| Firewall | ufw status verbose |
restrictive default policy |
For every gap, note the fix applied, the ticket opened or the accepted risk with a reason, plus a review date. Automate read-only checks in a script, but do not apply fixes automatically: an unexplained remediation breaks more than it protects.
Run Lynis again after fixes and compare. An audit is done when every gap is fixed, accepted or tracked. Keep a copy of the report off the server if it contains sensitive details, and repeat the routine after any architecture change.
Advertisement
Was this article helpful?
Read next
- Secure a public APIThe minimum layers for an exposed API: TLS, authentication, quotas, validation, CORS and usable logs.
- Encrypt sensitive dataTell apart TLS, application encryption, encrypted backups and key management on a VPS.
- Secure a databaseReduce network exposure, privileges and backup leakage for a MariaDB or PostgreSQL database.