How to Enable Automatic Security Updates on Ubuntu

How to Enable Automatic Security Updates on Ubuntu

Firewall configured, SSH on keys, fail2ban running — and a server nobody has updated in eight months. It is the most common state of a forgotten VPS: the perimeter defense is right, but openssl or the kernel carry flaws that are already fixed and public. The classic case is the 2017 Equifax breach, where the Apache Struts patch existed months before the intrusion. On Ubuntu, the unattended-upgrades package fixes this by installing security patches on its own.

What is unattended-upgrades?

What does unattended-upgrades do on Ubuntu?

It is an APT service that downloads and installs updates automatically in the background, from a list of repositories you authorize — by default, only the security ones. It runs from systemd timers (apt-daily and apt-daily-upgrade), so you don't depend on a hand-written cron job.

On recent Ubuntu installs it usually ships installed and enabled, but that varies by image (cloud provider VPS, minimal, flavors). Check before assuming.

Step 1: install and enable it

sudo apt update
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

The last command opens a screen asking whether to install updates automatically. Answer Yes. It writes the file /etc/apt/apt.conf.d/20auto-upgrades:

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

The values mean "every 1 day": refresh the package lists and run unattended-upgrade.

Step 2: choose what gets updated automatically

The main configuration lives in /etc/apt/apt.conf.d/50unattended-upgrades. Open it with sudo nano and look for the Allowed-Origins block:

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

Lines starting with // are disabled. The default is to keep only -security active (plus the ESM channels if you use Ubuntu Pro). Leaving -updates commented out is the conservative choice: it brings non-security bug fixes that are more likely to change behavior. Never enable -proposed on a server.

Can automatic updates break the server?

They can, but the risk is much lower with the security channel only, because those patches are small and aimed at fixing the flaw without changing functionality. Even so, on critical production systems, keep a backup and test in a staging environment. The 3-2-1 backup rule applies here too.

Step 3: set up automatic reboots

Kernel patches and library patches such as glibc only take effect after a reboot. When one is needed, the system creates the file /var/run/reboot-required. To let unattended-upgrades handle it during low-traffic hours, adjust the same file:

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";

With this, the server only restarts when needed, at 3 AM in the server's time zone, and skips the reboot if a user is logged in. If you can't accept any interruption, leave Automatic-Reboot "false" and schedule a manual maintenance window, checking the reboot-required file every week.

Two useful options in the same file:

Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Mail "[email protected]";

The first cleans up leftover dependencies. The second emails a report, but only works if the server has a configured MTA (such as postfix or msmtp).

Step 4: test without applying anything

sudo unattended-upgrade --dry-run --debug

--dry-run simulates the run and shows which packages would be upgraded, without installing them. In debug mode you see which origins were accepted. If something like "Packages that will be upgraded" shows up, the setup is working. To check that the timers are active:

systemctl list-timers apt-daily.timer apt-daily-upgrade.timer

Step 5: check the logs

sudo tail -n 50 /var/log/unattended-upgrades/unattended-upgrades.log
ls /var/run/reboot-required

The log shows each run, with installed packages and errors. If ls says the file doesn't exist, no reboot is pending. A server that keeps that file around for weeks has patches installed but not yet active in the running kernel.

What unattended-upgrades does not cover

  • Software outside APT: binaries downloaded by hand, Docker images, pip/npm packages and snaps follow a different update logic.
  • Containers: the host gets updated, but container images need to be rebuilt.
  • Services that need a restart: without a reboot, a daemon can keep running the old library in memory. The needrestart package helps list what to restart.
  • Insecure configuration: a patch doesn't fix a weak password or a needlessly open port. For that, see the UFW firewall tutorial and the guide to fail2ban against brute force.

The bigger lesson

Many intrusions don't use a new flaw: they use a flaw with a published fix that nobody installed. Automating the security patch takes that decision out of human effort and puts it into a routine that runs by itself. It is the cheapest item on the hardening list, and worth as much as well-configured SSH.

If you want to go deeper on what happens when the patch isn't installed, read how to protect yourself from ransomware.

Sources consulted

  • unattended-upgrade manual pages and comments in the 50unattended-upgrades file (Debian/Ubuntu package)
  • Ubuntu Server documentation on automatic updates

Comments