TIL #6 - Unattended Upgrades

Intro

The number of my servers (both physical and virtual) seems to be growing and I’ve reached the point where updating and upgrading them manually will just not cut it. I have Ansible playbooks for all of them, but still… You have to run the playbooks manually, or from a cron job, but I wanted to try something that was not available back in the days when I was working with Linux servers daily. Or I was not aware of these tools, being a young sysadmin.

Hence here’s a new post labeled TIL and let’s see how I configured the unattended-upgrades package on Ubuntu.

Overview

In the following sections I’ll walk through the

  • installation of requirements
  • configuration of the package and of course the notification system

Requirements

You need to install the apt-config-auto-update package if you want your Ubuntu system to restart after applying upgrades that require a reboot (typically a kernel upgrade). Run the following command to install it:

sudo apt install apt-config-auto-update

Check if the service is running:

sudo systemctl status unattended-upgrades

Configuration (with notifications)

The prerequisites for SMTP configurations can be found in this post.

Changes to /etc/apt/apt.conf.d/50unattended-upgrades

Uncomment in the Unattended-Upgrade::Allowed-Origins section:

${distro_id}:${distro_codename}-updates

Uncomment and change the following options to receive email notifications when upgrades were installed:

Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Mail "your@email.address";
Unattended-Upgrade::MailReport "on-change";

We need an option added to avoid getting error messages from unattended-update’s mail sending subsystem. Without this option I got errors, your mileage may vary:

Unattended-Upgrade::Sender "your_sender@email.address";

Enabling other sources

If you have some repos not included in the base install, now is the time to add them, if you want those packages auto-updated too.

First, we should get some info about the sources we want to enable. For example, enabling the docker repo:

cat /var/lib/apt/lists/download.docker.com_linux_ubuntu_dists_jammy_InRelease | more

Output:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Architectures: amd64 arm64 armhf s390x ppc64el
Components: stable edge test nightly
Date: Wed, 08 Nov 2023 11:56:23 +0000
Label: Docker CE
Origin: Docker
Suite: jammy
MD5Sum:
 251e4713232a7be49261710f91586547             9709 Release
 cd2ea5f0824c53ce29c56fcb7f69100a              809 nightly/Contents-amd64
 696b27282b146daac383b726466dab80              243 nightly/Contents-amd64.bz2
... (omitted)

What we need is the Origin and Suite values. Put them in the config file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        // Extended Security Maintenance; doesn't necessarily exist for
        // every release and this system may not have it installed, but if
        // available, the policy for updates is such that unattended-upgrades
        // should also install from here by default.
        "${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";
        "Docker:jammy";
};

Finally, do a test run:

sudo unattended-upgrade –dry-run –d -v

Add a task to crontab

If everything is peachy, open the crontab editor:

sudo crontab -e

Run every day at midnight:

0 0 * * * /usr/bin/unattended-upgrade

Conclusion

This setup seems to be working fine for me, the only thing to look out for is to read the emails I get, but that was the whole point of setting up the sending of emails.

I would not use this setup on any mission critical server though, I like to have more control over what gets updated and when, in a production environment. For my use case this is a really convenient solution, but this is just a playground.

And of course, the above config went straight into the Ansible playbook of this server. If I ever need to reinstall the system, it will be ready in a few minutes. I guess you kids have it easy nowadays…