Configure automatic security updates with unattended-upgrades and email notifications

Intermediate 25 min Apr 03, 2026 197 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up automated security patching on Linux servers with unattended-upgrades and dnf-automatic. Configure email notifications, update policies, and monitoring to keep your systems secure while maintaining control over critical services.

Prerequisites

  • Root or sudo access
  • Internet connectivity
  • Basic Linux command line knowledge
  • Email delivery capability

What this solves

Manual security updates create vulnerability windows that attackers exploit. This tutorial configures automated security patching with unattended-upgrades (Ubuntu/Debian) and dnf-automatic (RHEL-based systems) to maintain security while protecting critical services. You'll implement email notifications, update policies, and monitoring to balance automation with operational control.

Step-by-step configuration

Update system packages

Start by updating your package manager to ensure you get the latest security patches and package definitions.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install automatic update packages

Install the appropriate automatic update service for your distribution. Ubuntu/Debian use unattended-upgrades while RHEL-based systems use dnf-automatic.

sudo apt install -y unattended-upgrades apt-listchanges
sudo dnf install -y dnf-automatic

Install mail transfer agent

Install a mail server to send update notifications. Postfix provides reliable local mail delivery without requiring external SMTP configuration.

sudo apt install -y postfix mailutils
sudo systemctl enable --now postfix
sudo dnf install -y postfix mailx
sudo systemctl enable --now postfix
Note: Choose "Local only" when prompted during Postfix installation for basic notification delivery.

Configure unattended-upgrades (Ubuntu/Debian)

Configure unattended-upgrades to automatically install security updates with email notifications and exclusion policies.

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

Unattended-Upgrade::Package-Blacklist {
    "nginx";
    "apache2";
    "mysql-server";
    "postgresql";
    "docker-ce";
    "kubernetes*";
};

Unattended-Upgrade::DevRelease "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 "false";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

Unattended-Upgrade::Mail "admin@example.com";
Unattended-Upgrade::MailReport "on-change";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Verbose "1";
Unattended-Upgrade::Debug "false";

Unattended-Upgrade::SyslogEnable "true";
Unattended-Upgrade::SyslogFacility "daemon";

Enable automatic updates (Ubuntu/Debian)

Configure the automatic update schedule and enable the service to run daily security updates.

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
sudo systemctl enable --now unattended-upgrades
sudo systemctl status unattended-upgrades

Configure dnf-automatic (RHEL-based systems)

Configure dnf-automatic to download and install security updates automatically with email notifications.

[commands]
upgrade_type = security
random_sleep = 360
network_online_timeout = 60
download_updates = yes
apply_updates = yes

[emitters]
emit_via = email,stdio

[email]
email_from = root@example.com
email_to = admin@example.com
email_host = localhost
email_port = 25

[base]
debuglevel = 1

Enable dnf-automatic service (RHEL-based systems)

Enable and start the dnf-automatic timer to run daily security updates at a random time within the configured window.

sudo systemctl enable --now dnf-automatic.timer
sudo systemctl status dnf-automatic.timer

Configure update exclusions

Create package exclusion policies to prevent automatic updates of critical services that require manual intervention or testing.

sudo apt-mark hold nginx apache2 mysql-server postgresql
apt-mark showhold
exclude=nginx httpd mysql postgresql docker-ce kubernetes
Warning: Excluding packages from automatic updates means you must manually monitor and apply security patches for those services.

Configure log monitoring

Set up log rotation and monitoring for automatic update activities to track successful updates and failures.

/var/log/unattended-upgrades/unattended-upgrades.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 root root
}
sudo mkdir -p /var/log/unattended-upgrades
sudo touch /var/log/unattended-upgrades/unattended-upgrades.log
sudo chown root:root /var/log/unattended-upgrades/unattended-upgrades.log
sudo chmod 644 /var/log/unattended-upgrades/unattended-upgrades.log

Create update monitoring script

Create a monitoring script to check for failed updates and send alerts when automatic updates encounter problems.

#!/bin/bash

LOGFILE="/var/log/unattended-upgrades/unattended-upgrades.log"
ERROR_LOG="/tmp/update-errors.log"
ADMIN_EMAIL="admin@example.com"

if [[ -f "$LOGFILE" ]]; then
    # Check for errors in the last 24 hours
    grep -i "error\|failed\|abort" "$LOGFILE" | tail -20 > "$ERROR_LOG"
    
    if [[ -s "$ERROR_LOG" ]]; then
        echo "Automatic update errors detected on $(hostname):" | mail -s "Update Errors - $(hostname)" "$ADMIN_EMAIL" < "$ERROR_LOG"
    fi
fi

Check for pending security updates

if command -v apt &> /dev/null; then PENDING=$(apt list --upgradable 2>/dev/null | grep -c security) if [[ $PENDING -gt 0 ]]; then echo "$PENDING pending security updates on $(hostname)" | mail -s "Pending Security Updates - $(hostname)" "$ADMIN_EMAIL" fi elif command -v dnf &> /dev/null; then PENDING=$(dnf updateinfo list security 2>/dev/null | wc -l) if [[ $PENDING -gt 0 ]]; then echo "$PENDING pending security updates on $(hostname)" | mail -s "Pending Security Updates - $(hostname)" "$ADMIN_EMAIL" fi fi
sudo chmod 755 /usr/local/bin/check-updates.sh
sudo chown root:root /usr/local/bin/check-updates.sh

Schedule monitoring with cron

Schedule the monitoring script to run daily and send weekly update summaries to track system maintenance activities.

sudo crontab -e
# Check for update errors daily at 8 AM
0 8   * /usr/local/bin/check-updates.sh

Send weekly update summary on Mondays at 9 AM

0 9 1 grep -i "upgraded\|installed\|removed" /var/log/unattended-upgrades/unattended-upgrades.log | tail -50 | mail -s "Weekly Update Summary - $(hostname)" admin@example.com

Verify your setup

Test your automatic update configuration and verify that email notifications work correctly.

sudo systemctl status unattended-upgrades
sudo unattended-upgrade --dry-run --debug
sudo tail -f /var/log/unattended-upgrades/unattended-upgrades.log
sudo systemctl status dnf-automatic.timer
sudo dnf-automatic
sudo journalctl -u dnf-automatic -f
echo "Test automatic update notification" | mail -s "Test Email - $(hostname)" admin@example.com
/usr/local/bin/check-updates.sh

Configure rollback strategies

Enable system snapshots

Configure automatic system snapshots before updates to enable quick rollback if updates cause issues. This requires appropriate filesystem support.

sudo apt install -y snapper
sudo snapper -c root create-config /
sudo snapper list
Note: Snapper requires Btrfs or LVM with sufficient free space. Consider implementing backup strategies if snapshots aren't available.

Create update rollback script

Create a script to rollback recent updates in case of system issues after automatic updates.

#!/bin/bash

echo "WARNING: This will attempt to rollback recent updates"
echo "Press Ctrl+C to cancel, or Enter to continue..."
read

if command -v apt &> /dev/null; then
    echo "Checking recent package changes..."
    grep " install \| upgrade " /var/log/dpkg.log | tail -20
    echo "Use 'sudo apt install package=version' to downgrade specific packages"
elif command -v dnf &> /dev/null; then
    echo "Recent DNF transactions:"
    dnf history list | head -10
    echo "Use 'sudo dnf history undo ID' to rollback a transaction"
fi
sudo chmod 755 /usr/local/bin/rollback-updates.sh

Common issues

Symptom Cause Fix
No email notifications received Postfix not configured or email settings incorrect Test with echo "test" | mail -s "test" admin@example.com and check /var/log/mail.log
Updates not running automatically Service not enabled or configuration errors Check service status and run dry-run to identify configuration issues
Critical service broken after update Package conflict or configuration change Use package exclusions and test updates in staging environment first
Disk space filling up Old kernels and packages not cleaned up Enable automatic cleanup in configuration and run sudo apt autoremove
System requiring reboot frequently Kernel updates installed automatically Consider enabling automatic reboots during maintenance windows

Security considerations

Automatic updates balance security with stability. Monitor update logs regularly and maintain staging environments for testing critical service updates. Consider implementing comprehensive monitoring with Prometheus and Grafana to track system health after updates.

For containerized environments, integrate automatic host updates with Kubernetes security hardening practices to maintain both container and host security.

Never disable automatic security updates without implementing a robust manual patching process. Unpatched systems are the primary attack vector for most security incidents.

Next steps

Automated install script

Run this to automate the entire setup

#automatic updates #security patching #unattended-upgrades #dnf-automatic #email notifications

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer