Files
auto-update-ubuntu/auto-upgrade-new
2026-01-30 09:35:27 +01:00

260 lines
5.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Author : Allan Christensen
# First Created : 23-06-2022 (DD-MM-YYYY)
# Description : OPS-controlled unattended-upgrades policy configuration for 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 1
fi
#
# Variables
#
mode="${1:-}"
config1="/etc/apt/apt.conf.d/20auto-upgrades"
config1alt="/usr/share/unattended-upgrades/20auto-upgrades"
config2="/etc/apt/apt.conf.d/50unattended-upgrades"
config2alt="/usr/share/unattended-upgrades/50unattended-upgrades"
cronfile="/etc/cron.d/updatesystem"
#
# Functions
#
die () {
echo "Error: $*" >&2
exit 1
}
usage () {
cat <<EOF
Usage: $0 <mode>
Please select ONE of the following modes:
1 Security + software updates
Automatic reboot immediately after upgrades complete
2 Security + software updates
No automatic reboot
Users will be notified on next login if a reboot is required
3 Security updates only
Automatic reboot immediately after upgrades complete
4 Security updates only
No automatic reboot
Users will be notified on next login if a reboot is required
EOF
exit 1
}
chkcfg () {
if [[ ! -f "$1" ]]; then
[[ -f "$2" ]] || die "Missing source config: $2"
cp -Rp "$2" "$1" || die "Failed to copy $2 to $1"
fi
}
mkorig () {
if [[ ! -f "${1}.orig" ]]; then
cp -Rp "$1" "${1}.orig" || die "Failed to create backup: ${1}.orig"
fi
}
#
# Disable Ubuntu automatic timers (OPS owns scheduling)
#
disable_apt_timers () {
systemctl disable --now apt-daily.timer apt-daily-upgrade.timer >/dev/null 2>&1 || true
systemctl mask apt-daily.service apt-daily-upgrade.service >/dev/null 2>&1 || true
}
#
# Ensure periodic jobs are disabled (cron owns execution)
#
set_20auto () {
sed -i 's|^\s*APT::Periodic::Update-Package-Lists.*|APT::Periodic::Update-Package-Lists "0";|' "$config1"
sed -i 's|^\s*APT::Periodic::Unattended-Upgrade.*|APT::Periodic::Unattended-Upgrade "0";|' "$config1"
}
#
# Allowed origins explicit, Bash-native
#
set_allowed_origins () {
local allow_updates="$1"
#
# Always enable security updates
#
sed -i \
'/^\s*\/\/\s*"\${distro_id}:\${distro_codename}-security"/ s|^\s*//\s*||' \
"$config2"
#
# Enable or disable non-security updates
#
if [[ "$allow_updates" == "true" ]]; then
sed -i \
'/^\s*\/\/\s*"\${distro_id}:\${distro_codename}-updates"/ s|^\s*//\s*||' \
"$config2"
else
sed -i \
'/^\s*"\${distro_id}:\${distro_codename}-updates"/ s|^|// |' \
"$config2"
fi
}
#
# Reboot policy immediate reboot after upgrades
#
set_reboot_policy () {
local reboot="$1"
local reboot_with_users="$2"
#
# Automatic-Reboot (exact key only)
#
sed -i \
'/^\s*\/\/\s*Unattended-Upgrade::Automatic-Reboot\s/ s|^\s*//\s*||' \
"$config2"
sed -i \
's|^\s*Unattended-Upgrade::Automatic-Reboot\s*".*";|Unattended-Upgrade::Automatic-Reboot "'"$reboot"'";|' \
"$config2"
#
# Automatic-Reboot-WithUsers (exact key only)
#
sed -i \
'/^\s*\/\/\s*Unattended-Upgrade::Automatic-Reboot-WithUsers\s/ s|^\s*//\s*||' \
"$config2"
sed -i \
's|^\s*Unattended-Upgrade::Automatic-Reboot-WithUsers\s*".*";|Unattended-Upgrade::Automatic-Reboot-WithUsers "'"$reboot_with_users"'";|' \
"$config2"
#
# Ensure reboot-time stays commented (cron defines timing)
#
sed -i \
'/^\s*Unattended-Upgrade::Automatic-Reboot-Time/ s|^|// |' \
"$config2"
}
#
# Cron authoritative schedule
#
write_cron () {
cat > "$cronfile" <<EOF
#
# Managed by: auto-update-ubuntu
# Purpose : OPS-controlled unattended upgrades
# Schedule : Every Friday at 03:00
#
0 3 * * 5 root /usr/bin/apt update && /usr/bin/unattended-upgrade -v >/dev/null 2>&1
EOF
chmod 644 "$cronfile" || die "Failed chmod on $cronfile"
chown root:root "$cronfile" || die "Failed chown on $cronfile"
}
restart_services () {
systemctl restart unattended-upgrades.service >/dev/null 2>&1 || die "Failed to restart unattended-upgrades"
systemctl restart cron.service >/dev/null 2>&1 || die "Failed to restart cron"
}
#
# Validate mode
#
case "$mode" in
1|2|3|4) ;;
*) usage ;;
esac
#
# Informational output (configuration-time only)
#
echo "Applying unattended-upgrades policy:"
echo ""
case "$mode" in
1)
echo " Mode: 1"
echo " Updates: Security + software updates"
echo " Reboot: Immediate reboot after upgrades complete"
;;
2)
echo " Mode: 2"
echo " Updates: Security + software updates"
echo " Reboot: Disabled"
echo " User notification: On next login if a reboot is required"
;;
3)
echo " Mode: 3"
echo " Updates: Security updates only"
echo " Reboot: Immediate reboot after upgrades complete"
;;
4)
echo " Mode: 4"
echo " Updates: Security updates only"
echo " Reboot: Disabled"
echo " User notification: On next login if a reboot is required"
;;
esac
echo ""
#
# Packages (no implicit apt update)
#
apt-get -y -qq install unattended-upgrades update-notifier-common >/dev/null \
|| die "Package install failed"
#
# Ensure configs exist
#
chkcfg "$config1" "$config1alt"
chkcfg "$config2" "$config2alt"
#
# Backup originals (once)
#
mkorig "$config1"
mkorig "$config2"
#
# OPS-owned execution model
#
set_20auto
disable_apt_timers
#
# Apply policy
#
case "$mode" in
1|2) set_allowed_origins "true" ;;
3|4) set_allowed_origins "false" ;;
esac
case "$mode" in
1|3) set_reboot_policy "true" "true" ;;
2|4) set_reboot_policy "false" "false" ;;
esac
#
# Cron + services
#
write_cron
restart_services
exit 0