"Remember to install updates weekly" – this sentence from the maintenance sections of the other tutorials is the first one people forget. That's exactly why the server now takes it over itself: unattended-upgrades installs security updates automatically. That closes the most dangerous gap in self-hosting – the server that runs unpatched for months.
What are we building?
By the end, your Debian 13 automatically pulls security updates daily and installs them without your involvement. You decide whether and when the server reboots for necessary kernel updates, and you know how to verify that the automation really kicks in. What gets automated are security updates and the conservative stable point releases; larger upgrades of your other software stay deliberately in your hands.
Prerequisites
- A hardened server with an active firewall
Step by step
Step 1: Install the package
sudo apt update
sudo apt install -y unattended-upgrades apt-listchanges
apt-listchanges shows the changelogs on updates – useful if you later do check manually what changed.
Step 2: Enable the automation
The simplest way to switch on the daily run:
sudo dpkg-reconfigure -plow unattended-upgrades
Choose Yes in the dialog. That creates the file /etc/apt/apt.conf.d/20auto-upgrades with this content:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
The 1 means "daily": update package lists and run unattended upgrades. It's triggered via the systemd timers apt-daily.timer (package lists) and apt-daily-upgrade.timer (upgrade run) – no separate cron job needed.
Step 3: Define what gets updated
Take a look at /etc/apt/apt.conf.d/50unattended-upgrades:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
On Debian 13, three sources are active in the Origins-Pattern block by default:
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};
The two Debian-Security lines ensure timely security updates – the actual purpose. The first line (label=Debian) covers the conservative stable updates that only arrive with Debian point releases; so it's not a risky rolling update, but well-seasoned. If you really want only security updates, comment out the first line with //.
Two options are worth setting explicitly here. Clean up old kernels/packages automatically, otherwise /boot eventually fills up (Remove-Unused-Kernel-Packages is already the default in code, but only appears commented out in the file – set explicitly, the decision is documented):
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
And the most important point – the automatic reboot:
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
⚠️ Automatic reboot – decide deliberately
Some security updates (especially kernel) only take effect after a reboot. With
Automatic-Reboot "true"the server then reboots on its own – always set anAutomatic-Reboot-Timewhen you do: without it, the server reboots immediately after the upgrade run (the code default is"now"; the02:00in the example file is only a commented-out suggestion). Choose a time with low usage. If you want no automatic reboots, leave the option at"false"and reboot yourself when/var/run/reboot-requiredexists. Both are defensible – it just has to be a deliberate decision.
What does that reboot actually depend on? unattended-upgrades only reboots if the marker file /var/run/reboot-required exists. A bare Debian 13 does not create it on kernel updates – on Ubuntu that hook lives in a helper package that doesn't exist in Debian. The unattended-upgrades package, however, ships its own kernel hook, so there is nothing for you to build. A quick check:
dpkg -S /etc/kernel/postinst.d/unattended-upgrades
unattended-upgrades: /etc/kernel/postinst.d/unattended-upgrades
The hook runs after every kernel installation, sets /var/run/reboot-required and also records the triggering package in /var/run/reboot-required.pkgs. That makes both Automatic-Reboot and the manual check of the file reliable.
On a Debian without unattended-upgrades the file is never created – there, a missing /var/run/reboot-required tells you nothing about whether a reboot is pending (see First steps with a netcup VPS).
Step 4: Do a dry run
Test what unattended-upgrades would do, without a real installation:
sudo unattended-upgrade --dry-run --debug
In the debug output, this line is decisive (on a fresh Debian 13, shortened):
Allowed origins are: origin=Debian,codename=trixie,label=Debian, origin=Debian,codename=trixie,label=Debian-Security, origin=Debian,codename=trixie-security,label=Debian-Security
[...]
No packages found that can be upgraded unattended and no pending auto-removals
The Debian-Security sources must appear there. If something is listed, the configuration applies; if the run finds nothing to do (as above), there's simply no security update pending right now.
When things go wrong
The dry run reports No packages found that can be upgraded unattended. Usually perfectly normal – no security update is currently pending. Check the configuration anyway via the Allowed origins are: line in the --debug run. If no security origins appear there, the Origins-Pattern from step 3 isn't right.
Updates come, but the server never reboots despite a kernel update. Usually Automatic-Reboot is set to "false" (default) – then set it to "true" and give it an Automatic-Reboot-Time (step 3). If the option is right, check the marker file: without /var/run/reboot-required the reboot never triggers. The package's kernel hook is what sets it – dpkg -S /etc/kernel/postinst.d/unattended-upgrades must report it (step 3).
/boot fills up, updates fail. Old kernels pile up. Set Remove-Unused-Kernel-Packages "true" (step 3); clean up once with sudo apt autoremove --purge.
A package is stubbornly held back (kept back). unattended-upgrades doesn't install updates that would remove other packages. You resolve such cases deliberately by hand with sudo apt upgrade and check what happens.
Maintenance & backups
-
Still check anyway: automation doesn't replace attention. Take a monthly look at the log
/var/log/unattended-upgrades/unattended-upgrades.logand occasionally runsudo apt update && sudo apt upgradefor the non-security-critical updates. -
Plan for reboots: if you use automatic reboots, make sure your services survive a reboot cleanly (
restart: unless-stoppedin Docker Compose if you run containers). - No dedicated backup needed, but note whether you enabled automatic reboots – it later explains why the server was briefly gone at night.
This post first appeared on serverkueche.de.
Top comments (0)