Debian 8-11 - Unattended upgrades - Automatic updates

There are good guides out there regarding unattended upgrades, so this is just a small cheat sheet

More detailed info here:

Log file locations:

Log file rotation:

Config file locations:
/etc/apt/apt.conf.d/02periodic OR /etc/apt/apt.conf.d/20auto-upgrades (Only one of these is necessary)

Debian 8:
Cron job running it:
/etc/cron.daily/apt-compat VIA /etc/crontab for cron.daily, set to 6:25 every day

To run it at another time, call /usr/lib/apt/apt.systemd.daily (in previous Debian 8 /etc/cron.daily/apt) in /etc/crontab for example to run it at 12:00:

0 12 * * *   root    /usr/lib/apt/apt.systemd.daily

Or if you want to run it on every boot after 15 min, edit /etc/rc.local and add this on a new line before exit 0:

sleep 900 && /usr/lib/apt/apt.systemd.daily &

The script places empty files here with file modified timestamps that tells it when it has already been run and so on:

Debian 11:

The cron job seems to have been replaced by a systemd timer.

Configuration for the downloads timer: /lib/systemd/system/apt-daily.timer
Overridden by - edit this file: /etc/systemd/system/apt-daily.timer.d/override.conf
sleep 900 && unattended-upgrades &

Configuration for the updates timer: /lib/systemd/system/apt-daily-upgrade.timer
Overridden by - edit this file: /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf

Read the wiki page at, there may be unexpected things, like that the OnCalendar= parameter needs to be set to empty before it can be set to something else.

To run it from rc.local:
sleep 900 && /usr/bin/unattended-upgrades &


There are at least two things reporting here. The unattended-upgrades and the apt-listchanges.
There is also a log file written by unattended-upgrades.

unattended-upgrades follows the APT::Periodic::Verbose "X"; setting in /etc/apt/apt.conf.d/02periodic

Example of unattended-upgrades/apt mail report with APT::Periodic::Verbose "2"; and no upgrades done, first run:

verbose level 2
power status (255) undetermined, continuing
system is on main power.
sleeping for 29 seconds
power status (255) undetermined, continuing
system is on main power.
check_stamp: missing time stamp file: /var/lib/apt/periodic/update-stamp.
download updated metadata (success).
send dbus signal (success)
check_stamp: missing time stamp file: /var/lib/apt/periodic/download-upgradeable-stamp.
download upgradable (success)
check_stamp: missing time stamp file: /var/lib/apt/periodic/upgrade-stamp.
unattended-upgrade (success)
check_stamp: missing time stamp file: /var/lib/apt/periodic/autoclean-stamp.
autoclean (success).
skip aging since MaxAge is 0

apt-listchanges follows /etc/apt/listchanges.conf

Example of log file output from unattended-upgrades, at /var/log/unattended-upgrades/unattended-upgrades.log when nothing done, first run:

2016-11-05 07:35:46,874 INFO Initial blacklisted packages:
2016-11-05 07:35:46,875 INFO Initial whitelisted packages:
2016-11-05 07:35:46,875 INFO Starting unattended upgrades script
2016-11-05 07:35:46,876 INFO Allowed origins are: ['Debian stable', 'Debian jessie-security', 'Debian jessie-updates']
2016-11-05 07:35:51,540 INFO No packages found that can be upgraded unattended

Note: Do not panic if CPU goes 100% (on one of the cores) when unattended-upgrades is running.

Follow progress in the log files, especially /var/log/unattended-upgrades/unattended-upgrades-dpkg.log


apt-get install unattended-upgrades apt-listchanges

Configuration examples - /etc/apt/apt.conf.d/02periodic

// Enable the update/upgrade script (0=disable)
APT::Periodic::Enable "1";

// Do "apt-get update" automatically every n-days (0=disable)
APT::Periodic::Update-Package-Lists "1";

// Do "apt-get upgrade --download-only" every n-days (0=disable)
APT::Periodic::Download-Upgradeable-Packages "1";

// Run the "unattended-upgrade" security upgrade script
// every n-days (0=disabled)
// Requires the package "unattended-upgrades" and will write
// a log in /var/log/unattended-upgrades
APT::Periodic::Unattended-Upgrade "1";

// Do "apt-get autoclean" every n-days (0=disable)
APT::Periodic::AutocleanInterval "7";
// was 21

// Send report mail to root
//     0:  no report             (or null string)
//     1:  progress report       (actually any string)
//     2:  + command outputs     (remove -qq, remove 2>/dev/null, add -d)
//     3:  + trace on
APT::Periodic::Verbose "1";

// default random sleep is 1800 or 30 min to ease the load on the servers
//APT::Periodic::RandomSleep "10";

Configuration examples - /etc/apt/apt.conf.d/50unattended-upgrades

// Unattended-Upgrade::Origins-Pattern controls which packages are
// upgraded.
// Lines below have the format format is "keyword=value,...".  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.) The keywords originate from the Release
// file, but several aliases are accepted.  The accepted keywords are:
//   a,archive,suite (eg, "stable")
//   c,component     (eg, "main", "crontrib", "non-free")
//   l,label         (eg, "Debian", "Debian-Security")
//   o,origin        (eg, "Debian", "Unofficial Multimedia Packages")
//   n,codename      (eg, "jessie", "jessie-updates")
//     site          (eg, "")
// The available values on the system are printed by the command
// "apt-cache policy", and can be debugged by running
// "unattended-upgrades -d" and looking at the log file.
// Within lines unattended-upgrades allows 2 macros whose values are
// derived from /etc/debian_version:
//   ${distro_id}            Installed origin.
//   ${distro_codename}      Installed codename (eg, "jessie")
Unattended-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).
//      "o=Debian,n=jessie";
//      "o=Debian,n=jessie-updates";
//      "o=Debian,n=jessie-proposed-updates";
//      "o=Debian,n=jessie,l=Debian-Security";

        // 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).
//        "o=Debian,a=stable";
//        "o=Debian,a=stable-updates";
//      "o=Debian,a=proposed-updates";


// recommended, enabled by default:
//        "origin=Debian,codename=${distro_codename},label=Debian-Security";

// List of packages to not update (regexp are supported)
Unattended-Upgrade::Package-Blacklist {
//	"vim";
//	"libc6";
//	"libc6-dev";
//	"libc6-i686";

// This option allows you to control if on a unclean dpkg exit
// unattended-upgrades will automatically run 
//   dpkg --force-confold --configure -a
// The default is true, to ensure updates keep getting installed
//Unattended-Upgrade::AutoFixInterruptedDpkg "false";

// Split the upgrade into the smallest possible chunks so that
// they can be interrupted with SIGUSR1. This makes the upgrade
// a bit slower but it has the benefit that shutdown while a upgrade
// is running is possible (with a small delay)
//Unattended-Upgrade::MinimalSteps "true";

// Install all unattended-upgrades when the machine is shuting down
// instead of doing it in the background while the machine is running
// This will (obviously) make shutdown slower
//Unattended-Upgrade::InstallOnShutdown "true";

// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. A package that provides
// 'mailx' must be installed. E.g. ""
Unattended-Upgrade::Mail "root";

// Set this value to "true" to get emails only on errors. Default
// is to always send a mail if Unattended-Upgrade::Mail is set
//Unattended-Upgrade::MailOnlyOnError "true";

// Do automatic removal of new unused dependencies after the upgrade
// (equivalent to apt-get autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "true";

// 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";

// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
//Acquire::http::Dl-Limit "70";

Configuration examples - /etc/apt/listchanges.conf

# which=news

Specifying your own packages/sources/repos for upgrade

If you have added repos to the system, then you may need to tweak the settings to get these repos to upgrade automatically.

cd /var/lib/apt/lists/

Find the Release file relevant for the package you want to automate. It can be a little bit tricky, but it should end with Release in the filename and contain the package name, here's to search for text in all files:

grep -rn "<write package name here>" ./

Open the file and find the two lines:
Origin: <something 1>
Suite: <something 2>

Prepare a line like this:
"o=<something 1>,a=<something 2>";

For example:
"o=vscode stable,a=stable";

Then open the config file
vi /etc/apt/apt.conf.d/50unattended-upgrades

Go down to the Unattended-Upgrade::Origins-Pattern { section and put the line there.

To test, run:

Check logs here to find out if it works:
tail /var/log/unattended-upgrades/unattended-upgrades.log


- One machine updates, but another does not. Are you sure that both machines has the same programs installed? One machine may have software installed that can be updated while the other may not have it installed, and therefore the unattended upgrades differ.

Also check the logs and check the Unattended-Upgrade::Origins-Pattern { } section for errors.

- If you run apt update or find that a package is available but not updated, then the source for the package can be added. Run unattended-upgrades -d|grep <package name>. Find a line that begins with "Marking not allowed" followed by some properties to put into the 50unattended-upgrades file. Note the a= or c= and o= values in this line, then put them into /etc/apt/apt.conf.d/50unattended-upgrades below the others.

Like this if you want to go by origin and archive values:
"o=<origin text>,a=<stable text>"

Or like this if you want to go by origin and contrib values:
"o=<origin text>,c=<contrib text>"

Then re-run unattended-upgrades -d, this should then upgrade the package.

This is a personal note. Last updated: 2022-05-04 09:39:23.







Don't forget to pay my friend a visit too. Joakim