VPS Automatic Security Updates: Configure unattended-upgrades, Notifications, and Safe Automation
Unpatched software is one of the most common VPS compromise vectors — known vulnerabilities with public exploits are actively scanned and exploited within hours of disclosure. Manually running apt upgrade is error-prone: administrators forget, travel, or deprioritize updates. Ubuntu’s unattended-upgrades package applies security updates automatically, every day, without human intervention — addressing the class of vulnerabilities that require only “keep software current.”
What unattended-upgrades Does (and Doesn’t Do)
By default, unattended-upgrades applies only packages from Ubuntu’s security repositories — packages that fix known CVEs. It does not apply non-security updates (which might change behavior) unless configured to do so. This makes it safe for production servers: security patches go in automatically, feature/compatibility changes do not.
Step 1: Install and Configure
<code">sudo apt install -y unattended-upgrades apt-listchanges # Initial configuration (answer "Yes" to enable) sudo dpkg-reconfigure unattended-upgrades # Verify it's running sudo systemctl status unattended-upgrades
Step 2: Configure Update Scope
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
// Ubuntu security updates (always include)
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
// Optional: include general Ubuntu updates
// "${distro_id}:${distro_codename}";
// "${distro_id}:${distro_codename}-updates";
};
// Packages to blacklist from auto-update (things you want to control manually)
Unattended-Upgrade::Package-Blacklist {
// "php8.2-fpm"; // Uncomment if you want to manage PHP updates manually
// "nginx"; // Uncomment if you prefer manual Nginx updates
};
// Remove unused kernel packages after upgrade
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
// Remove unused automatically-installed packages
Unattended-Upgrade::Remove-Unused-Dependencies "true";
// Automatically reboot ONLY if required (kernel or libc updates)
Unattended-Upgrade::Automatic-Reboot "false"; // Set to "true" to allow auto-reboot
// Reboot time (only applies if Automatic-Reboot is true)
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
// Size limit for downloaded packages (0 = no limit)
Unattended-Upgrade::MinimalSteps "true"; // Apply updates in small atomic steps
Step 3: Configure Update Schedule
sudo nano /etc/apt/apt.conf.d/20auto-upgrades
// 1 = enabled, 0 = disabled
APT::Periodic::Update-Package-Lists "1"; // Refresh package lists daily
APT::Periodic::Download-Upgradeable-Packages "1"; // Download available updates daily
APT::Periodic::Unattended-Upgrade "1"; // Apply security updates daily
APT::Periodic::AutocleanInterval "7"; // Clean package cache weekly
Step 4: Email Notifications
<code">sudo apt install -y mailutils ssmtp sudo nano /etc/ssmtp/ssmtp.conf
root=admin@yourdomain.com
mailhub=smtp.mailgun.org:587
AuthUser=postmaster@mg.yourdomain.com
AuthPass=your_smtp_password
UseTLS=YES
UseSTARTTLS=YES
FromLineOverride=YES
# Add to /etc/apt/apt.conf.d/50unattended-upgrades:
Unattended-Upgrade::Mail "admin@yourdomain.com";
Unattended-Upgrade::MailReport "on-change"; // Email only when something changes
// Options: "always", "on-change", "only-on-error"
Step 5: Telegram Notifications (No SMTP Needed)
sudo nano /usr/local/bin/update-notify.sh
<code">#!/bin/bash
BOT_TOKEN="your_telegram_bot_token"
CHAT_ID="your_telegram_chat_id"
HOSTNAME=$(hostname)
LOG="/var/log/unattended-upgrades/unattended-upgrades.log"
# Check if unattended-upgrades ran today and installed packages
TODAY=$(date '+%Y-%m-%d')
if grep -q "Packages that will be upgraded" "$LOG" 2>/dev/null; then
PACKAGES=$(grep -A5 "Packages that will be upgraded" "$LOG" | tail -1)
MSG="🔒 Security updates applied on $HOSTNAME:\n$PACKAGES"
else
MSG="✅ Security update check completed on $HOSTNAME — no updates needed"
fi
curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
-d "chat_id=$CHAT_ID" \
-d "text=$MSG" \
-d "parse_mode=HTML" > /dev/null
chmod +x /usr/local/bin/update-notify.sh
# Run after daily updates (add to crontab)
sudo crontab -e
# Add:
30 6 * * * /usr/local/bin/update-notify.sh
Step 6: Handle Kernel Updates Safely
Kernel updates require a reboot to take effect. For production servers, plan reboots during low-traffic windows:
<code"># Check if a reboot is required cat /var/run/reboot-required # File exists if reboot needed cat /var/run/reboot-required.pkgs # Which packages triggered it # Schedule a reboot during low-traffic window sudo shutdown -r 03:00 # Reboot at 3 AM sudo shutdown -r +30 # Reboot in 30 minutes sudo shutdown -c # Cancel scheduled reboot # Or configure in unattended-upgrades to reboot automatically at 3 AM: # Unattended-Upgrade::Automatic-Reboot "true"; # Unattended-Upgrade::Automatic-Reboot-Time "03:00";
Testing the Configuration
<code"># Dry run — shows what would be upgraded without making changes sudo unattended-upgrades --dry-run --debug # Run manually to verify configuration works sudo unattended-upgrades -v # View upgrade history cat /var/log/unattended-upgrades/unattended-upgrades.log grep "Packages" /var/log/unattended-upgrades/unattended-upgrades.log | tail -20
Beyond unattended-upgrades: Remaining Security Hygiene
Automatic updates handle one important piece. Also do these manually or on schedule:
- Keep Docker images updated:
docker compose pull && docker compose up -dmonthly - Update Node.js packages:
npm audit fixperiodically - Update Python packages:
pip install -U package_name - Review Fail2ban logs for unusual attack patterns:
sudo fail2ban-client status - Check for new Nginx versions and update configuration headers
Getting Started
Configure unattended-upgrades within the first hour of provisioning any new Ubuntu VPS at VPS.DO. The two-minute setup ensures the server remains patched for known CVEs without ongoing manual effort. Pair with Fail2ban and UFW for a defense-in-depth approach to VPS security.
Conclusion
Automatic security updates via unattended-upgrades eliminate the most common VPS compromise vector — unpatched software with known CVEs. The default configuration applies only security updates (safe for production), removes unused kernel packages, and can notify you of changes via email or Telegram. Manual reboots for kernel updates are a reasonable trade-off for production servers where controlled downtime windows are preferable to automated restarts.