You've already forked auto-update-ubuntu
latest commit
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal 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
169
README.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Auto Update for Ubuntu 24.04 Server
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](./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 Ubuntu’s 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 won’t stop you from running the script without reading the documentation like there’s 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 Ubuntu’s 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.
|
||||
|
||||
Ubuntu’s 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 Ubuntu’s 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
264
auto-update-ubuntu
Executable 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
4
last-tested
Normal file
@@ -0,0 +1,4 @@
|
||||
------------------------------------
|
||||
Last tested: 10-02-2026 (DD-MM-YYYY)
|
||||
Environment: Ubuntu Server 24.04 LTS
|
||||
------------------------------------
|
||||
Reference in New Issue
Block a user