~/jackwent.co.uk
jack@jackwent:~$ cat ubuntu-autopatch.sh

Ubuntu 24.04 AutoPatch Script

by published 24 August 2024updated 11 October 20263 min read

What it does

Keeping servers patched is one of those jobs that’s important, boring and easy to forget. This script does it for you on Ubuntu 24.04. It updates your packages, deals with any that get kept back, and makes sure the server ends up fully up to date. If a reboot is needed afterwards, it does that too. Set it up once and your servers look after themselves.

#!/bin/bash

# Define a file to track progress
PROGRESS_FILE="/var/log/update-script-progress"

# Function to check if a reboot is required
check_reboot() {
    if [ -f /var/run/reboot-required ]; then
        echo "Reboot required. Rebooting now..."
        echo "step1_reboot" > $PROGRESS_FILE
        reboot
        exit 0
    fi
}

# Function to check the progress and continue where left off
check_progress() {
    if [ -f $PROGRESS_FILE ]; then
        PROGRESS=$(cat $PROGRESS_FILE)
        case $PROGRESS in
            "step1_reboot")
                echo "Continuing after first reboot..."
                step2_install_updates
                ;;
            "step2_updates")
                echo "Continuing after updates..."
                step3_install_kept_back
                ;;
            "step3_kept_back")
                echo "Continuing after installing kept-back packages..."
                check_reboot_after_updates
                ;;
            *)
                echo "Unknown progress state, starting from the beginning."
                start_script
                ;;
        esac
    else
        start_script
    fi
}

# Function to start the script
start_script() {
    check_reboot
    step2_install_updates
}

# Function to perform updates
step2_install_updates() {
    echo "Updating package lists..."
    sudo apt update

    echo "Upgrading installed packages..."
    # Set non-interactive frontend to avoid prompts
    sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --with-new-pkgs

    echo "step2_updates" > $PROGRESS_FILE
    step3_install_kept_back
}

# Function to install kept-back packages
step3_install_kept_back() {
    echo "Installing kept-back packages..."
    # Install kept-back packages by explicitly listing them
    KEPT_BACK=$(apt list --upgradable 2>/dev/null | grep -P '^\S+' -o)
    if [ -n "$KEPT_BACK" ]; then
        sudo DEBIAN_FRONTEND=noninteractive apt-get install -y $KEPT_BACK
    fi

    echo "step3_kept_back" > $PROGRESS_FILE
    check_reboot_after_updates
}

# Function to check if a reboot is required after updates
check_reboot_after_updates() {
    check_reboot
    cleanup
}

# Function to clean up unnecessary packages
cleanup() {
    echo "Cleaning up unnecessary packages..."
    sudo apt autoremove -y
    sudo apt autoclean

    echo "System is up to date. No reboot required."
    rm -f $PROGRESS_FILE
}

# Start or continue the script
check_progress

Features

  1. Automatic updates. It refreshes the package lists, upgrades everything installed, and also installs packages that would normally be kept back during an upgrade.
  2. Automatic reboots. If an update needs a reboot (a new kernel, for example), the script reboots the server for you.
  3. Progress tracking. It records how far it’s got in /var/log/update-script-progress, so if it’s interrupted, by a reboot for instance, it carries on where it left off.
  4. Runs unattended. Everything runs non-interactively, so it’s perfect for cron and never sits waiting for someone to press a key.

How it works

  1. Checks for a pending reboot. First it looks to see if a previous update already needs a reboot, and reboots if so.
  2. Updates and upgrades. It refreshes the package lists (apt update), upgrades installed packages (apt-get upgrade --with-new-pkgs), then installs any held back packages explicitly (apt-get install).
  3. Reboots if needed. Once the updates are done it checks again and reboots if required.
  4. Tidies up. It removes packages that are no longer needed and clears out the cache (apt autoremove, apt autoclean) to free up space.
  5. Logs as it goes. Progress is saved at each step so it can always pick up again after an interruption.

Where I use it

I still run this script on some of my own servers, where it patches them every night without anyone touching them. It suits the servers where a nightly reboot doesn’t matter and nothing needs careful timing. For a server other things depend on, it’s safer to patch at a time you choose, with a snapshot or backup taken first so there’s a clean way back.

Setting it up

Save the script to a file on your server, for example /opt/scripts/update-script.sh.

Make it executable:

sudo chmod +x /opt/scripts/update-script.sh

Schedule it with cron. To run it every night at 2am, open your crontab:

sudo crontab -e

Then add:

# Run the script at 2 AM every day to ensure the system is updated
0 2 * * * /opt/scripts/update-script.sh >> /var/log/update-script.log 2>&1

# Run the script at system reboot to continue updates if the system was rebooted during an update
@reboot /opt/scripts/update-script.sh >> /var/log/update-script.log 2>&1

The first line is the nightly 2am run that does the regular updates.

The @reboot line is the important one. If the server reboots part way through an update, whether the script rebooted it or someone did it by hand, this makes sure the script starts again on boot and finishes the job.

Between the two, your server gets updated every night and never gets left half way through.

Running it by hand. You can also run it yourself at any time:

sudo /opt/scripts/update-script.sh

Worth knowing

  • Logs. Progress goes to /var/log/update-script-progress and, with the cron setup above, the output goes to /var/log/update-script.log. It’s worth keeping an eye on these, at least for the first few runs.
  • Permissions. The script needs to run commands like apt-get and reboot, so it needs root (or sudo).
  • Test it first. Run it by hand once before you hand it over to cron, so you know it behaves on your server.

Once that’s in place your server keeps itself patched, which cuts down your exposure to security holes and means you’re always on the latest fixes.

Disclaimer

Before you run any automated update script, make sure you’ve got backups you trust. Regular backups are the thing that gets you out of trouble when something unexpected happens.

This script is designed to apply updates safely and cope with reboots along the way, but automatic updates always carry some risk.

You use this script at your own risk. I can’t take responsibility for any damage, data loss or downtime that comes from running it. Please make sure you have full backups before using this, or any other automation, on your systems.

[jackwent]