System hardening
Disable unneeded services
Remove or stop packages, daemons, timers, and sockets the server does not need to reduce code, privileges, and exposed behavior.
Every running service adds code and configuration you must trust. If the product does not need it, remove the obligation.
Find what runs
Review enabled systemd units, installed server packages, scheduled jobs, and container workloads:
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabled
Check timers and sockets as well as services. A stopped unit can start again when its socket receives traffic or a scheduled timer fires after the review:
systemctl list-timers
systemctl list-sockets
Confirm ownership before disabling anything. “I don’t recognize it” is not the same as “nothing needs it”. Read what the unit does with systemctl cat exim4, find which package installed a file with dpkg -S, and check whether the application or a backup job depends on it.
Stop, disable, or remove
A default image may enable a mail daemon the application never uses. Stopping it removes the listener now, while disabling or removing it prevents the next reboot from restoring exposure:
sudo systemctl disable --now exim4
If nothing on the server needs the package at all, go one step further and sudo apt purge exim4. A removed package is one less thing to patch, configure, and audit for the life of the server.
Verify the exposure is gone
Recheck listeners afterward and document services the application depends on:
sudo ss -lntup
The mail port should be gone from the list. Reboot the lab machine once and check again — the reboot is what catches a socket or timer quietly reactivating the unit you thought was dead.
Save the enabled-unit and listener evidence for one unneeded service. Disable it, reboot the lab host, and prove the port stays closed while the application’s health checks still pass.
Lesson completed