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.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-upgradesunattended-upgrades: /etc/kernel/postinst.d/unattended-upgradesThe 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 --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. 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.
Last updated: Jul 27, 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 …