Set and Forget: Automating Ubuntu Updates with Unattended Upgrades

Patching a Linux box every few weeks is one of those chores that drifts to the bottom of the to-do list, especially when you have a few machines to maintain. Ubuntu ships with a tool called unattended-upgrades that quietly takes care of security fixes in the background, and with a few configuration tweaks it can run a near hands-off patching routine on laptops, home servers, and small office boxes. The same package is used by Canonical on their own cloud images, so the configuration patterns are well understood and surprisingly flexible for an open source utility.

For Australian users the case for automation is even stronger. The Australian Cyber Security Centre lists patching as one of the core mitigations in its Essential Eight maturity model, and small businesses handling data under the Privacy Act 1988 are expected to keep their systems reasonably current. Add in the realities of National Broadband Network connections with their sometimes modest upload speeds, the wide range of time zones from Perth to Brisbane, and the steady stream of long weekends and public holidays, and a manual update routine tends to slip. Letting unattended-upgrades do the heavy lifting during off-peak hours keeps machines secure without you having to remember to log in.

This walkthrough covers the package itself, the main configuration files under /etc/apt/apt.conf.d/, how to schedule and stagger jobs, how to handle reboots on machines that need them, and a few local tweaks that make the routine behave well on NBN links and inside Australian business environments. Everything applies to current Ubuntu Server and Ubuntu Desktop releases, including 22.04 LTS, 24.04 LTS, and the interim versions in between.

Installing and Enabling the Package

The unattended-upgrades package lives in the standard Ubuntu repositories, so it is usually a single apt command away. On a fresh install you might find that it is already present, because Ubuntu Server images include it by default for security patches. If you are on a minimal cloud image, a desktop, or an older install where it was removed, install it with sudo apt install unattended-upgrades apt-listchanges. The apt-listchanges companion is handy because it shows you a brief summary of what changed before each batch of updates, which makes log reviews far easier.

Once installed, run sudo dpkg-reconfigure --priority=low unattended-upgrades to be prompted about enabling automatic updates. Answering Yes writes a basic schedule into /etc/apt/apt.conf.d/20auto-upgrades and turns the systemd timer on. You can also do this manually by creating the timer entry yourself, but the reconfigure route is the gentlest way to get started. After that, check the timer with systemctl status apt-daily.timer and systemctl status apt-daily-upgrade.timer. Both should show Active: active (waiting), which means the job is armed and waiting for its next window.

It is worth taking a look at the unit files to understand what actually runs. apt-daily.timer triggers apt-daily.service, which refreshes the package index, and apt-daily-upgrade.timer triggers apt-daily-upgrade.service, which performs the upgrade. Both are randomised within a time window so that thousands of machines on the internet do not hit the mirrors at exactly the same second. That is particularly relevant in Australia, where our relatively small pool of Ubuntu mirror traffic can spike during northern-hemisphere business hours.

Choosing Which Updates to Install

The main configuration file lives at /etc/apt/apt.conf.d/50unattended-upgrades, and it is here you decide what gets applied automatically. By default Ubuntu only enables the -security and -updates pockets, which means you will receive security patches and bug-fix backports but not new feature releases. That default is a sensible starting point for servers and for most desktops, and it lines up with what the ACSC recommends for organisations that want stable behaviour.

If you want broader coverage, the file uses simple patterns. Uncommenting the lines that begin with the Ubuntu archive hostnames and the matching -updates and -proposed pockets turns on more frequent patches. Adding -backports pulls in newer versions of certain applications. For a home lab in Perth or a small studio in Surry Hills, a wider net is usually fine. For a production box holding customer data, sticking to -security is the safer choice. Each stanza also accepts a list of packages to exclude, and you can use that to keep certain kernels, Docker versions, or proprietary drivers from being upgraded without manual review.

Blacklisting is done by adding a package name to the Unattended-Upgrade::Package-Blacklist block. For example, adding "linux-image-generic" there will stop kernel upgrades from being applied automatically, which is occasionally useful if you run custom out-of-tree modules such as certain virtualisation drivers. There is also a -NeverAutoRemove list if you have packages you want to keep around even when nothing depends on them. After any edit, run sudo unattended-upgrades --dry-run --debug to confirm your patterns match what you expect, without actually installing anything.

Scheduling Around Australian Time Zones

By default the daily timers run on a randomised schedule anchored to the system clock, which on most Australian machines will be set to AEST, AEDT, ACST, or AWST depending on where the box lives. You can see the current value with timedatectl. The default windows are usually early in the morning UTC, which translates to mid-afternoon on the east coast and lunchtime in Western Australia. That is fine for desktops, but for a home server in Adelaide that runs scheduled jobs at certain hours, you may prefer the upgrade to run late at night when nobody is using it.

The simplest way to shift the window is to override the OnCalendar directive. Drop a snippet into /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf with an empty OnCalendar line followed by OnCalendar=--* 02:30 and a RandomizedDelaySec=15m setting. The empty line clears the inherited schedule, and the next line sets a new 02:30 local time trigger. Reload systemd with sudo systemctl daemon-reload, then sudo systemctl restart apt-daily-upgrade.timer. You can also adjust the randomisation window to spread the load if you manage several machines. For a multi-site setup spanning Sydney, Melbourne, and Brisbane offices, staggering timers by an hour or two prevents every site from saturating your shared link at once.

For an extra layer of control, edit /etc/apt/apt.conf.d/20auto-upgrades and set APT::Periodic::Unattended-Upgrade to a value such as 3 to run every three days instead of daily, or 7 for weekly. Weekly is a good fit for low-bandwidth sites or machines on metered connections, and it still keeps security exposure to a week at most. If you are running on a 4G or 5G backup link in regional Queensland, weekly may be a much friendlier choice than daily.

Handling Reboots Without Surprise Downtime

Kernel updates, libvirt host changes, and certain glibc patches do not fully take effect until a reboot. Unattended-upgrades has an Automatic-Reboot toggle in 50unattended-upgrades that you can switch to true, but turning it on blindly is rarely wise. A more useful pattern is to leave automatic reboot off and instead install needrestart, which scans running processes after an upgrade and tells you which services need restarting without a full reboot. This works particularly well for web servers, Docker hosts, and other long-running daemons that can be restarted on their own.

If you do want automatic reboots, configure them for a quiet window such as 03:00 local time using Automatic-Reboot-Time. This pairs well with a server in a regional data centre or a home lab that nobody touches after midnight. Add Unattended-Upgrade::Automatic-Reboot-WithUsers to false so a logged-in user does not get kicked off mid-task, and set Unattended-Upgrade::Automatic-Reboot-Allow-NTP-Reconfigure to true if the box has problems keeping time after sleep. For laptops, prefer no automatic reboot at all, because closing the lid will simply cancel it and you will be back to manual reviews.

A practical approach for a small business is to keep automatic reboots disabled and let unattended-upgrades record what needs a restart in /var/run/reboot-required. A short daily cron job or a systemd timer can check for that flag, send a notification, and only reboot the box during a defined maintenance window. That gives you the security of regular patching without the surprise of a remote machine coming back at 5pm on a Friday with all of its services half-loaded.

Notifications, Logs, and Email Alerts

Automation without visibility is a recipe for quiet failure. The unattended-upgrades package writes detailed logs to /var/log/unattended-upgrades/, with one file per run named after the date. Each entry lists every package fetched and installed, any failures, and the exit code of the underlying apt processes. Reading a week of these files is a quick way to spot repositories that are misbehaving, mirrors that are slow, or packages that keep failing to upgrade.

For most Australian users a daily glance is enough, but a small business with obligations under the Notifiable Data Breaches scheme will want a record. The simplest way to keep a paper trail is to install apticron. Configure it with your SMTP details in /etc/apticron/apticron.conf, set EMAIL= to a monitored address, and you will receive a short summary every time new packages are pending. Pair this with a log shipping agent such as rsyslog forwarding to a central syslog server, and you have an audit trail that satisfies most compliance questions.

On a home network the easier path is to point apticron at a free webmail address and skim the daily digest from your phone. Combined with a Uptime Kuma or Healthchecks.io ping after each run, you can be confident that patching is actually happening. There is also the option of using the unattended-upgrades syslog facility, which can feed into journald on systemd systems. Querying it with journalctl -u apt-daily-upgrade.service --since today is a quick way to confirm the most recent run finished cleanly.

Local Tweaks for Australian Conditions

A few small adjustments make unattended-upgrades behave better in the Australian context. First, pick mirrors that are actually close to you. The default archive.ubuntu.com route is fine, but pointing your sources list at au.archive.ubuntu.com or one of the university mirrors reduces latency on long-haul links. For users in Hobart, Launceston, or Cairns this can shave a few minutes off each run, which matters when the upgrade is downloading hundreds of megabytes of security fixes.

Second, keep an eye on NBN upload speeds if you run a home server. Many FTTN and HFC connections are still asymmetric, and a full security run on a beefy box can push a noticeable amount of log and journal data upstream. Using a local mirror and reducing the download concurrency in a custom /etc/apt/apt.conf.d/99local file with Acquire::Queue-Mode "access" and an Acquire::http::Dl-Limit cap can keep you from saturating the link while someone else in the house is on a video call.

Third, align your schedule with Australian public holidays if you maintain machines for a small business. Australia Day, Anzac Day, and the various state long weekends often coincide with skeleton staff rosters. Pushing upgrades to early Tuesday morning rather than Monday morning means a failed run is more likely to be noticed before the office fills up. The Australian Cyber Security Centre also publishes alerts around major events, and you can add a quick cron check against the ACSC advisory feed to pause upgrades for a day if a critical bulletin lands.

The key thing to remember is that unattended-upgrades trades a one-time configuration cost for months of quiet, automatic protection. The logs, the dry-run command, and the ACSC advisory feed are the three things worth revisiting whenever you have a spare afternoon. With those in place, your Ubuntu fleet stays current while you get on with the rest of the week.