Installation
sudo apt install -y unattended-upgrades apt-listchangesWith the installation complete, we're primarily concerned with the configuration of two files:
/etc/apt/apt.conf.d/50unattended-upgrades/etc/apt/apt.conf.d/20auto-upgrades
When you manually install upgrades with apt, you'd probably run something like, apt update && apt upgrade -y --autoremove && apt autoclean. All you're really doing is automating this process with the use of unattended-upgrades.
Choosing What to Upgrade
Origins Pattern
Origins Pattern controls which apt sources will be read by unattended-upgrades to pull and upgrade packages automatically.
tail -n 146 /etc/apt/apt.conf.d/50unattended-upgrades | head -n 13Unattended-Upgrade::Origins-Pattern {
// Codename based matching:
// This will follow the migration of a release through different
// archives (e.g. from testing to stable and later oldstable).
// Software will be the latest available for the named release,
// but the Debian release itself will not be automatically upgraded.
// Archive or Suite based matching:
// Note that this will silently match a different release after
// migration to the specified archive (e.g. testing becomes the
// new stable).
origin=${distro_id},codename=${distro_codename};
};You'd probably see something like this in a default installation of Unattended Upgrades
Note that every line starting with // is a comment and is not processed by Unattended Upgrades. Read them to understand more about each section. The interesting line is:
origin=${distro_id},codename=${distro_codename};Making Sense of Origins
What are the two variable names we see here?
${distro_id}${distro_codename}

You can translate these variable names by the value(s) in /etc/debian_version, but can also be found in /etc/os-release or by running lsb_release -a.

lsb_release -a command run on a Kali VM${distro_id}lsb_release -a—Distributor ID=Kali
${distro_codename}lsb_release -a—Codename=kali-rolling
Therefore, unattended-upgrades will translate the origins pattern to:
"origin=Kali,codename=kali-rolling";How It Fits Together
We now know that when unattended-upgrades is run, it will look at the origins pattern block and translate "origin=${distro_id},codename=${distro_codename}" to those from lsb_release -a.

A package will be upgraded only if the values in its metadata match all the supplied keywords in a line. (In other words, omitted keywords are wild cards.)
A valid release pattern can contain the keywords:
a,archive, orsuitecorcomponentlorlabeloororiginnorcodename- and a
sitehostname
unattended-upgrades treats this as a wildcard and matches loosely based on what you've provided.The available values on the system are printed by the command "apt-cache policy"apt-cache policyRunning this command provides any apt sources that will be read by unattended-upgrades

apt-cache policy output on Kali VMunattended-upgrades does not accept the b= (branch) of the specific source. apt will install the correct packages based on the host's CPU architecture.
apt releases using the same logic as unattended-upgradeWe can conclude from the information above:
- Given the release identifier
"origin=Kali,codename=kali-rolling";- The
o=field is translated from${distro_id}toKali - The
a=field is a wildcard, since it was not provided in the origin - The
n=field is translated from${distro_codename}tokali-rolling - The
c=field is a wildcard, since it was not provided in the origin
- The
- Any package identified in the release identifiers in pink above will be upgraded by
unattended-upgrades
A Word of Caution
unattended-upgrades could unexpectedly upgrade your OS if your archive, a, suite, c, or codename are set to something like stable.If your /etc/apt/sources are set to something like stable instead of hard-coded Debian versions such as bullseye, bookworm, trixie, etc, then this would cause unattended-upgrades to pull the latest Debian system files in the stable branch using apt and upgrade the entire operating system.
Holding Packages from Upgrades
If there are packages that you wish to be held from automatic upgrades, you can use apt-mark hold or pinning.
sudo apt-mark hold PACKAGE_NAMEMarking a package as "held" to prevent upgrades
Ubuntu-Specific Notes
I'm adding this here just to have it documented, but when I was configuring unattended-upgrades on Ubuntu, I noted that the --dry-run -d parser would only accept configurations with explicitly the o and the a values in an origin pattern. Any other keywords seemed to cause errors with the parser.
// apt-cache policy for MongoDB
// o=mongodb,a=xenial
"mongodb:xenial";
// apt-cache policy for Ubiquiti
// o=Ubiquiti Networks, Inc.,a=stable
"Ubiquiti Networks, Inc.:stable";In previous testing, Ubuntu requires "colon-delimited" fields, not commas
Configuring the Service
sudo nano /etc/apt/apt.conf.d/50unattended-upgradesExample 1: Visual Studio Code
Let's use this output from apt-cache policy as an example:
500 http://packages.microsoft.com/repos/code stable/main armhf Packages
release o=code stable,a=stable,n=stable,l=code stable,c=main,b=armhf
origin packages.microsoft.com
500 http://packages.microsoft.com/repos/code stable/main arm64 Packages
release o=code stable,a=stable,n=stable,l=code stable,c=main,b=arm64
origin packages.microsoft.com
500 http://packages.microsoft.com/repos/code stable/main amd64 Packages
release o=code stable,a=stable,n=stable,l=code stable,c=main,b=amd64
origin packages.microsoft.com
These are the branches of the Visual Studio Code apt repositories on my Kali Linux box.
- I do not need to configure three separate origin patterns for these
- These sources are all the same with the exception of the branch denoting the CPU architecture
b=armhfb=arm64b=amd64
- On my Kali VM, specifically,
aptwill automatically use theamd64branch based on the VM's CPU type.
So, if I wanted to identify a release pattern that will automatically upgrade Visual Studio Code to the latest version, I can copy and paste this single string:
"o=code stable,a=stable,n=stable,l=code stable,c=main";Unattended-Upgrade::Origins-Pattern {
// Comments and other content
// Removed for clarity
"origin=${distro_id},codename=${distro_codename}";
"o=code stable,a=stable,n=stable,l=code stable,c=main";
};Showing origin for VS Code added to the Origins Pattern block
Example 2: Microsoft Edge and Brave Browser
Again, looking at the output from apt-cache policy:
500 https://packages.microsoft.com/repos/edge stable/main amd64 Packages
release o=edge stable,a=stable,n=stable,l=edge stable,c=main,b=amd64
origin packages.microsoft.com
500 https://brave-browser-apt-release.s3.brave.com stable/main amd64 Packages
release o=Brave Software,a=stable,n=stable,l=Brave Browser,c=main,b=amd64
origin brave-browser-apt-release.s3.brave.comTo keep my Microsoft Edge and Brave Browser automatically upgraded, I could copy and paste these strings into the config file:
"o=edge stable,a=stable,n=stable,l=edge stable,c=main";Microsoft Edge release string
"o=Brave Software,a=stable,n=stable,l=Brave Browser,c=main";Brave browser release string
Unattended-Upgrade::Origins-Pattern {
// Comments and other content
// Removed for clarity
"origin=${distro_id},codename=${distro_codename}";
"o=code stable,a=stable,n=stable,l=code stable,c=main";
"o=edge stable,a=stable,n=stable,l=edge stable,c=main";
"o=Brave Software,a=stable,n=stable,l=Brave Browser,c=main";
};VS Code, Microsoft Edge, and Brave Browser in the Origins Pattern block
Configuring Upgrade Options
/etc/apt/apt.conf.d/50unattended-upgrades fileNow that the origin patterns have been added, scroll down the configuration file and you'll see additional options — some commented out with a // prefix.

// that you may want to configureUnattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::InstallOnShutdown "false";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
Unattended-Upgrade::OnlyOnACPower "false";All of the options I've from which I've removed the preceding // and configured
A few more things to note:
- I auto-reboot at
04:00, change this to a time that suits your needs - I haven't shown you how to configure
//Unattended-Upgrade::Mail "";, but I'd encourage you to look into this if you're running a production server and/or want to track changes. - Read the
// Commentsabove each section to gain a better understanding about each option.
Vendor-Specific Upgrades
sudo apt full-upgrade, which requires an additional configuration added to unattended-upgrades. Always consult your distribution vendor's documentation for best practices when performing upgrades.
Unattended-Upgrade::Upgrade-Type "full-upgrade";Adding the full-uprade option to my Kali Linux VM to follow vendor-specific advice
Configuring the Schedule
sudo nano /etc/apt/apt.conf.d/20auto-upgrades// How often (in days) to apt update
APT::Periodic::Update-Package-Lists "7";
// How often (in days) to download new packages
APT::Periodic::Download-Upgradeable-Packages "7";
// How often (in days) to clean the apt clean
APT::Periodic::AutocleanInterval "7";
// How often (in days) to run unattended-upgrades
APT::Periodic::Unattended-Upgrade "7";Weekly schedule
Enable and Start the Service
sudo systemctl enable --now unattended-upgradesWe want the daemon to start at boot and also start immediately
Troubleshooting
Dry Run Mode
sudo unattended-upgrades -d --dry-runRun unattended-upgrades with output in dry run mode
You can use dry run mode to see if there are any problems with your origin patterns, or problems with your overall configuration. Dry run mode will operate like a normal run, but will not install upgrades.
Manual Run
sudo unattended-upgrades -dRun unattended-upgrades manually with debug output
Running unattended-upgrades in debug mode will run an actual upgrade of your packages based on your origin patterns. Running it in debug mode manually can be useful when you want to gauge how the program will behave in future unattended runs.
References
