$ -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y msmtp msmtp-mta mailutils
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y msmtp msmtp-mta mailutils
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y msmtp msmtp-mta mailutils
-weight: 600;">sudo nano /etc/msmtprc
-weight: 600;">sudo nano /etc/msmtprc
-weight: 600;">sudo nano /etc/msmtprc
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log account gmail
host smtp.gmail.com
port 587
from your-email@gmail.com
user your-email@gmail.com
password your-app-password-here account default: gmail
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log account gmail
host smtp.gmail.com
port 587
from your-email@gmail.com
user your-email@gmail.com
password your-app-password-here account default: gmail
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log account gmail
host smtp.gmail.com
port 587
from your-email@gmail.com
user your-email@gmail.com
password your-app-password-here account default: gmail
-weight: 600;">sudo chmod 600 /etc/msmtprc
-weight: 600;">sudo chmod 600 /etc/msmtprc
-weight: 600;">sudo chmod 600 /etc/msmtprc
-weight: 600;">sudo nano /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo nano /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo nano /usr/local/bin/-weight: 500;">update-notify.sh
#!/bin/bash
RECIPIENT="your-email@gmail.com"
HOSTNAME=$(hostname) # Refresh package lists
-weight: 500;">apt-get -weight: 500;">update -qq # Get the list of upgradable packages
UPDATES=$(-weight: 500;">apt list --upgradable 2>/dev/null | grep -v "Listing...")
COUNT=$(echo "$UPDATES" | grep -c "/" || true) # Get system stats
DISK=$(df / | awk 'NR==2 {print $5}')
MEMORY=$(free -h | awk '/^Mem:/ {print $3 "/" $2}') # Send email with all the information
echo -e "Subject: [$HOSTNAME] Weekly Server Report\n\nDisk: $DISK\nMemory: $MEMORY\nPending updates: $COUNT\n\n$UPDATES" \ | msmtp "$RECIPIENT"
#!/bin/bash
RECIPIENT="your-email@gmail.com"
HOSTNAME=$(hostname) # Refresh package lists
-weight: 500;">apt-get -weight: 500;">update -qq # Get the list of upgradable packages
UPDATES=$(-weight: 500;">apt list --upgradable 2>/dev/null | grep -v "Listing...")
COUNT=$(echo "$UPDATES" | grep -c "/" || true) # Get system stats
DISK=$(df / | awk 'NR==2 {print $5}')
MEMORY=$(free -h | awk '/^Mem:/ {print $3 "/" $2}') # Send email with all the information
echo -e "Subject: [$HOSTNAME] Weekly Server Report\n\nDisk: $DISK\nMemory: $MEMORY\nPending updates: $COUNT\n\n$UPDATES" \ | msmtp "$RECIPIENT"
#!/bin/bash
RECIPIENT="your-email@gmail.com"
HOSTNAME=$(hostname) # Refresh package lists
-weight: 500;">apt-get -weight: 500;">update -qq # Get the list of upgradable packages
UPDATES=$(-weight: 500;">apt list --upgradable 2>/dev/null | grep -v "Listing...")
COUNT=$(echo "$UPDATES" | grep -c "/" || true) # Get system stats
DISK=$(df / | awk 'NR==2 {print $5}')
MEMORY=$(free -h | awk '/^Mem:/ {print $3 "/" $2}') # Send email with all the information
echo -e "Subject: [$HOSTNAME] Weekly Server Report\n\nDisk: $DISK\nMemory: $MEMORY\nPending updates: $COUNT\n\n$UPDATES" \ | msmtp "$RECIPIENT"
-weight: 600;">sudo chmod +x /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo chmod +x /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo chmod +x /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo /usr/local/bin/-weight: 500;">update-notify.sh
-weight: 600;">sudo cat /var/log/msmtp.log
-weight: 600;">sudo cat /var/log/msmtp.log
-weight: 600;">sudo cat /var/log/msmtp.log
echo "0 6 * * 0 root /usr/local/bin/-weight: 500;">update-notify.sh" | -weight: 600;">sudo tee /etc/cron.d/-weight: 500;">update-notify
echo "0 6 * * 0 root /usr/local/bin/-weight: 500;">update-notify.sh" | -weight: 600;">sudo tee /etc/cron.d/-weight: 500;">update-notify
echo "0 6 * * 0 root /usr/local/bin/-weight: 500;">update-notify.sh" | -weight: 600;">sudo tee /etc/cron.d/-weight: 500;">update-notify
-weight: 600;">sudo cat /etc/cron.d/-weight: 500;">update-notify
-weight: 600;">sudo cat /etc/cron.d/-weight: 500;">update-notify
-weight: 600;">sudo cat /etc/cron.d/-weight: 500;">update-notify
Disk: 28%
Memory: 1.4Gi/11Gi
Pending updates: 9 containerd.io/jammy 2.2.4-1~ubuntu.22.04~jammy arm64 [upgradable from: 2.2.3-1~ubuntu.22.04~jammy]
-weight: 500;">docker-ce/jammy 5:29.5.2-1~ubuntu.22.04~jammy arm64 [upgradable from: 5:29.5.1-1~ubuntu.22.04~jammy]
-weight: 500;">docker-ce-cli/jammy 5:29.5.2-1~ubuntu.22.04~jammy arm64 [upgradable from: 5:29.5.1-1~ubuntu.22.04~jammy]
...
Disk: 28%
Memory: 1.4Gi/11Gi
Pending updates: 9 containerd.io/jammy 2.2.4-1~ubuntu.22.04~jammy arm64 [upgradable from: 2.2.3-1~ubuntu.22.04~jammy]
-weight: 500;">docker-ce/jammy 5:29.5.2-1~ubuntu.22.04~jammy arm64 [upgradable from: 5:29.5.1-1~ubuntu.22.04~jammy]
-weight: 500;">docker-ce-cli/jammy 5:29.5.2-1~ubuntu.22.04~jammy arm64 [upgradable from: 5:29.5.1-1~ubuntu.22.04~jammy]
...
Disk: 28%
Memory: 1.4Gi/11Gi
Pending updates: 9 containerd.io/jammy 2.2.4-1~ubuntu.22.04~jammy arm64 [upgradable from: 2.2.3-1~ubuntu.22.04~jammy]
-weight: 500;">docker-ce/jammy 5:29.5.2-1~ubuntu.22.04~jammy arm64 [upgradable from: 5:29.5.1-1~ubuntu.22.04~jammy]
-weight: 500;">docker-ce-cli/jammy 5:29.5.2-1~ubuntu.22.04~jammy arm64 [upgradable from: 5:29.5.1-1~ubuntu.22.04~jammy]
...
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">upgrade -y
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">upgrade -y
-weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">upgrade -y
-weight: 600;">sudo -weight: 500;">docker ps --format "table {{.Names}}\t{{.Status}}"
-weight: 600;">sudo -weight: 500;">docker ps --format "table {{.Names}}\t{{.Status}}"
-weight: 600;">sudo -weight: 500;">docker ps --format "table {{.Names}}\t{{.Status}}"
-weight: 600;">sudo tail -f /var/log/msmtp.log
-weight: 600;">sudo tail -f /var/log/msmtp.log
-weight: 600;">sudo tail -f /var/log/msmtp.log - Why Automation Matters for Updates
- The Architecture
- Prerequisites - Step 1: Create a Gmail App Password
- Step 2: Install Mail Utilities
- Step 3: Configure Gmail SMTP
- Step 4: Create the Update Notification Script
- Step 5: Test the Script
- Step 6: Schedule With Cron - Understanding Your Update Report
- Applying Updates Safely
- Wrapping Up - You remember sporadically, if at all
- Updates pile up and become harder to review
- When you finally apply them, there's a larger blast radius
- You miss the pattern of what's actually changing on your system - An Ubuntu server (22.04 or later works fine)
SSH access with -weight: 600;">sudo privileges
- A Gmail account with 2FA enabled (for the app password)
- About 10 minutes of setup time - Go to your Google Account β Security
- Scroll to "App passwords" (only visible if 2FA is enabled)
- Select "Mail" and "Windows Computer" (the actual device doesn't matter)
- Google generates a 16-character password like lqxu mdsxjwbj mast
- Copy this password as you'll use it in the next step. - auth on enables SMTP authentication
tls on encrypts the connection
- port 587 is Gmail's submission port (not 25 or 465)
- password is the 16-character app password (without spaces) - Authentication failed: Your app password is wrong. Double-check it in Gmail's security settings, and make sure you removed spaces when pasting it into msmtprc.
- TLS error: Less common, but if you see this, try tls_trust_file /etc/ssl/certs/ca-certificates.crt (which is already in the config above).
- Timeout: Your firewall might be blocking port 587. Contact your hosting provider or check firewall rules. - 0 = minute 0
- 6 = hour 6 (UTC)
- * = any day of month
- * = any month