Automatic Security Updates on VPS: Unattended Upgrades, Alerts, and Safe Automation

Automatic Security Updates on VPS: Unattended Upgrades, Alerts, and Safe Automation

Unpatched packages are one of the most common causes of VPS compromise — many attacks exploit known vulnerabilities with published CVEs and public exploit code. Running outdated software for days or weeks after a security patch is released leaves your server exposed to automated scanning and exploitation. Ubuntu’s unattended-upgrades package automates security patching, applying updates as soon as they’re released without manual intervention.

What Unattended Upgrades Does

  • Applies security updates automatically: Only from Ubuntu Security (ubuntu-security) and Ubuntu Updates repositories by default
  • Does NOT auto-update all packages: Only security-classified packages, not general updates (which might break compatibility)
  • Sends email reports: What was updated, any errors
  • Optional automatic reboot: For kernel updates that require a restart (configurable)

Step 1: Install and Enable

<code"># Install unattended-upgrades (usually pre-installed on Ubuntu)
sudo apt install -y unattended-upgrades apt-listchanges

# Enable automatic updates
sudo dpkg-reconfigure -plow unattended-upgrades
# Answer "Yes" when prompted

# Or enable directly:
cat | sudo tee /etc/apt/apt.conf.d/20auto-upgrades << 'EOF'
APT::Periodic::Update-Package-Lists "1";      // Check for updates daily
APT::Periodic::Unattended-Upgrade "1";        // Apply updates daily
APT::Periodic::AutocleanInterval "7";         // Clean package cache weekly
APT::Periodic::Download-Upgradeable-Packages "1"; // Download before applying
EOF

Step 2: Configure What Gets Updated

<code">sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
<code">Unattended-Upgrade::Allowed-Origins {
    // Ubuntu security updates — always enable
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";

    // Optional: Also apply general updates (more risk, more coverage)
    // "${distro_id}:${distro_codename}";
    // "${distro_id}:${distro_codename}-updates";
};

// Packages to NEVER auto-update (add packages that need manual testing)
Unattended-Upgrade::Package-Blacklist {
    // "nginx";          // Example: don't auto-update Nginx config-sensitive packages
    // "postgresql-16";  // Example: major DB updates need manual migration check
};

// Remove unused dependencies automatically
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

// Email configuration
Unattended-Upgrade::Mail "admin@yourdomain.com";
Unattended-Upgrade::MailReport "on-change";  // "always", "on-change", "only-on-error"

// Automatic reboot for kernel updates
Unattended-Upgrade::Automatic-Reboot "false";   // Change to "true" to auto-reboot
Unattended-Upgrade::Automatic-Reboot-Time "04:00"; // If rebooting, do it at 4 AM

// Minimal logging (set to "1" for verbose)
Unattended-Upgrade::Verbose "0";

// Only download, don't apply (for manual review):
// Unattended-Upgrade::InstallOnShutdown "false";

Step 3: Configure Email Notifications

<code"># Install msmtp for lightweight SMTP relay
sudo apt install -y msmtp msmtp-mta

sudo nano /etc/msmtprc
<code">defaults
auth           on
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        /var/log/msmtp.log

account        default
host           smtp.mailgun.org
port           587
from           vps-alerts@yourdomain.com
user           postmaster@mg.yourdomain.com
password       your_mailgun_password

account default : default
<code">sudo chmod 600 /etc/msmtprc

# Test email
echo "Test from VPS" | mail -s "Test Alert" admin@yourdomain.com

# Check if unattended-upgrades uses the right mailer:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
# Ensure: Unattended-Upgrade::Mail "admin@yourdomain.com";

Step 4: Telegram Notifications (More Reliable Than Email)

<code">sudo nano /usr/local/bin/notify-updates.sh
<code">#!/bin/bash
# Send Telegram notification when unattended-upgrades runs
BOT_TOKEN="YOUR_TELEGRAM_BOT_TOKEN"
CHAT_ID="YOUR_TELEGRAM_CHAT_ID"
LOG="/var/log/unattended-upgrades/unattended-upgrades.log"
HOSTNAME=$(hostname)

# Check if any upgrades were applied today
TODAY=$(date +%Y-%m-%d)
UPDATES=$(grep -c "Upgraded:" "$LOG" 2>/dev/null || echo 0)
ERRORS=$(grep -c "ERROR" "$LOG" 2>/dev/null || echo 0)

if [ "$UPDATES" -gt 0 ] || [ "$ERRORS" -gt 0 ]; then
    PACKAGES=$(grep "Upgraded:" "$LOG" | tail -5 | sed 's/.*Upgraded: //')
    MESSAGE="🔒 *Security Updates Applied*
Host: \`$HOSTNAME\`
Date: $TODAY
Packages updated: $UPDATES
$([ "$ERRORS" -gt 0 ] && echo "⚠️ Errors: $ERRORS" || echo "✅ No errors")
Recent: $PACKAGES"

    curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
        -d "chat_id=${CHAT_ID}" \
        -d "parse_mode=Markdown" \
        -d "text=${MESSAGE}" > /dev/null
fi
<code">chmod +x /usr/local/bin/notify-updates.sh

# Schedule to run after unattended-upgrades (6 AM daily)
echo "0 6 * * * root /usr/local/bin/notify-updates.sh" | \
    sudo tee /etc/cron.d/update-notifications

Step 5: Manual Testing

<code"># Dry run — see what WOULD be updated without applying
sudo unattended-upgrades --dry-run --verbose

# Force run immediately (applies updates now)
sudo unattended-upgrades --verbose

# Check what was applied
cat /var/log/unattended-upgrades/unattended-upgrades.log | tail -30

# Check for pending kernel reboot
if [ -f /var/run/reboot-required ]; then
    echo "REBOOT REQUIRED"
    cat /var/run/reboot-required.pkgs
fi

Step 6: Kernel Updates and Reboots

<code"># Kernel security updates are applied but require reboot to take effect
# Check if reboot is needed:
cat /var/run/reboot-required 2>/dev/null && echo "Reboot needed" || echo "No reboot needed"
cat /var/run/reboot-required.pkgs 2>/dev/null   # Which packages need reboot

# Use kexec for faster kernel updates (no BIOS/GRUB wait):
sudo apt install -y kexec-tools

# Or use livepatch for kernel updates without reboots (Ubuntu Pro feature):
sudo ua enable livepatch   # Requires Ubuntu Pro (free for 5 machines)

# Schedule reboots safely with prior notice:
# Add to cron — reboot at 4 AM if update requires it:
echo "0 4 * * * root [ -f /var/run/reboot-required ] && /sbin/shutdown -r now 'Scheduled reboot for kernel update'" | \
    sudo tee /etc/cron.d/reboot-if-required

Step 7: Exclude Docker Packages

<code"># Docker packages should NOT be auto-updated — they can change container runtime
# behavior and break running containers
# Add to /etc/apt/apt.conf.d/50unattended-upgrades:

Unattended-Upgrade::Package-Blacklist {
    "docker-ce";
    "docker-ce-cli";
    "containerd.io";
    "docker-compose-plugin";
    // Also exclude packages that need migration steps:
    // "postgresql-*";
};

Getting Started

Unattended upgrades should be enabled on every VPS immediately after provisioning — before installing any other software. On Ubuntu VPS plans at VPS.DO, Ubuntu Security releases security patches within hours of upstream disclosure. Automated patching with Telegram notifications gives you the best of both worlds: security without manual monitoring, with immediate notification when patches are applied.

Conclusion

Automatic security updates with unattended-upgrades are the single highest-ROI security improvement for a VPS — eliminating the most common attack vector (known, patched vulnerabilities) with zero daily effort. Configure it to update only security-classified packages, exclude packages that need manual migration (Docker, PostgreSQL major versions), send Telegram notifications when patches apply, and add a Telegram alert for when a kernel reboot is pending. Combined with SSH key auth, UFW, and Fail2ban, automated patching completes a solid VPS security baseline.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!