techweb24.dev
README.md

How to Turn On Automatic Security Updates on Ubuntu Server (unattended-upgrades)

Most hacked servers aren't broken into with clever zero-days. They're running software that was patched weeks ago. When PHP2Shell was disclosed, attacks started within days, and servers that installed security updates automatically were protected before most admins even read the news. Ubuntu can do this for you with a built-in tool called unattended-upgrades. Here's how to set it up properly, test it, and control reboots.

Automatic security updates on Ubuntu with unattended-upgrades
These steps work on Ubuntu Server LTS releases (22.04, 24.04 and 26.04) and on Debian. Run them over SSH as a user with sudo.

Step 1: Install and enable unattended-upgrades

It's preinstalled on most Ubuntu servers, but make sure:

sudo apt update
sudo apt install unattended-upgrades apt-listchanges

# turn it on (choose "Yes" in the dialog)
sudo dpkg-reconfigure -plow unattended-upgrades

This creates /etc/apt/apt.conf.d/20auto-upgrades. Check that it contains:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

The "1" means every day: refresh the package lists, then install updates.

Step 2: Choose what gets updated

The main settings live in /etc/apt/apt.conf.d/50unattended-upgrades. By default only the security pocket is enabled, which is the safest choice for production servers:

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";
//      "${distro_id}:${distro_codename}-updates";
};

Include PHP from the ondrej/php PPA

Many servers get newer PHP versions from ppa:ondrej/php. Updates from PPAs are not installed automatically unless you add them. Add this line inside Allowed-Origins:

        "LP-PPA-ondrej-php:${distro_codename}";

Not sure of the right name for a repository? Run apt-cache policy and look at the o= (origin) and a=/n= values for that repository.

Useful options

// remove old kernels and packages that are no longer needed
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";

// email a report (needs a working mail setup, e.g. msmtp or postfix)
Unattended-Upgrade::Mail "you@example.com";
Unattended-Upgrade::MailReport "only-on-error";

// never auto-update these packages
Unattended-Upgrade::Package-Blacklist {
    "mysql-server";
};

Step 3: Decide how reboots work

Kernel and core library updates only take effect after a reboot. You have three options:

OptionSettingGood for
Reboot automatically at a quiet timeAutomatic-Reboot "true"; + Automatic-Reboot-Time "04:00";Single servers where a minute of downtime at night is fine
Reboot manuallyleave Automatic-Reboot "false";Servers you check regularly
Livepatch (no reboot for kernel fixes)sudo pro attach then sudo pro enable livepatchServers that must stay up. Ubuntu Pro is free for personal use on a few machines

Check whether a server is waiting for a reboot:

[ -f /var/run/reboot-required ] && cat /var/run/reboot-required.pkgs || echo "No reboot needed"

Services like PHP-FPM, Nginx and MySQL are restarted automatically after library updates by needrestart, which is installed by default on recent Ubuntu releases.

Step 4: Test it with a dry run

Don't wait a day to find out if it works. Simulate a run and watch what it would install:

sudo unattended-upgrade --dry-run --debug
Output of unattended-upgrade dry run showing allowed origins and packages to upgrade

Look for the line listing Allowed origins and the packages it would upgrade. If you added the PHP PPA, PHP packages should appear when updates are available.

Step 5: Check that it's running

# when the automatic jobs run next
systemctl list-timers apt-daily.timer apt-daily-upgrade.timer

# what was installed and when
less /var/log/unattended-upgrades/unattended-upgrades.log
grep -h 'Packages that will be upgraded' /var/log/unattended-upgrades/unattended-upgrades.log | tail

By default the upgrade timer runs once a day around 06:00 with a random delay. To pick a time, override the timer:

sudo systemctl edit apt-daily-upgrade.timer
[Timer]
OnCalendar=
OnCalendar=*-*-* 03:30
RandomizedDelaySec=15m

What automatic updates don't cover

  • Software you installed outside apt: Docker images, Composer and npm packages, WordPress and its plugins, and binaries you downloaded manually. Docker containers keep old PHP until you rebuild them.
  • Major version upgrades: moving from PHP 8.1 to 8.3, or from Ubuntu 22.04 to 24.04, is always a manual decision.
  • End-of-life releases: an Ubuntu version that's out of support gets no new security updates at all (unless covered by Ubuntu Pro). Check with pro status or lsb_release -a.

Summary

sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades   # origins, reboot, email
sudo unattended-upgrade --dry-run --debug             # test

Five minutes of setup means the next critical PHP, OpenSSL or kernel fix lands on your server within a day, without you having to remember. Questions about a specific setup? Ask in the comments.

Zubaer Ahammed

Full-stack & Android developer from Bangladesh. Builds web platforms and apps and writes practical tutorials here. zubaer.com

Comments