Most successful server break-ins happen not through clever exploits but through a vulnerability whose patch came out several months earlier. The reason is usually not laziness: updating by hand on a working server is frightening, because apt upgrade sometimes restarts things nobody asked it to restart. Automatic updates settle the question, but they have a poor reputation — deserved exactly to the extent that they are configured in a hurry.
Let us go through a setup where security patches arrive on their own and the PHP version does not change overnight.
Installation
sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades
The dialogue creates /etc/apt/apt.conf.d/20auto-upgrades. Check what came out of it:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
The ones mean "daily". All of it is driven by a systemd timer rather than classic cron:
systemctl list-timers | grep apt
The main thing: security only
The main file is /etc/apt/apt.conf.d/50unattended-upgrades. It contains a list of Allowed-Origins (on Debian, Origins-Pattern), and by default only the security repository is enabled there. Leave it that way.
The temptation to uncomment the -updates line — "let everything update" — is strong. Do not: the updates repository brings new versions, not only fixes, and that is exactly where nocturnal surprises come from. Security and freshness are different jobs, and the second is better done by hand while you are at the keyboard.
If some package must not be updated automatically, there is a blacklist for it:
Unattended-Upgrade::Package-Blacklist {
"mariadb-server";
"php8.3-fpm";
};
Use it deliberately: every line here means "I update this one myself" — and that is a promise you will have to keep.
Reboots
The key line:
Unattended-Upgrade::Automatic-Reboot "false";
Leaving it at false is right for a server with a website: an unannounced reboot at three in the morning is worse than a patch deferred by a day. But that decision has a mandatory second half, and it is the half people forget.
When the kernel, libc or openssl is updated, the system creates the file /var/run/reboot-required. Until a reboot happens, the fixed version is on disk while the old one runs in memory — that is, the vulnerability has not gone anywhere, even though the package counts as updated. Check for it explicitly:
ls -l /var/run/reboot-required
cat /var/run/reboot-required.pkgs
The second file lists exactly what made the reboot necessary. The rule is simple: once you see the flag, plan a window within the next day or two, not "some time".
Libraries are a separate case. openssl gets updated while nginx and PHP-FPM keep running with the old version in memory, and no reboot flag appears at all. Who needs a restart is shown by needrestart:
sudo apt install needrestart
sudo needrestart -b
Just put it in "report, do not ask" mode — otherwise it will start asking questions in the middle of a non-interactive installation and hang it. For that, drop a file into /etc/needrestart/conf.d/ with the line $nrconf{restart} = 'l';.
Check that it works at all
A trial run without installing:
sudo unattended-upgrade --dry-run --debug
The output shows which packages match the rules and which were rejected and why. What actually happened is in the logs:
sudo tail -50 /var/log/unattended-upgrades/unattended-upgrades.log
How many updates are waiting right now:
apt list --upgradable 2>/dev/null | grep -i security
That last command is the most useful of the lot. Configured automatic updates have a habit of breaking quietly: /boot ran out of space, a repository changed its key, the timer was switched off after some manual edit. Outwardly all is well, and patches have not been installed for months.
Space on /boot
A classic: old kernels are not removed, the /boot partition fills up, installing a new kernel fails, and updates stop as a whole. Once every few months it is worth looking:
df -h /boot
sudo apt autoremove --purge
Or enable automatic cleanup in the same 50unattended-upgrades: Remove-Unused-Kernel-Packages "true" and Remove-Unused-Dependencies "true".
What is left for a person
Automatic updates remove the routine but not the watching. Two questions you should be able to answer at any moment: how many security updates are waiting, and whether the reboot flag is set. Both answers are one line on a page, and the whole point is that the line should catch your eye by itself rather than at your initiative once a quarter.