unattended-upgrades: automatic security updates for Debian
Debian installs security updates automatically: set up unattended-upgrades, control the reboot, and verify it really runs.
Table of contents
“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-listchangesapt-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-upgradesChoose 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-upgradesOn 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
Automatic-Reboot "true" the server then reboots on its own – always set an
Automatic-Reboot-Time when you do: without it, the server reboots immediately
after the upgrade run (the code default is "now"; the 02:00 in 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-required exists. Both are defensible – it just has to be a deliberate
decision.For the automatic reboot to be able to trigger on Debian at all, one building block is
still missing: unattended-upgrades only reboots if the marker file
/var/run/reboot-required exists – and Debian 13 does not create it on kernel
updates by default (the responsible hook comes from an Ubuntu helper package that
doesn’t exist in Debian; only individual packages like dbus set the file themselves).
A two-liner closes the gap:
sudo tee /etc/kernel/postinst.d/zz-reboot-required > /dev/null <<'EOF'
#!/bin/sh
touch /var/run/reboot-required
EOF
sudo chmod +x /etc/kernel/postinst.d/zz-reboot-requiredThe hook runs after every kernel installation and sets the marker file. From now on,
both Automatic-Reboot and the manual check of /var/run/reboot-required work
reliably – without the hook, the automatic reboot would simply never trigger on kernel
updates.
Step 4: Do a dry run
Test what unattended-upgrades would do, without a real installation:
sudo unattended-upgrade --dry-run --debugIn 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-removalsThe 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. Either
Automatic-Reboot is set to "false" (default) – then set it to "true" (step 3) –
or the marker file is never set because the kernel hook
/etc/kernel/postinst.d/zz-reboot-required from step 3 is missing. Without it, Debian
doesn’t create /var/run/reboot-required on kernel updates, and the automatic reboot
never triggers.
/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.
Last updated: Jul 19, 2026
Send feedback: feedback@serverkueche.de
You might also like

Hardening SSH access
Key-based login instead of passwords and no root login: the most important moves to harden the front door to your …

Installing Docker on Debian
Install Docker Engine and Docker Compose cleanly from the official repository – the foundation for most self-hosting …

First steps with a netcup VPS
From a freshly ordered netcup server to a ready-to-use system: SSH login, system updates, a sudo user and the most …