How to Configure Unattended Upgrades on Debian

The unattended-upgrades package automatically installs security patches and critical software updates on your Debian system without manual intervention. This keeps servers protected against vulnerabilities, ensures fixes are applied promptly during maintenance windows, and reduces the administrative burden of patch management on production systems, development servers, and VPS instances. By the end of this guide, you will have unattended upgrades configured with systemd timers, custom origin settings, optional email notifications, automatic reboot scheduling, and dedicated logging to monitor all upgrade activity.

These instructions apply to Debian 13 (Trixie), 12 (Bookworm), and 11 (Bullseye). Commands work identically across all supported releases unless noted otherwise. Output examples use Debian 13; your codename will differ based on your installed version.

Install Unattended Upgrades Package

Update the Package Index

Refresh your package lists before installing to ensure you get the latest available version:

sudo apt update && sudo apt upgrade

Install the Unattended Upgrades Package

Install the unattended-upgrades package:

sudo apt install unattended-upgrades

Most Debian desktop installations include this package by default. Server and minimal installations may require installing it manually using the command above.

Install Optional Packages

Two optional packages extend unattended-upgrades functionality:

apt-config-auto-update

  • Enables automatic system reboots after upgrades that require a restart
  • Useful for servers that can tolerate scheduled downtime
  • Works in conjunction with Automatic-Reboot configuration options
sudo apt install apt-config-auto-update

powermgmt-base

  • Provides power management detection for laptops
  • Enables the OnlyOnACPower setting to skip updates while on battery
  • Recommended for portable devices
sudo apt install powermgmt-base

Verify the Installation

Run a dry-run test to confirm the package is working and see which origins are allowed:

sudo unattended-upgrades --dry-run --debug

The output shows the allowed update origins and any packages that would be upgraded:

Starting unattended upgrades script
Allowed origins are: origin=Debian,codename=trixie,label=Debian, origin=Debian,codename=trixie,label=Debian-Security, origin=Debian,codename=trixie-security,label=Debian-Security
Initial blacklist:
Initial whitelist (not strict):
Packages that will be upgraded: base-files bash libc-bin libc6 libcap2
All upgrades installed

Your output will show your Debian release codename (bullseye, bookworm, or trixie) and different packages depending on what updates are available. The key confirmation is seeing “Allowed origins” with your release name and “All upgrades installed” at the end.

Understand the Systemd Timer Scheduling

Debian enables automatic upgrades through systemd timers, not cron jobs. Two timers work together to handle package updates:

apt-daily.timer

  • Runs twice daily at 6:00 AM and 6:00 PM
  • Downloads package lists and new packages
  • Includes a randomized delay of up to 12 hours to distribute load across mirrors

apt-daily-upgrade.timer

  • Runs daily at 6:00 AM
  • Installs downloaded security updates via unattended-upgrades
  • Includes a randomized delay of up to 60 minutes

Check the status of the upgrade timer:

systemctl status apt-daily-upgrade.timer

View scheduled timer runs:

systemctl list-timers apt-daily*

Expected output showing the next scheduled runs:

NEXT                        LEFT          LAST                        PASSED       UNIT
Sun 2026-01-12 06:15:00 UTC 12h left      Sat 2026-01-11 06:30:00 UTC 11h ago      apt-daily-upgrade.timer
Sun 2026-01-12 06:00:00 UTC 11h left      Sat 2026-01-11 18:00:00 UTC 30min ago    apt-daily.timer

Manage the Unattended Upgrades Service

The unattended-upgrades service runs as a shutdown helper that ensures upgrades complete before the system powers off. Common management commands:

ActionCommand
Check service statussystemctl status unattended-upgrades
Stop the servicesudo systemctl stop unattended-upgrades
Start the servicesudo systemctl start unattended-upgrades
Disable on bootsudo systemctl disable unattended-upgrades
Enable on bootsudo systemctl enable unattended-upgrades
Restart the servicesudo systemctl restart unattended-upgrades

Configure Unattended Upgrades

The main configuration file controls which packages get upgraded automatically, notification settings, reboot behavior, and logging. Back up the original before making changes:

sudo cp /etc/apt/apt.conf.d/50unattended-upgrades{,.bak}

Edit the configuration file:

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

The file uses APT configuration syntax. Remove the leading // from any line to enable that option. The following sections explain the most useful settings.

Review CLI Options

The unattended-upgrades command accepts these flags for testing and debugging:

OptionDescription
-h, –helpDisplay the help message
-d, –debugEnable debug messages showing detailed processing information
–apt-debugEnable verbose debug messages from apt/libapt
-v, –verboseEnable info-level messages
–dry-runSimulate the upgrade process and download packages without installing
–download-onlyDownload upgrades without attempting installation
–minimal-upgrade-stepsUpgrade packages in minimal steps (default behavior, allows SIGTERM interruption)
–no-minimal-upgrade-stepsUpgrade all packages together in a single transaction

Use --dry-run --debug after changing configuration to verify your settings work correctly before relying on automatic upgrades.

Configure Update Origins

The Origins-Pattern section controls which repositories are eligible for automatic updates. The default configuration includes only security updates from Debian:

Unattended-Upgrade::Origins-Pattern {
    "origin=Debian,codename=${distro_codename},label=Debian";
    "origin=Debian,codename=${distro_codename},label=Debian-Security";
    "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};

To enable automatic updates from additional sources, uncomment or add the relevant lines. Common additions:

Unattended-Upgrade::Origins-Pattern {
    "origin=Debian,codename=${distro_codename},label=Debian";
    "origin=Debian,codename=${distro_codename},label=Debian-Security";
    "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
    // Enable stable updates (point releases)
    "origin=Debian,codename=${distro_codename}-updates,label=Debian";
    // Enable proposed updates (testing before point release)
    "origin=Debian,codename=${distro_codename}-proposed-updates,label=Debian";
    // Enable backports (newer software versions)
    "o=Debian Backports,a=${distro_codename}-backports,l=Debian Backports";
};

The ${distro_codename} variable automatically expands to your Debian release (bullseye, bookworm, or trixie). This makes the configuration portable across versions.

Exclude Packages from Automatic Updates

The Package-Blacklist section uses Python regular expressions to exclude specific packages from automatic upgrades:

Unattended-Upgrade::Package-Blacklist {
    "linux-";
    "libc6$";
    "nginx";
    "mysql-server";
    "postgresql";
};

Use this to prevent automatic updates to:

  • Kernel packages (may require reboot and testing)
  • Core system libraries that could affect running applications
  • Database servers that need coordinated maintenance windows
  • Web servers that require configuration verification after updates

Configure Email Notifications

Set up email alerts to monitor upgrade activity. Two options control email behavior:

Unattended-Upgrade::Mail "admin@example.com";
Unattended-Upgrade::MailReport "on-change";

The MailReport option accepts three values:

  • always sends email after every unattended-upgrades run
  • only-on-error sends email only when upgrades fail
  • on-change sends email when packages are upgraded or errors occur

Email notifications require a working mail transfer agent (MTA) on your system. Install bsd-mailx or mailutils along with an MTA such as Postfix for outbound mail delivery.

Configure Automatic Reboots

Some updates (kernel, libc, systemd) require a reboot to take effect. These options control automatic reboot behavior:

// Enable automatic reboot when required
Unattended-Upgrade::Automatic-Reboot "true";

// Reboot even if users are logged in
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";

// Schedule reboot at a specific time instead of immediately
Unattended-Upgrade::Automatic-Reboot-Time "03:00";

When a reboot is required, the system creates /var/run/reboot-required. Check for pending reboots manually:

cat /var/run/reboot-required 2>/dev/null || echo "No reboot required"

Configure Dependency Cleanup

Control whether unattended-upgrades removes orphaned packages automatically:

// Remove unused kernel packages after upgrade
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";

// Remove dependencies that became unused after this upgrade
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

// Remove all unused dependencies (like apt autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "false";

Configure Logging

Control how unattended-upgrades logs its activity:

// Enable syslog logging (default: false)
Unattended-Upgrade::SyslogEnable "true";

// Syslog facility (default: daemon)
Unattended-Upgrade::SyslogFacility "daemon";

// Enable verbose output in logs
Unattended-Upgrade::Verbose "true";

// Enable debug output (very detailed)
Unattended-Upgrade::Debug "false";

Configure Power and Network Settings

For laptops and metered connections, these options prevent upgrades in unfavorable conditions:

// Only upgrade when connected to AC power (requires powermgmt-base)
Unattended-Upgrade::OnlyOnACPower "true";

// Skip updates on metered connections
Unattended-Upgrade::Skip-Updates-On-Metered-Connections "true";

// Limit download bandwidth in KB/s
Acquire::http::Dl-Limit "500";

Additional Configuration Options

Other useful settings in the configuration file:

// Automatically fix interrupted dpkg (default: true)
Unattended-Upgrade::AutoFixInterruptedDpkg "true";

// Install upgrades in minimal steps for SIGTERM interruption (default: true)
Unattended-Upgrade::MinimalSteps "true";

// Install upgrades during shutdown instead of in background
Unattended-Upgrade::InstallOnShutdown "false";

// Allow package downgrades if pin priority exceeds 1000
Unattended-Upgrade::Allow-downgrade "false";

Enabling Allow-downgrade can cause system instability. Only use this when you have a specific need, such as rolling back a problematic update through APT pinning.

Test Configuration Changes

After editing the configuration, run a dry-run test to verify your changes:

sudo unattended-upgrades --dry-run --debug

Check the output for:

  • Your expected origins appearing in “Allowed origins”
  • Blacklisted packages not appearing in upgrade candidates
  • No configuration errors in the output

Schedule Automatic Upgrades with Cron (Optional)

Debian enables unattended upgrades through systemd timers by default. A manual cron job is only needed if you require a specific schedule different from the default 6:00 AM run or prefer cron-based scheduling over systemd timers.

To create a custom schedule using cron, edit the root crontab:

sudo crontab -e

Add a line specifying when to run unattended-upgrades. This example runs at midnight daily:

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

Common scheduling patterns:

ScheduleCron ExpressionDescription
Daily at midnight0 0 * * *Run at 00:00 every day
Daily at 3 AM0 3 * * *Low-traffic maintenance window
Twice daily0 6,18 * * *Run at 6 AM and 6 PM
Every 6 hours0 */6 * * *More frequent security updates
Weekdays only0 2 * * 1-5Skip weekends

If using cron, consider disabling the default systemd timers to avoid duplicate runs:

sudo systemctl disable apt-daily-upgrade.timer
sudo systemctl stop apt-daily-upgrade.timer

Monitor Upgrade Logs

Unattended-upgrades maintains dedicated log files in /var/log/unattended-upgrades/:

  • unattended-upgrades.log contains the main upgrade activity log
  • unattended-upgrades-dpkg.log contains dpkg output during package installation

View recent upgrade activity:

sudo cat /var/log/unattended-upgrades/unattended-upgrades.log

Example log output showing a successful upgrade run:

2026-01-11 06:54:13,029 INFO Starting unattended upgrades script
2026-01-11 06:54:13,030 INFO Allowed origins are: origin=Debian,codename=trixie,label=Debian, origin=Debian,codename=trixie,label=Debian-Security
2026-01-11 06:54:13,030 INFO Initial blacklist:
2026-01-11 06:54:14,558 INFO Packages that will be upgraded: base-files bash libc-bin libc6 libcap2
2026-01-11 06:54:14,558 INFO Writing dpkg log to /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
2026-01-11 06:54:19,664 INFO All upgrades installed

View the last 50 lines of the log:

sudo tail -n 50 /var/log/unattended-upgrades/unattended-upgrades.log

Search for entries from a specific date:

sudo grep "2026-01-11" /var/log/unattended-upgrades/unattended-upgrades.log

Search for a specific package:

sudo grep "openssl" /var/log/unattended-upgrades/unattended-upgrades.log

View Logs via Journalctl

If syslog logging is enabled in the configuration, view logs through journalctl:

journalctl -u unattended-upgrades

View logs from today only:

journalctl -u unattended-upgrades --since today

Troubleshoot Common Issues

Upgrades Not Running Automatically

Verify the systemd timer is enabled and running:

systemctl status apt-daily-upgrade.timer

If the timer is disabled, enable it:

sudo systemctl enable apt-daily-upgrade.timer
sudo systemctl start apt-daily-upgrade.timer

Packages Held Back

If the log shows packages being held back, check for dependency conflicts:

sudo apt update
sudo apt --simulate upgrade

Resolve by running a full upgrade manually:

sudo apt upgrade

Dpkg Lock Errors

If unattended-upgrades reports lock file errors, another package manager process is running. Check for running APT processes:

ps aux | grep -E 'apt|dpkg'

Wait for other processes to complete, or if the lock is stale:

sudo rm /var/lib/apt/lists/lock
sudo rm /var/lib/dpkg/lock-frontend
sudo dpkg --configure -a

Email Notifications Not Working

Email requires a working MTA. Test mail delivery:

echo "Test email" | mail -s "Test from $(hostname)" admin@example.com

If mail fails, install and configure an MTA:

sudo apt install bsd-mailx postfix

During Postfix installation, select “Internet Site” for a server that sends mail directly, or “Satellite system” to relay through an external SMTP server.

Check for Configuration Errors

Syntax errors in the configuration file cause unattended-upgrades to fail silently. Run a debug dry-run to catch errors:

sudo unattended-upgrades --dry-run --debug 2>&1 | head -20

Look for Python tracebacks or error messages indicating configuration problems.

Remove Unattended Upgrades

To disable automatic updates and manage packages manually, remove the unattended-upgrades package along with any optional packages you installed:

sudo apt remove unattended-upgrades apt-config-auto-update powermgmt-base

The apt-config-auto-update and powermgmt-base packages are optional. Omit them from the command if you did not install them.

Remove orphaned dependencies:

sudo apt autoremove

If you added a manual cron job, remove it:

sudo crontab -e

Delete the line containing /usr/bin/unattended-upgrade.

Verify the package is removed:

dpkg -l | grep unattended-upgrades

No output confirms the package is no longer installed. Configuration files at /etc/apt/apt.conf.d/50unattended-upgrades may remain after removal. Delete manually for a clean slate:

sudo rm /etc/apt/apt.conf.d/50unattended-upgrades /etc/apt/apt.conf.d/50unattended-upgrades.bak 2>/dev/null

Conclusion

You now have unattended upgrades configured on Debian with automatic security patches, systemd timer scheduling, and dedicated logging to monitor activity. For additional system hardening, consider setting up Fail2ban on Debian to protect against brute-force attacks, configuring UFW firewall on Debian for network access control, or using Timeshift on Debian to create system snapshots before major updates. For remote server management, ensure SSH is properly configured on Debian, and for servers exposed to the internet, add SSL certificates with Let’s Encrypt on Debian to provide essential encryption for web traffic.

3 thoughts on “How to Configure Unattended Upgrades on Debian”

    • Thanks for catching that, DeeDeeRanged. You were absolutely right. The example under the OnlyOnACPower heading was incorrectly showing the SyslogFacility syntax instead of the correct option. The article has been corrected to:

      Unattended-Upgrade::OnlyOnACPower "true";

      Thank you for taking the time to report this. Your feedback directly improved the guide for future readers.

      Reply

Leave a Comment

Let us know you are human: