Skip to content
Launch offerNew accounts: we double your first deposit of $100 or more, up to $250 bonus.Claim my bonus
LiteKeep
Sign inDeploy a server

Step-by-step tutorial, 2026

Unattended upgrades on Ubuntu. And proof they really run.

Our own server said “update daily” in its config. It had never installed a single update by itself. Here’s how we found out, and how to check yours in a minute.

  • 12 min read
  • 7 chapters
  • Updated

What the config said

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

Daily. Looks fine.

What could run

apt-daily.timer          masked
apt-daily-upgrade.timer  masked

Linked to /dev/null. Never starts.

After we unmasked them

01:15  Starting unattended upgrades script
next   06:38 UTC

Running every day.

The short answer

Ubuntu installs security updates by itself through the unattended-upgrades package, once a day. Check it with systemctl is-enabled apt-daily.timer apt-daily-upgrade.timer (both should say enabled) and look for a recent run in /var/log/unattended-upgrades/unattended-upgrades.log.

If a timer says masked, nothing installs, whatever the config files say. Fix it with sudo systemctl unmask and enable --now on both. Our free checker below tests all of it from one paste.

Every guide to automatic updates on Ubuntu says the same thing: install unattended-upgrades, set two values to “1”, done.

Our server had both values set to “1”. It had never run. No log file, no updates, nothing but the ones we’d installed by hand.

The reason took one command to find. The server’s image had masked the two systemd timers that start the updates. A masked unit can’t start at all, so the config files were describing a schedule nobody ran.

This tutorial sets automatic updates up properly, and then proves they work. That second part is the one most guides skip.

In this guide you’ll learn

  • A free checker: one read-only command, one paste, a clear answer
  • The masked-timer trap we found on our own server
  • The setup, step by step, with a dry run before the real one
  • What it installs by default, and how to add Docker or other repos
  • Reboots and restarts: when they happen, and when they can’t help
  • How to tell it ran, every day, without logging in to look

Chapter 1

The short answer

Automatic updates need three things to be true at once. Most guides check only the first two.

What has to be true for updates to install by themselves
CheckWhereGood answer
Installeddpkg -s unattended-upgradesStatus: install ok installed
Scheduled/etc/apt/apt.conf.d/20auto-upgradesBoth values "1"
Able to runsystemctl is-enabled apt-daily.timer apt-daily-upgrade.timerenabled, enabled
Has run/var/log/unattended-upgrades/unattended-upgrades.logA run from today or yesterday

On a standard Ubuntu server, the package is installed by default and security updates are switched on. Custom and minimal images are where it goes wrong.

Setting up a new server? Deploy a Lite 2, run the checker below in its first minute, and you know your updates are real from day one. It bills by the hour, so testing this costs cents.

Chapter 2

Check your server in one paste

The block below only reads. It prints one labelled line per check. Paste the result and the checker tells you what works, what doesn’t, and the exact fix.

1. Run this on your server
echo "installed $(dpkg -s unattended-upgrades >/dev/null 2>&1 && echo yes || echo no)"
for t in apt-daily.timer apt-daily-upgrade.timer; do echo "timer $t $(systemctl is-enabled $t 2>&1)"; done
apt-config dump APT::Periodic | sed 's/^/periodic /'
echo "kernels $(ls /boot 2>/dev/null | grep -c '^vmlinuz')"
echo "reboot $([ -f /var/run/reboot-required ] && echo yes || echo no)"
echo "lastrun $(sudo grep -h 'Starting unattended upgrades script' /var/log/unattended-upgrades/unattended-upgrades.log 2>/dev/null | tail -n 1 | cut -c1-10)"
echo "today $(date -u +%F)"

Read-only: it changes nothing. It asks for sudo once, to read the update log.

No server handy?

Run the block, then paste its output on the left.

Click “Load our server before the fix” to see the real output that started this tutorial: everything looks switched on, and nothing has ever run.

Chapter 3

What we found on our own server

We run the same checks on our own Ubuntu 22.04 server that we’re asking you to run. Here’s what they showed on 24 October 2026.

Our server, before and after the fix
BeforeAfter
20auto-upgradesBoth "1"Both "1"
apt-daily.timermaskedenabled
apt-daily-upgrade.timermaskedenabled
Update logDid not existFirst run 01:15 UTC
Updates installed by itselfNone, everDaily from then on

Both timers were links to /dev/null, created when the image was built. That’s what masking is: the unit is linked to /dev/null so it can’t be started, even by hand. It shows up on other images too.

We also found an empty /boot. That server starts its kernel from outside, so apt has no kernel to update. Kernel fixes on a server like that come from the platform, not from you.

Chapter 4

Set it up, step by step

Works on Ubuntu 22.04, 24.04 and later. Each step is safe to repeat.

  1. Install the package

    sudo apt update
    sudo apt install unattended-upgrades
  2. Switch on the schedule

    sudo dpkg-reconfigure -plow unattended-upgrades

    Answer Yes. Then check cat /etc/apt/apt.conf.d/20auto-upgrades shows both values as “1” (every day).

  3. Make sure the timers can run

    sudo systemctl unmask apt-daily.timer apt-daily-upgrade.timer
    sudo systemctl enable --now apt-daily.timer apt-daily-upgrade.timer
    systemctl list-timers 'apt-daily*'

    The last command should list both timers with a time under NEXT. If they weren’t masked, the first line does nothing.

  4. Dry run

    sudo unattended-upgrade -v --dry-run

    Shows which sources it allows and what it would install, without installing anything.

  5. First real run

    sudo unattended-upgrade -v

    This creates the log. Ours said “No packages found that can be upgraded unattended”, which was correct: we were already up to date on security fixes.

On our 22.04 server the timers fire at 06:00 and 18:00 for the download and 06:00 for the install, each with a random delay (up to 12 hours and 60 minutes), so thousands of servers don’t hit the mirrors at once. A missed run catches up after boot.

Chapter 5

What it installs, and what it doesn’t

The rules live in the file 50unattended-upgrades, in /etc/apt/apt.conf.d/, under Allowed-Origins.

  • By default: security updates. The -updates, -proposed and -backports lines are commented out.
  • Our proof: nano and tmux had newer versions waiting in jammy-updates. The run skipped both, because neither was a security fix.
  • Other repositories are ignored. Adding a repo does not make unattended-upgrades consider it. You have to list it.

Adding Docker’s repository

Docker’s repository identifies itself as Origin: Docker, with the Ubuntu codename as the suite, so the line is:

Unattended-Upgrade::Allowed-Origins {
    // ...the existing lines...
    "Docker:${distro_codename}";
};

Holding a package back

Unattended-Upgrade::Package-Blacklist {
    "postgresql-16$";
};

Entries are regular expressions, so end the name with $ to match only that package. Holding back one package can also block updates that depend on it.

Chapter 6

Reboots and restarts

Some updates only take effect after a restart. Ubuntu flags it with the file /var/run/reboot-required.

  1. See if one is waitingHow to check: cat /var/run/reboot-required.pkgs lists the packages asking for it.
  2. Automatic rebootsHow to check: Off by default. To allow them at a quiet hour, set Unattended-Upgrade::Automatic-Reboot "true"; and Unattended-Upgrade::Automatic-Reboot-Time "04:00"; in 50unattended-upgrades. Without a time, the default is “now”.
  3. Logged-in usersHow to check: Automatic-Reboot-WithUsers defaults to true, so it reboots even while someone is logged in. Set it to false if that would hurt.
  4. Services, not the whole serverHow to check: From Ubuntu 24.04, needrestart restarts affected services automatically. On 22.04, run sudo needrestart -r l after updates to list services still running old code.

Chapter 7

How to tell it ran

Once a week, or from a monitoring script, look at the evidence instead of the config.

Where unattended-upgrades leaves evidence
Look atWhat it tells you
/var/log/unattended-upgrades/unattended-upgrades.logWhat it decided: allowed sources, packages installed or skipped
/var/log/unattended-upgrades/unattended-upgrades-dpkg.logThe raw install output, including errors
journalctl -u apt-daily-upgrade.serviceWhether the timer actually started it
systemctl list-timers 'apt-daily*'When it last ran and will run next

Want an email instead? Set Unattended-Upgrade::Mail to your address. It needs a working mail client on the server, which most VPSes don’t have out of the box.

MythIf 20auto-upgrades says "1", updates are on.

Fact

Only if both timers can run. Ours said “1” and never ran.

MythAutomatic updates will break my server.

Fact

The default installs security fixes only, from Ubuntu’s own archive. The risky parts, other repos and automatic reboots, are off until you turn them on.

MythIt patches the kernel too, so I never need to reboot.

Fact

A new kernel package needs a reboot to load. And if the platform supplies the kernel, apt never touches it.

Now it’s your move

Automatic updates are one of the cheapest security wins on a server, as long as they actually run. Check the timers, check the log, and run the checker again after any rebuild.

Next, lock down logins with our SSH hardening tutorial, or see the full VPS security guide.

Want a server that patches itself from day one? Deploy a Lite, run the setup above in five minutes, and let it look after itself. Billed by the hour, never more than the monthly price.