latest commit

This commit is contained in:
2026-02-11 09:15:51 +01:00
commit da1bc20ea3
4 changed files with 458 additions and 0 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Allan Christensen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

169
README.md Normal file
View File

@@ -0,0 +1,169 @@
# Auto Update for Ubuntu 24.04 Server
[![OS](https://img.shields.io/badge/ubuntu-24.04-E95420)](#)
[![Shell](https://img.shields.io/badge/shell-bash-121011)](#)
[![Feature](https://img.shields.io/badge/feature-controlled_updates-0078D7)](#)
[![Cron](https://img.shields.io/badge/scheduler-cron-lightgrey)](#)
[![License](https://img.shields.io/badge/License-MIT-green)](./LICENSE)
Install unattended security and system updates on Ubuntu 24.04 server.
This is not a demo and not a quick experiment.
This is a production-ready policy tool designed to enforce predictable update behaviour.
---
## Why this installer exists
Ubuntu includes unattended-upgrades, but configuration is often inconsistent, unclear, or left in default states that do not match operational policy.
This script provides a repeatable way to enforce a defined update policy, ensuring systems are patched regularly and reboot behaviour is predictable.
---
## What this installer does
✔ Configures unattended-upgrades using a clean, deterministic policy
✔ Allows switching between four update modes
✔ Ensures updates are enforced on a fixed weekly schedule
✔ Automatically rebuilds the unattended-upgrades configuration safely
✔ Leaves Ubuntus timers untouched
✔ Safe to re-run and switch modes at any time
✔ Logs policy changes for auditing and troubleshooting
✔ Uses vendor defaults as a base to preserve compatibility
---
## What this installer does NOT do
It wont stop you from running the script without reading the documentation like theres no tomorrow.
Skip the README, and whatever happens next is your headache, not a bug report.
---
## 1. Download the installer
```
git clone https://git.x-files.dk/server/auto-update-ubuntu.git
```
```
cd auto-update-ubuntu
```
---
## 2. Run the installer
```
sudo ./auto-update <mode>
```
Example:
```
sudo ./auto-update 2
```
---
## Available modes
The modes control two things:
- Which updates are installed
- Whether the system reboots automatically if required
The script is built with re-runs in mind.
If you need to switch modes, simply run the script again with another mode.
The current policy will be replaced automatically.
**Mode 1**
Security + updates (full system updates, not security-only)
Automatic reboot
Reboot happens even if users are logged in
**Mode 2**
Security + updates (full system updates, not security-only)
No automatic reboot
Users are notified on next login if a reboot is required
**Mode 3**
Security updates only
Automatic reboot
Reboot happens even if users are logged in
**Mode 4**
Security updates only
No automatic reboot
Users are notified on next login if a reboot is required
---
## How it works
The script rebuilds the unattended-upgrades configuration from Ubuntus vendor template each time a mode is applied.
This ensures a clean and predictable configuration and avoids problems caused by manually edited or partially modified files.
If you manually edit `/etc/apt/apt.conf.d/50unattended-upgrades`, those changes will be overwritten, but only when you switch modes.
A cron job (`/etc/cron.d/auto-update`) is created to enforce updates every Friday at 03:00.
This ensures that systems are updated regularly even if users postpone updates during the week.
Ubuntus systemd timers are left untouched.
If both timers and the cron job run, nothing breaks — updates may simply be checked more than once.
---
## Cron behaviour
The cron job is created the first time a mode is applied and is scheduled to run every Friday at 03:00.
The cron file is created as:
```
/etc/cron.d/auto-update
```
You are free to change the schedule to any time you prefer, or even run it daily if required.
The script does not modify or reset the cron job after it has been created.
Switching modes does not alter the existing cron schedule.
---
## Common questions
**Q:** Why am I still seeing available updates? Is the script not working?**
**A:** These notifications are generated by Ubuntus default update timers, which this script does not disable.
You may still see update notifications during the week, even though the cron enforcement job runs on Friday.
If you log in on a Tuesday and updates are available, you are encouraged to install them manually.
This will not conflict with the script.
You may also see updates appear shortly after the scheduled run.
This simply means new updates were released after the last scheduled update cycle.
---
## Logging
Policy changes are logged to:
```
/var/log/auto-update.log
```
This log records when a mode was applied and which user executed the script.
Package installation and upgrade details are logged by unattended-upgrades in:
```
/var/log/unattended-upgrades/
```
---
### More Information
More guides and documentation can be found on [wiki.x-files.dk](https://wiki.x-files.dk)
---
### License
Licensed under the [MIT License](./LICENSE).

264
auto-update-ubuntu Executable file
View File

@@ -0,0 +1,264 @@
#!/usr/bin/env bash
# Author : Allan Christensen
# First Created : 12-03-2021 (DD-MM-YYYY)
# Description : Manage unattended-upgrades policy on Ubuntu 24.04
# License : MIT License
#
# Are we root
#
if [[ $(id -u) -ne 0 ]]; then echo "" && echo "Must be root or use sudo" && echo "" ; exit ; fi
#
# Variables
#
config="/etc/apt/apt.conf.d/50unattended-upgrades"
template="/usr/share/unattended-upgrades/50unattended-upgrades"
cronfile="/etc/cron.d/auto-update"
logfile="/var/log/auto-update.log"
#
# Log timestamp format
# Default: DD-MM-YYYY HH:MM
# Change to "+%Y-%m-%d %H:%M" for ISO format if preferred
#
log_date_format="+%d-%m-%Y %H:%M"
#
# Create safe temporary file
#
tmpfile="$(mktemp /tmp/auto-update.XXXXXX)"
trap 'rm -f "$tmpfile"' EXIT
#
# Function: Ensure config exists
#
chkcfg () {
if [[ ! -f "$1" ]]; then
printf "Config missing: %s → copying from %s\n" "$1" "$2"
cp -Rp "$2" "$1"
fi
}
#
# Function: Detect current mode
#
detect_mode() {
managed="false"
updates_enabled="false"
reboot_enabled="false"
reboot_users_enabled="false"
current_mode="unknown"
if grep -q "Managed by auto-update" "$config"; then
managed="true"
else
return
fi
grep -q '${distro_codename}-updates' "$config" && updates_enabled="true"
grep -q 'Automatic-Reboot "true"' "$config" && reboot_enabled="true"
grep -q 'Automatic-Reboot-WithUsers "true"' "$config" && reboot_users_enabled="true"
if [[ "$updates_enabled" == "true" && "$reboot_enabled" == "true" ]]; then
current_mode=1
elif [[ "$updates_enabled" == "true" && "$reboot_enabled" == "false" ]]; then
current_mode=2
elif [[ "$updates_enabled" == "false" && "$reboot_enabled" == "true" ]]; then
current_mode=3
else
current_mode=4
fi
}
#
# Function: Show status and usage
#
show_status() {
detect_mode
if [[ "$managed" != "true" ]]; then
printf "\nCurrent policy: Not yet managed by auto-update\n"
printf "System default unattended-upgrades configuration detected.\n"
else
printf "\nCurrent policy: Mode %s\n" "$current_mode"
if [[ "$updates_enabled" == "true" ]]; then
printf "Updates: Security + updates\n"
else
printf "Updates: Security only\n"
fi
if [[ "$reboot_enabled" == "true" ]]; then
printf "Automatic reboot: Yes\n"
else
printf "Automatic reboot: No\n"
fi
if [[ "$reboot_users_enabled" == "true" ]]; then
printf "Reboot even if users are logged in: Yes\n"
else
printf "Reboot even if users are logged in: No\n"
fi
fi
printf "Cron enforcement: Friday at 03:00\n"
printf "\nUsage:\n"
printf " auto-update <mode>\n\n"
printf "Modes:\n"
printf " 1 Security + updates, automatic reboot\n"
printf " 2 Security + updates, no reboot\n"
printf " 3 Security only, automatic reboot\n"
printf " 4 Security only, no reboot\n\n"
}
#
# Function: Apply mode
#
apply_mode() {
local mode="$1"
cp "$template" "$tmpfile" || {
echo "Failed to copy template. Aborting."
exit 1
}
sed -i '/Unattended-Upgrade::Allowed-Origins {/,/};/d' "$tmpfile"
sed -i '/Unattended-Upgrade::Automatic-Reboot /d' "$tmpfile"
sed -i '/Unattended-Upgrade::Automatic-Reboot-WithUsers /d' "$tmpfile"
case "$mode" in
1)
origins_block=' "${distro_id}:${distro_codename}-security";
"${distro_id}:${distro_codename}-updates";'
reboot_value="true"
reboot_users_value="true"
;;
2)
origins_block=' "${distro_id}:${distro_codename}-security";
"${distro_id}:${distro_codename}-updates";'
reboot_value="false"
reboot_users_value="false"
;;
3)
origins_block=' "${distro_id}:${distro_codename}-security";'
reboot_value="true"
reboot_users_value="true"
;;
4)
origins_block=' "${distro_id}:${distro_codename}-security";'
reboot_value="false"
reboot_users_value="false"
;;
*)
printf "\nInvalid mode.\n\n"
exit 1
;;
esac
cat <<EOF >> "$tmpfile"
//
// Managed by auto-update
//
Unattended-Upgrade::Allowed-Origins {
$origins_block
};
Unattended-Upgrade::Automatic-Reboot "$reboot_value";
Unattended-Upgrade::Automatic-Reboot-WithUsers "$reboot_users_value";
EOF
mv "$tmpfile" "$config"
}
#
# Function: Ensure cron job exists
#
ensure_cron() {
if [[ ! -f "$cronfile" ]]; then
printf "Creating cron enforcement job...\n"
cat <<EOF > "$cronfile"
# Runs auto-update policy enforcement every Friday at 03:00
0 3 * * 5 root /usr/bin/apt-get update -qq && /usr/bin/unattended-upgrade -v >/dev/null 2>&1
EOF
chmod 644 "$cronfile"
chown root:root "$cronfile"
else
printf "Cron job already exists (%s), leaving it unchanged.\n" "$cronfile"
fi
}
#
# Install required packages
#
apt-get update -qq
apt-get install -y unattended-upgrades update-notifier-common >/dev/null
#
# Ensure configuration exists
#
chkcfg "$config" "$template"
#
# Argument handling
#
if [[ -z "$1" ]]; then
show_status
exit 0
fi
mode="$1"
if [[ ! "$mode" =~ ^[1-4]$ ]]; then
printf "\nInvalid mode. Please select 1-4.\n"
show_status
exit 1
fi
#
# Apply selected mode
#
printf "\nApplying Mode %s...\n" "$mode"
apply_mode "$mode"
ensure_cron
#
# Log action
#
actor="${SUDO_USER:-root}"
printf "%s Mode %s applied by %s\n" "$(date "$log_date_format")" "$mode" "$actor" >> "$logfile"
#
# Restart services
#
systemctl restart unattended-upgrades.service >/dev/null
systemctl restart cron.service >/dev/null
#
# Show resulting status
#
show_status
#
# All done
#
printf "\nAll Done...\n"
#
# End of script
#

4
last-tested Normal file
View File

@@ -0,0 +1,4 @@
------------------------------------
Last tested: 10-02-2026 (DD-MM-YYYY)
Environment: Ubuntu Server 24.04 LTS
------------------------------------