I will walk through installing and configuring unattended-upgrades on an Ubuntu server so that security patches are applied automatically every day without any manual intervention. By the end, your server will download and install security updates on a schedule, send you an email notification when patches are applied, and optionally reboot itself when a kernel update requires it.
Prerequisites
- An Ubuntu server running Ubuntu 20.04 or 22.04 LTS.
- A user account with sudo privileges.
- SSH access to the server.
- A basic familiarity with editing files on the command line.
- An SMTP server or mail relay if you want email notifications, though this is optional.
Step 1 - Install unattended-upgrades
Most Ubuntu LTS installations include unattended-upgrades by default, but I always confirm it is present and up to date before configuring it.
sudo apt update sudo apt install unattended-upgrades apt-listchanges -y
The apt-listchanges package is worth installing alongside unattended-upgrades. It reads the changelog entries for packages before they are upgraded and can include those details in email notifications, which makes it easier to understand what changed after an automatic update runs.
Step 2 - Enable the automatic update timer
Ubuntu uses a systemd timer called apt-daily and apt-daily-upgrade to trigger package list refreshes and upgrades on a schedule. Run the reconfigure command to make sure both timers are active and the correct defaults are written to the configuration files.
sudo dpkg-reconfigure --priority=low unattended-upgrades
This command presents a simple prompt asking whether to automatically download and install stable updates. Select yes. Behind the scenes it writes an auto-upgrade configuration file to /etc/apt/apt.conf.d/20auto-upgrades with the correct settings to enable both the daily download and the daily upgrade timers.
Verify the file was written correctly by printing its contents.
cat /etc/apt/apt.conf.d/20auto-upgrades
The output should contain the following two lines.
APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1";
The value 1 means the action runs once per day. If the file contains zeros, the feature is disabled. Update the values to 1 manually if needed.
Step 3 - Review and adjust the upgrade sources
The main configuration file for unattended-upgrades lives at /etc/apt/apt.conf.d/50unattended-upgrades. This file controls which package sources are eligible for automatic updates. Open it in your preferred editor.
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
The Allowed-Origins block near the top of the file lists the repositories that unattended-upgrades will pull from. For most Ubuntu servers, the correct and safe defaults are the security and updates repositories for your release codename. The file uses the codename placeholder dollar-sign-distro-codename which resolves to the running release automatically.
Make sure the following two lines are uncommented, meaning they do not have a leading double slash.
Unattended-Upgrade::Allowed-Origins { "${distro_id}:${distro_codename}"; "${distro_id}:${distro_codename}-security"; "${distro_id}ESMApps:${distro_codename}-apps-security"; "${distro_id}ESM:${distro_codename}-infra-security"; };
Note: I recommend leaving the updates and proposed repositories commented out for automatic upgrades. Security patches are well tested before release. General updates and proposed packages carry more risk of introducing breaking changes on an unattended server.
Step 4 - Configure email notifications
Knowing when automatic updates run and whether they succeeded is important for any server you care about. The 50unattended-upgrades file has a mail setting that accepts an email address. Find the line that starts with Unattended-Upgrade::Mail and uncomment it, then replace the example address with your own.
Unattended-Upgrade::Mail "you@yourdomain.com";
By default the mail is only sent when an error occurs. To receive a notification after every successful run as well, find the MailReport setting and set it to always.
Unattended-Upgrade::MailReport "always";
For email delivery to work, the server needs a working mail transport agent. A common lightweight option for Ubuntu servers is msmtp combined with msmtp-mta, configured to relay through an external SMTP service such as your existing email provider or a transactional email service.
Note: If you do not have a mail relay set up yet, leave the Mail setting commented out for now and focus on getting the upgrades working first. You can add email notifications later without changing any other part of the configuration.
Step 5 - Enable automatic reboots for kernel updates
Some security updates, particularly kernel patches and glibc updates, require a reboot to take effect. Without a reboot, the old vulnerable version stays in memory even though a patched version is installed on disk. Decide whether you want unattended-upgrades to handle reboots automatically.
To enable automatic reboots, find the Automatic-Reboot setting in the 50unattended-upgrades file and change it to true.
Unattended-Upgrade::Automatic-Reboot "true";
Then set the time at which the reboot should happen so it occurs during a low-traffic window rather than immediately after the upgrade finishes.
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
Gotcha: Automatic reboots are convenient but carry risk if your server runs stateful services that do not restart cleanly. If you run databases, queues, or long-lived PHP workers, test your startup scripts and confirm all services recover correctly after a cold reboot before enabling this setting in production.
If you prefer to handle reboots manually, leave Automatic-Reboot set to false. The file /var/run/reboot-required will be created by the package manager whenever a reboot is needed, so you can check for its existence in a monitoring script or a daily login message.
Step 6 - Run a dry run to verify the configuration
Before relying on the timer to trigger the first real upgrade, I run unattended-upgrades manually in dry-run mode to confirm it can connect to the repositories, find eligible packages, and read the configuration correctly. A dry run reports everything it would do without actually making any changes.
sudo unattended-upgrades --dry-run --debug
The output is verbose. Look for lines that list packages that would be upgraded and confirm there are no authentication errors or repository connection failures. If the output ends without errors, the configuration is correct.
To trigger a real upgrade immediately without waiting for the daily timer, run the command without the dry-run flag.
sudo unattended-upgrades --debug
This is useful after the initial setup to apply any pending security patches right away.
Step 7 - Check the logs after the first automatic run
Unattended-upgrades writes a log file to /var/log/unattended-upgrades/ after each run. There are two files worth checking regularly. The main log records which packages were upgraded and any errors that occurred. The apt-term log contains the raw apt output from each upgrade transaction.
cat /var/log/unattended-upgrades/unattended-upgrades.logcat /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
A healthy log entry looks like a timestamped line listing the packages that were upgraded followed by a line confirming the run completed. An empty log after the first scheduled run usually means the timer has not fired yet or there were no eligible packages to upgrade at that time, both of which are normal.
You can also check the status of the systemd timers directly to confirm they are active and see when they last ran and when they will next run.
systemctl status apt-daily.timer systemctl status apt-daily-upgrade.timer
Wrap-up
Your Ubuntu server now applies security patches automatically every day using unattended-upgrades. The upgrade sources are scoped to security repositories only so the risk of a breaking update is minimal. Email notifications tell you when patches are applied, and the log files give you a full audit trail of every automatic upgrade. Combined with the deployment workflows from the rest of this series, your infrastructure now handles both application updates through CI and operating system security patches through unattended-upgrades, with minimal manual effort required to keep everything patched and current.