If you follow current IT security vulnerabilities and security breaches, you’ll probably agree that keeping systems up to date is becoming increasingly important. Unattended upgrades for Debian/Ubuntu have been around for as long as I can remember and it’s a pretty easy way to achieve that. Here’s how.
Installation
You will need to install unattended-upgrades
apt-get install unattended-upgrades
I also install apt-config-auto-update which is the replacement for update-notifier-common and allows automatic reboot. Then I install apt-listchanges and postfix (local-only configuration, you may want to install bsd-mailx or mailutils instead)
Configuration
Use the following command to enable automatic updates:
dpkg-reconfigure --priority=low unattended-upgrades
Now take a look at: /etc/apt/apt.conf.d/50unattended-upgrades. E.g.
Unattended-Upgrade::Origins-Pattern {
//"origin=Debian,codename=${distro_codename}-updates";
//"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};
Origins-Pattern is the most important part. Because here you define what you will do automatically. Only security updates? Everything? You may also add custom repositories here.
Do not forget to add an E-Mail so you know what’s going on:
Unattended-Upgrade::Mail "";
You should be very careful with the following setting; However, automatic restarts could be handy. I wouldn’t use this for my host systems (hypervisor). But I don’t see a problem for specific virtual machines. Depending on your monitoring infrastructure, you may want to pick an out-of-office time, but still a time in which you can respond quickly if something goes wrong. Don’t use this for critical systems.
// Automatically reboot *WITHOUT CONFIRMATION* if
// the file /var/run/reboot-required is found after the upgrade
Unattended-Upgrade::Automatic-Reboot "true";
// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: "now"
Unattended-Upgrade::Automatic-Reboot-Time "06:00";
Assuming that you do not want automatic reboots the needrestart package might become useful to you. It will tell you when a restart of services is required. So consider to additionally install needrestart.
I strongly recommend to run:
unattended-upgrade --dry-run --debug
After you edited the above configuration. It will show you for which package repositories it does automatic updates. Also it will help you to configure e.g. custom package repositories if you use any.
That’s all.
Mail Example #1
If you configured everything correctly and your mail is also configured correctly you should soon receive E-Mails similar to the following one. Here the system upgraded a few php8.3-* packages
Unattended upgrade result: All upgrades installed
Packages that were upgraded:
php8.3-bcmath php8.3-cli php8.3-common php8.3-fpm php8.3-intl
php8.3-opcache php8.3-readline php8.3-sqlite3 php8.3-sqlite3-dbgsym
Package installation log:
Log started: 2024-02-18 06:40:12
apt-listchanges: Reading changelogs...
apt-listchanges: Reading changelogs...
Preparing to unpack .../0-php8.3-sqlite3-dbgsym_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-sqlite3-dbgsym (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../1-php8.3-sqlite3_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-sqlite3 (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../2-php8.3-readline_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-readline (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../3-php8.3-opcache_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-opcache (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../4-php8.3-intl_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-intl (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../5-php8.3-cli_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-cli (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../6-php8.3-fpm_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-fpm (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../7-php8.3-bcmath_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-bcmath (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Preparing to unpack .../8-php8.3-common_8.3.3-1+0~20240216.17+debian12~1.gbp87e37b_amd64.deb ...
Unpacking php8.3-common (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) over (8.3.2-1+0~20240120.16+debian12~1.gbpb43448) ...
Setting up php8.3-common (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-sqlite3 (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-readline (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-bcmath (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-opcache (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-sqlite3-dbgsym (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-intl (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-cli (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Setting up php8.3-fpm (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Processing triggers for man-db (2.11.2-2) ...
Processing triggers for php8.3-cli (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Processing triggers for php8.3-fpm (8.3.3-1+0~20240216.17+debian12~1.gbp87e37b) ...
Running kernel seems to be up-to-date.
No services need to be restarted.
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
Log ended: 2024-02-18 06:40:34
Unattended-upgrades log:
Starting unattended upgrades script
Allowed origins are: origin=Debian,codename=bookworm-updates, origin=Debian,codename=bookworm-proposed-updates, origin=Debian,codename=bookworm,label=Debian, origin=Debian,codename=bookworm,label=Debian-Security, origin=Debian,codename=bookworm-security,label=Debian-Security, origin=Debian Backports,codename=bookworm-backports,label=Debian Backports, origin=deb.sury.org,a=bookworm
Initial blacklist:
Initial whitelist (not strict):
Packages that will be upgraded: php8.3-bcmath php8.3-cli php8.3-common php8.3-fpm php8.3-intl php8.3-opcache php8.3-readline php8.3-sqlite3 php8.3-sqlite3-dbgsym
Writing dpkg log to /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
All upgrades installed
In the above example all repositories as well as deb.sury.org are enabled for unattended upgrades.
Mail Example #2
Here is a good example. My Firewall’s use suricata and the current update requires me to choose if I want to keep two configuration files or install the package maintainers version. Instead of just doing the update – unattended upgrades puts them on hold:
Unattended upgrade result: No packages found that can be upgraded
unattended and no pending auto-removals
Packages with upgradable origin but kept back:
Debian Backports stable-backports:
suricata
Unattended-upgrades log:
Starting unattended upgrades script
Allowed origins are: [..]
Initial blacklist:
Initial whitelist (not strict):
Package suricata has conffile prompt and needs to be upgraded manually
package suricata not upgraded
No packages found that can be upgraded unattended and no pending auto-removals
Package suricata is blacklisted.
Another cool thing, on login you see that there are updates available:
1 updates could not be installed automatically. For more details,
see /var/log/unattended-upgrades/unattended-upgrades.log