Unattended Upgrades with Email Notifications - Keeping Your Raspberry Pi Secure
In my last post, I discussed setting up an SFTP server on Raspberry Pi for Obsidian notes. When running a server, it is important to keep the security patches up-to-date. Old, unpatched software leaves systems vulnerable. The unattended-upgrades package on Debian-based systems (like Raspberry Pi OS) can automatically install security patches for you. This is a great way to keep your system up-to-date without having to manually check for updates and install them yourself.
In this post, we’ll cover installing and configuring unattended-upgrades, and we’ll set up Postfix to email you notifications when updates occur.
Caution: Although convenient, automatically updating has risks like unwanted changes or new bugs. Monitor your system’s status and updates regularly via logs or notifications. And frequently backup data, especially on production systems.
Prerequisites/Assumptions in this guide:
- You have a Raspberry Pi running Raspberry Pi OS (Debian version 11 - Bullseye).
- You already have SSH access to your Pi (or you can access the Pi terminal by some other login method like direct access or VNC).
- Your Raspberry Pi is on the same local area network as the computer you’re using to access it.
- You have a Gmail account to use for email notifications.
- You have a basic understanding of how to use the Linux terminal.
Part I: Installing and Configuring Unattended Upgrades
1. Login into the Pi via SSH (or any other means that you find convenient)
1
2
# Example:
ssh pi@raspberrypi
Note: The default user should be pi
, and the default hostname is typically raspberrypi
. It would be wise to change these to something else if you haven’t already done so. You could also use the Pi’s IPv4 address or its FQDN instead of the hostname if you prefer.
2. Update the Apt Package Manager and Upgrade Existing Packages
1
sudo apt update && sudo apt upgrade -y && sudo reboot
This will update your existing packages and reboot the Pi. Wait for the Pi to reboot and then log back in via SSH.
3. Install Unattended Upgrades
Installing unattended-upgrades is simple, just run the following command in your terminal:
1
sudo apt install unattended-upgrades -y
4. Enable Unattended Upgrades
Enable unattended-upgrades to run automatically by running the following command:
1
sudo dpkg-reconfigure --priority=low unattended-upgrades
At the confirmation prompt, select Yes to enable unattended upgrades.
5. Open the Unattended Upgrades Configuration File
The main configuration file for unattended-upgrades is located at /etc/apt/apt.conf.d/50unattended-upgrades. To open the 50unattended-upgrades
file in a terminal-based text editor such as nano, run the following command:
1
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
- If you’re unfamiliar with how to use nano, you can find a quick reference guide here.
6. Select Which Updates To Activate
To enable automatic package downloads and installation of security updates, look for the below line in the 50unattended-upgrades
file and make your settings match the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Unattended-Upgrade::Origins-Pattern {
// Codename based matching:
// This will follow the migration of a release through different
// archives (e.g. from testing to stable and later oldstable).
// Software will be the latest available for the named release,
// but the Debian release itself will not be automatically upgraded.
"origin=Debian,codename=${distro_codename}-updates"; // this line enables regular package updates from the Debian archive
// "origin=Debian,codename=${distro_codename}-proposed-updates";
"origin=Debian,codename=${distro_codename},label=Debian"; // this line enables non-security updates labeled as 'Debian' from the Debian archive
"origin=Debian,codename=${distro_codename},label=Debian-Security"; // this line enables security updates from the Debian archive
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security"; // this line enables security updates from the Debian archive
"origin=Raspbian,codename=${distro_codename},label=Raspbian"; // this line enables non-security updates labeled as 'Raspbian' from the Raspbian archive
"origin=Raspberry Pi Foundation,codename=${distro_codename},label=Raspberry Pi Foundation"; // this line enables non-security updates labeled as 'Raspberry Pi Foundation' from the Raspberry Pi Foundation archive
// Archive or Suite based matching:
// Note that this will silently match a different release after
// migration to the specified archive (e.g. testing becomes the
// new stable).
// "o=Debian,a=stable";
// "o=Debian,a=stable-updates";
// "o=Debian,a=proposed-updates";
// "o=Debian Backports,a=${distro_codename}-backports,l=Debian Backports";
};
Note, you will need to uncomment lines that you want to activate by removing the //
to the left of the line. To enable Raspberry Pi OS-specific updates, you’ll also need to add the origin patterns for Raspbian and Raspberry Pi Foundation to the above list.
7. Enable Auto-Reboot After Updates
To automatically reboot the server after updates that require it, find the following line in the 50unattended-upgrades
file and make your settings match the following:
1
Unattended-Upgrade::Automatic-Reboot "true";
Be aware that this will reboot your server without warning, so plan maintenance windows accordingly. You can set a specific time for the reboot to occur by uncommenting the following line to activate it and setting the time to your desired value:
1
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
8. Optional - install powermgmt-base:
- If your Pi is run on battery power, you can configure unattended-upgrades to only run when it’s connected to AC power. This requires the powermgmt-base package. You can install it with:
1
sudo apt install powermgmt-base
Then, in the
50unattended-upgrades
file, uncomment the lineUnattended-Upgrade::OnlyOnACPower "true";
to enforce this setting.”
9. Test Unattended Upgrades
To test unattended-upgrades, run the following command in your terminal:
1
sudo unattended-upgrades --dry-run --debug
If you see output that looks like the following, then you’re good to go!
1
2
3
4
5
6
7
8
9
10
11
12
Starting unattended upgrades script
Allowed origins are: origin=Debian,codename=bookworm-updates, origin=Debian,codename=bookworm,label=Debian, origin=Debian,codename=bookworm,label=Debian-Security, origin=Debian,codename=bookworm-security,label=Debian-Security, origin=Raspbian,codename=bookworm,label=Raspbian, origin=Raspberry Pi Foundation,codename=bookworm,label=Raspberry Pi Foundation
Initial blacklist:
Initial whitelist (not strict):
Using (^linux-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^kfreebsd-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^gnumach-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-modules-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-kernel-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^linux-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^kfreebsd-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^gnumach-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-modules-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-kernel-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$) regexp to find kernel packages
Using (^linux-.*-6\.1\.0\-rpi4\-rpi\-v8$|^kfreebsd-.*-6\.1\.0\-rpi4\-rpi\-v8$|^gnumach-.*-6\.1\.0\-rpi4\-rpi\-v8$|^.*-modules-6\.1\.0\-rpi4\-rpi\-v8$|^.*-kernel-6\.1\.0\-rpi4\-rpi\-v8$|^linux-.*-6\.1\.0\-rpi4\-rpi\-v8$|^kfreebsd-.*-6\.1\.0\-rpi4\-rpi\-v8$|^gnumach-.*-6\.1\.0\-rpi4\-rpi\-v8$|^.*-modules-6\.1\.0\-rpi4\-rpi\-v8$|^.*-kernel-6\.1\.0\-rpi4\-rpi\-v8$) regexp to find running kernel packages
pkgs that look like they should be upgraded:
Fetched 0 B in 0s (0 B/s)
fetch.run() result: 0
Packages blacklist due to conffile prompts: []
No packages found that can be upgraded unattended and no pending auto-removals
The list of kept packages can't be calculated in dry-run mode.
NOTE - if you do not want to enable email notifications, you can stop right here. But if you want to enable email notifications, keep reading…
Part II. Configuring Email Notifications with Postfix
10. Enable Email Notifications
To receive email notifications when updates are performed, add your email address to the following line in the 50unattended-upgrades
file (using your real email address):
1
Unattended-Upgrade::Mail "your-email-address@example.com";
11. Set the frequency of email notifications.
You can choose how often you receive email notifications from the unattended-upgrades script by setting your notification preference to one of these options: “always”, “only-on-error”, or “on-change”. We will set our notification preference to “always” to receive an email notification every time the script is run.
1 Unattended-Upgrade::MailReport "always";
12. Create an App Password for Gmail
To use Gmail for our email notifications, we will need to get a Gmail App Password. To do this, follow this guide from Google: How to generate App Passwords.
Important- Be sure to copy the password to a safe place once it is generated, as you will not be able to view it again after closing the window.
13. Install Postfix for Email Notifications
To enable the email notifications from unattended-upgrades, we’ll be using the Postfix application. Postfix is a mail transfer agent (MTA) that can be used to send and receive email. For our purposes, we will only configure Postfix to send email notifications from unattended-upgrades.
- When installing Postfix, you’ll be prompted to enter your system mail name, which should be your Pi’s domain name. Use the following terminal command to get this before installing Postfix and jot it down for later use:
1
hostname -f
- To install Postfix, run the following command:
1
sudo apt install postfix -y
During the Postfix configuration select “Internet Site”, and specify your Raspberry Pi’s domain (from above) as the “mail name.”
TIP: I found the following guide from Tony Florida to be very helpful for learning how to set this up (https://tonyteaches.tech/postfix-gmail-smtp-on-ubuntu/)
14. Configure settings for Simple Authentication and Security Layer (SASL).
SASL provides a method for adding authentication support for Postfix to allow us to send email through our Gmail account.
- First, check to make sure that the
/etc/postfix/sasl/
directory exists by runningls -la /etc/postfix
in your terminal. You should see the sasl directory in the output. If the directory doesn’t exist, you can create it using the mkdir command as follows:1
sudo mkdir -p /etc/postfix/sasl/
The -p option tells mkdir to create parent directories as needed.
- Now create a file named
sasl_passwd
in the /etc/postfix/sasl/ directory by running the following command:1
sudo touch /etc/postfix/sasl/sasl_passwd
- Next, add your email address and Google App password to the sasl_passwd file by running the following command:
1
sudo nano /etc/postfix/sasl/sasl_passwd
- Then add the following line to the sasl_passwd file (using your actual email and App Password). Note - there should be no spaces between the characters in your Gmail App Password:
1
[smtp.gmail.com]:587 your-email@gmail.com:your-app-password
- Then add the following line to the sasl_passwd file (using your actual email and App Password). Note - there should be no spaces between the characters in your Gmail App Password:
15. Next, we will use the Postmap command to create a database file from the sasl_passwd file we just created.
- To do this, run the following command:
1
sudo postmap /etc/postfix/sasl/sasl_passwd
- If you look in the directory at /etc/postfix/sasl, you should now see a new file named sasl_passwd.db.
- This file is used by Postfix to authenticate with Gmail when sending email. (See this guide for more details.)
16. Now, change the permissions to make sure that only the root user can read or write to the sasl_passwd and sasl_passwd.db files. To do this, run the following commands (separately):
1
2
sudo chown root:root /etc/postfix/sasl/sasl_passwd /etc/postfix/sasl/sasl_passwd.db
sudo chmod 0600 /etc/postfix/sasl/sasl_passwd /etc/postfix/sasl/sasl_passwd.db
We’re almost done, I promise…hang in there! 😊
17. Now we need to configure the main Postfix configuration file:
The main configuration file for Postfix is in the following directory: /etc/postfix/main.cf. To open the main.cf file in a terminal-based text editor such as nano, run the following command:
1
sudo nano /etc/postfix/main.cf
Then find the following relayhost =
line, and change your settings to match the following:
1
relayhost = [smtp.gmail.com]:587
18. Add the following lines to the bottom of the main.cf file (credit to Tony Florida’s guide here):
1
2
3
4
5
6
# Enable SASL authentication
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
19. Restart Postfix with the following command:
1
sudo systemctl restart postfix
20. Now - let’s test to see if unattended-upgrades can send email notifications. To do this, run the following command:
1
sudo unattended-upgrades -d
For this to work, you will need the notification preference set to ‘always’ (see step 11).
You should see output that looks like the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Starting unattended upgrades script
Allowed origins are: origin=Debian,codename=bookworm-updates, origin=Debian,codename=bookworm,label=Debian, origin=Debian,codename=bookworm,label=Debian-Security, origin=Debian,codename=bookworm-security,label=Debian-Security, origin=Raspbian,codename=bookworm,label=Raspbian, origin=Raspberry Pi Foundation,codename=bookworm,label=Raspberry Pi Foundation
Initial blacklist:
Initial whitelist (not strict):
Using (^linux-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^kfreebsd-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^gnumach-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-modules-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-kernel-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^linux-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^kfreebsd-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^gnumach-.*-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-modules-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$|^.*-kernel-[1-9][0-9]*\.[0-9]+\.[0-9]+-[0-9]+(-.+)?$) regexp to find kernel packages
Using (^linux-.*-6\.1\.0\-rpi4\-rpi\-v8$|^kfreebsd-.*-6\.1\.0\-rpi4\-rpi\-v8$|^gnumach-.*-6\.1\.0\-rpi4\-rpi\-v8$|^.*-modules-6\.1\.0\-rpi4\-rpi\-v8$|^.*-kernel-6\.1\.0\-rpi4\-rpi\-v8$|^linux-.*-6\.1\.0\-rpi4\-rpi\-v8$|^kfreebsd-.*-6\.1\.0\-rpi4\-rpi\-v8$|^gnumach-.*-6\.1\.0\-rpi4\-rpi\-v8$|^.*-modules-6\.1\.0\-rpi4\-rpi\-v8$|^.*-kernel-6\.1\.0\-rpi4\-rpi\-v8$) regexp to find running kernel packages
pkgs that look like they should be upgraded:
Fetched 0 B in 0s (0 B/s)
fetch.run() result: 0
Packages blacklist due to conffile prompts: []
No packages found that can be upgraded unattended and no pending auto-removals
Extracting content from /var/log/unattended-upgrades/unattended-upgrades-dpkg.log since 2023-10-26 15:42:01
Sending mail to your-email@example.com
sendmail: warning: /etc/postfix/main.cf, line 53: overriding earlier entry: smtp_tls_security_level=may
postdrop: warning: /etc/postfix/main.cf, line 53: overriding earlier entry: smtp_tls_security_level=may
mail returned: 0
If you receive an email notification, then you’re all set! 🎉 If you didn’t receive an email, then you’ll need to go back and check your settings to make sure everything is correct.
Conclusion
Keeping your Linux systems up-to-date with the latest security patches is vital for defense against attacks. Manually applying updates is time-consuming and inefficient. Using the unattended-upgrades package automates the process of installing security updates in the background and makes the process much more efficient. Additionally, configuring email notifications via Postfix provides visibility into update activity.
I hope this guide was helpful! If you have any questions or comments, please feel free to reach out to me on LinkedIn or by email.