Look, let’s be real for a second. You, updating every single package on every single one of your Debian or Ubuntu servers, manually, the day a security patch drops? It’s not going to happen. I don’t care how disciplined you are. You’ll be tired, you’ll be busy, you’ll forget. And that one forgotten box will be the one some script-kiddy uses to pivot into your entire network. The solution isn’t to “try harder”—it’s to automate yourself out of the problem. That’s where unattended-upgrades comes in. It’s the sysadmin’s best friend: a cron job that automatically installs security updates so you can focus on more important things, like figuring out which developer let a plaintext password slip into a public GitHub repo again.

This isn’t magic; it’s a well-understood, if occasionally quirky, package. Let’s set it up so it works for you, not against you.

Installing and Basic Configuration

First, it might not be there. Let’s fix that.

sudo apt update
sudo apt install unattended-upgrades

Boom. Installed. Now, the important part: the config file. Don’t worry, the package maintainers are sensible. They include a sane default that only enables security updates. The main config file is /etc/apt/apt.conf.d/50unattended-upgrades. Open it up. You’ll see a critical section that looks like this:

Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        "${distro_id}ESM:${distro_codename}-security";
//      "${distro_id}:${distro_codename}-updates";
//      "${distro_id}:${distro_codename}-proposed";
//      "${distro_id}:${distro_codename}-backports";
};

See those commented lines? This is the first design choice you need to understand. The default is brilliantly conservative. It only allows automatic upgrades from the -security repository. This is fantastic because it massively reduces the chance that an update from -updates or (heaven forbid) -proposed will automatically break your production application at 3 a.m. Leave those commented out unless you have a specific, masochistic reason to enable them.

How It Actually Works (The Gory Details)

It’s not a daemon; it’s a cron job. Check /etc/cron.daily/apt-compat – it sources a config file that runs unattended-upgrade if it’s enabled. This happens once a day. This is a good thing. You don’t need a service constantly running for this. It wakes up, checks for security updates from the allowed origins, installs them, and even has a hook to automatically restart services (or the whole box) if needed.

Ah, reboots. The dreaded part. Sometimes a security update requires a reboot, like a new kernel or a critical libc update. The config file has a setting for this:

//Unattended-Upgrade::Automatic-Reboot "false";

If you uncomment and set this to "true", the system will reboot automatically if needed. This is a trade-off between ultimate uptime and ultimate security. For a personal server? Maybe set it to true. For a critical production box? You might want to handle that manually during a maintenance window. There’s a related setting, Automatic-Reboot-Time, which defaults to 04:00. Because nothing says “fun” like your production server deciding to reboot itself at the worst possible time. Set it to a time you’re confident is your lowest traffic period.

The “What the Heck Just Happened?” Logs

You can’t have automation without observability. The best place to see what unattended-upgrades has been up to is the log file: /var/log/unattended-upgrades/unattended-upgrades.log. It’s verbose and will tell you exactly what it installed, when, and if anything went wrong. Get in the habit of glancing at it. Another useful one is /var/log/apt/history.log, which records all apt activity, including the automated stuff.

The Edge Cases and Pitfalls (Where the Pain Lives)

  1. It Can Break Things: Yes, even security updates. It’s rare, but it happens. A badly tested security patch can introduce a new bug. This is why the default config is so conservative. You’re trading the small risk of a broken update for the massive, near-certain risk of a catastrophic security breach. It’s a good trade.
  2. DPKG Locks: If you have a long-running apt process you started manually, the automatic upgrade will fail gracefully because it can’t get the dpkg lock. It’ll just try again tomorrow. No big deal.
  3. Config File Changes: You modify your sources.list? You need to make sure your new repositories are added to the Allowed-Origins list in the config, or unattended-upgrades will ignore them.
  4. Holding Back a Package: Sometimes, you know a specific package version will break your world. You can hold it back with sudo apt-mark hold package-name. unattended-upgrades will respectfully leave it alone. Use this power wisely.

The bottom line is this: not enabling unattended-upgrades on an internet-facing Linux system is professional negligence. It’s the single most effective thing you can do to improve your security posture with minimal ongoing effort. Configure it, monitor its logs for a week, and then stop worrying about patching the base OS. You’ve got bigger fish to fry.