Why Automate Security Updates
If you have 5 VMs and you're manually running apt update && apt upgrade on each one every week, you're either lying or you have more discipline than anyone I've met. The reality: patches pile up, you forget, and one day a known CVE hits an unpatched service.
Unattended-upgrades solves this by automatically installing security patches from your distro's security repository. It only applies security fixes — not feature updates, not kernel upgrades, not anything that changes behavior. It does the boring, critical work of keeping your systems patched.
What it does:
- Checks for security updates daily (configurable)
- Downloads and installs them automatically
- Cleans up unused packages (optional)
- Sends email notifications (optional)
- Does NOT reboot automatically (by default — and we're keeping it that way)
What it does NOT do:
- Upgrade to new distro versions
- Update Docker container images
- Update packages from third-party PPAs (unless you configure it to)
- Reboot the system (unless you explicitly enable it)
Step 1: Install unattended-upgrades
On Ubuntu, unattended-upgrades is usually pre-installed but may not be enabled. On Debian, you may need to install it. This command covers both:
sudo apt update && sudo apt install unattended-upgrades apt-listchanges -yStep 1b: Verify Installation
Check that the package is installed and the service is present:
dpkg -l | grep unattended-upgrades && echo '---' && systemctl status unattended-upgrades | head -5Expected Output
You should see the package listed (ii = installed) and the service showing "active" or "loaded".
If the service shows "inactive", that's OK — it runs on a timer, not continuously. Check the timer:
systemctl list-timers | grep unattended
Step 2: Enable Automatic Updates
Create or update the auto-upgrades config file. This tells apt to check for and install updates daily:
sudo tee /etc/apt/apt.conf.d/20auto-upgrades << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
EOFWhat Each Line Does
- Update-Package-Lists "1" — run apt update once per day to refresh the package list
- Unattended-Upgrade "1" — run unattended-upgrade once per day to install available security patches
- Download-Upgradeable-Packages "1" — pre-download packages (so the install is faster)
- AutocleanInterval "7" — clean up downloaded package files older than 7 days (saves disk space)
Step 3: Configure What Gets Updated
Back up the default config, then edit the main configuration file:
sudo cp /etc/apt/apt.conf.d/50unattended-upgrades /etc/apt/apt.conf.d/50unattended-upgrades.bakStep 3b: Review Allowed Origins
Check which update sources are enabled. By default, only security updates are allowed — this is what we want:
grep -A 20 'Allowed-Origins' /etc/apt/apt.conf.d/50unattended-upgrades | grep -v '^//' | head -15Expected Output
You should see lines like:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
The "-security" lines are the important ones. These are the official security repositories for your distro. Do NOT add "-updates" or "-backports" unless you explicitly want non-security changes applied automatically.
If you see these lines commented out (prefixed with //), uncomment the security ones:
sudo sed -i 's|^//.*"\${distro_id}:\${distro_codename}-security"| "${distro_id}:${distro_codename}-security"|' /etc/apt/apt.conf.d/50unattended-upgrades
Step 4: Configure Recommended Settings
Apply these settings in /etc/apt/apt.conf.d/50unattended-upgrades. Each one is explained:
Remove unused kernel packages and dependencies automatically (keeps disk clean):
sudo sed -i 's|^//Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"|Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"|' /etc/apt/apt.conf.d/50unattended-upgrades
sudo sed -i 's|^//Unattended-Upgrade::Remove-Unused-Dependencies "false"|Unattended-Upgrade::Remove-Unused-Dependencies "true"|' /etc/apt/apt.conf.d/50unattended-upgradesStep 4b: Disable Automatic Reboot
Make sure automatic reboot is disabled. Some updates (kernel patches) require a reboot, but we want to control when that happens:
grep 'Automatic-Reboot' /etc/apt/apt.conf.d/50unattended-upgrades | grep -v '^//'Expected Output
You should see:
Unattended-Upgrade::Automatic-Reboot "false";
If this line is commented out or missing, the default is false — so you're fine. If it's set to "true", change it:
sudo sed -i 's|Unattended-Upgrade::Automatic-Reboot "true"|Unattended-Upgrade::Automatic-Reboot "false"|' /etc/apt/apt.conf.d/50unattended-upgrades
You can check if a reboot is needed anytime with:
[ -f /var/run/reboot-required ] && echo 'REBOOT NEEDED' || echo 'No reboot needed'
Step 5: Test With a Dry Run
Run unattended-upgrades in dry-run mode to verify your configuration without actually installing anything. This shows what WOULD be installed:
sudo unattended-upgrades --dry-run --debug 2>&1 | tail -30Validate: What You Should See
You should see output that includes:
- Which packages would be upgraded (if any are available)
- The allowed origins being checked
- "No packages found that can be upgraded unattended" (if your system is already up to date)
- No errors
If you see errors about allowed origins or sources, go back to Step 3 and check the Allowed-Origins config.
If you see "The list of kept packages can't be resolved" — there's a dependency conflict. Run: sudo apt --fix-broken install
Step 6: Verify the Timer Is Active
unattended-upgrades runs via a systemd timer. Make sure it's active:
systemctl list-timers --all | grep -E 'unattended|apt'Expected Output
You should see timers like:
apt-daily.timer — runs apt update
apt-daily-upgrade.timer — runs unattended-upgrades
Both should show NEXT and LAST timestamps indicating they're scheduled. If either is missing:
sudo systemctl enable --now apt-daily.timer
sudo systemctl enable --now apt-daily-upgrade.timer
Step 7: Check the Logs
After the system runs its first automatic update (within 24 hours), you can check what happened:
ls -la /var/log/unattended-upgrades/ 2>/dev/null && echo '---' && cat /var/log/unattended-upgrades/unattended-upgrades.log 2>/dev/null | tail -20 || echo 'No logs yet — check back after the first scheduled run'Optional: Email Notifications
To receive email when updates are applied, you need a working mail setup on the server (mailutils + an SMTP relay or local MTA). If you have that:
Uncomment and set the mail recipient in 50unattended-upgrades:
sudo sed -i 's|^//Unattended-Upgrade::Mail ""|Unattended-Upgrade::Mail "[email protected]"|' /etc/apt/apt.conf.d/50unattended-upgrades
sudo sed -i 's|^//Unattended-Upgrade::MailReport "on-change"|Unattended-Upgrade::MailReport "on-change"|' /etc/apt/apt.conf.d/50unattended-upgrades
To test email delivery: echo 'test' | mail -s 'unattended-upgrades test' [email protected]
If mail isn't configured on this server, skip this step. The logs in /var/log/unattended-upgrades/ serve the same purpose.
How to Undo Everything
To disable automatic updates:
1. Disable the timers:
sudo systemctl disable apt-daily.timer
sudo systemctl disable apt-daily-upgrade.timer
2. Or remove the package entirely:
sudo apt remove unattended-upgrades -y
3. Restore the original config if you backed it up:
sudo cp /etc/apt/apt.conf.d/50unattended-upgrades.bak /etc/apt/apt.conf.d/50unattended-upgrades
Your system will still receive updates — you'll just need to run apt update && apt upgrade manually.