Most successful attacks on servers use known vulnerabilities, ones that were already fixed by an update the server never received. Patch management is the routine that closes that gap: knowing what needs updating, applying it reliably, and making sure the fix is actually running. Here’s a practical approach for one VPS up to a small fleet.
CVEs in a nutshell
A CVE (Common Vulnerabilities and Exposures) ID, like CVE-2024-6387, identifies a publicly known vulnerability. Most come with a CVSS score (0–10):
| CVSS | Severity |
|---|---|
| 9.0–10.0 | Critical |
| 7.0–8.9 | High |
| 4.0–6.9 | Medium |
| 0.1–3.9 | Low |
The score alone doesn’t tell you your risk. Ask:
- Is the vulnerable software installed and running?
- Is it reachable by an attacker (internet-facing, a local user, needs special config)?
- Is it being exploited in the wild? CISA’s Known Exploited Vulnerabilities catalogue and EPSS scores help here.
An exploited bug in OpenSSH, Nginx or your CMS is urgent. A local-only bug in a tool you don’t use can wait for the regular cycle.
Distribution security updates
Your distribution backports security fixes into its package versions. A Debian or Ubuntu package with an old-looking version number can still contain the fix, so don’t judge by version numbers. Use the distribution’s trackers:
- Ubuntu: ubuntu.com/security/cves and
pro fix CVE-… - Debian: security-tracker.debian.org
- RHEL family: errata and
dnf updateinfo
Check pending security updates:
# Ubuntu/Debian
sudo apt update && apt list --upgradable
# RHEL family
sudo dnf updateinfo list security
sudo dnf updateinfo info CVE-2024-6387
Automate the routine
Security updates daily, automatically:
- Ubuntu/Debian: unattended-upgrades. See automatic security updates.
- RHEL family:
dnf-automaticwithupgrade_type = security. See AlmaLinux setup.
Everything else on a schedule (weekly or monthly), in a maintenance window: full upgrades, a reboot, and checks.
Automatic security updates rarely break things, and the risk of not patching is much larger. Exclude only packages you upgrade deliberately (database major versions, kernels on special hardware).
Updates aren’t active until restarted
Updating a package replaces files on disk. Running processes keep using the old code until they restart.
Services and libraries. On Debian/Ubuntu, needrestart lists and restarts services using outdated libraries, such as after an OpenSSL update:
sudo apt install needrestart
sudo needrestart -r l # list
sudo needrestart -r a # restart automatically
RHEL family:
sudo dnf needs-restarting -s # services needing restart
Kernel. Needs a reboot, or live patching:
cat /var/run/reboot-required 2>/dev/null # Ubuntu/Debian
sudo dnf needs-restarting -r # RHEL
Schedule reboots (monthly, or soon after critical kernel CVEs). See upgrade the kernel.
Containers. apt upgrade on the host doesn’t update container images. Rebuild and redeploy images regularly, using updated base images. Watchtower or CI pipelines can automate this. See Watchtower.
Don’t forget the application layer
Distribution updates don’t cover:
- CMS and plugins: WordPress, its plugins and themes, Joomla, Drupal. These are the most common entry points on web servers. See WordPress hardening.
- Language dependencies: npm, Composer, pip and gem packages. Use
npm audit,composer auditandpip-audit, plus Dependabot or Renovate in your repositories. - Software installed outside the package manager: binaries in
/usr/local/bin, manually installed apps, Docker images. - Control panels and admin tools: phpMyAdmin, Adminer, Portainer.
Keep an inventory of what runs on each server, so you know where to look when a new CVE appears.
Emergency patching workflow
When a critical, exploited CVE hits software you run:
- Confirm exposure: is the version affected? Is the service exposed? (
ss -tlnp,nmapfrom outside.) - Apply the update as soon as it’s available, or a workaround until then: disable the feature, restrict access in the firewall, add a WAF rule.
- Restart the affected services (or reboot), and verify the fixed version is running.
- Check for signs of exploitation if the window was long. See detect a compromised server.
Vulnerability scanning
- Lynis flags vulnerable packages as part of its audit. See Lynis.
- Trivy and Grype scan container images, filesystems and dependency files for known CVEs.
debsecan(Debian) lists CVEs that affect installed packages.
Quick reference
| Task | Command |
|---|---|
| Pending updates | apt list --upgradable / dnf updateinfo list security |
| CVE status (Ubuntu) | pro fix CVE-… |
| Services needing restart | needrestart -r l / dnf needs-restarting -s |
| Reboot needed | /var/run/reboot-required / dnf needs-restarting -r |
| Scan images | trivy image name:tag |
| App dependencies | npm audit, composer audit, pip-audit |
Related: Linux server hardening and apt update errors.