From 08e7de1b6ddb90480e693a23dd41e47a7f37423f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 12 Aug 2026 18:56:27 +0000 Subject: [PATCH] move unattended-upgrades into core utils, and make sure it is actually on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit apt only. It is a Debian and Ubuntu package — dnf's equivalent is dnf-automatic and pacman has no equivalent at all — so it is not a name to translate across the other lists. Installing the package is not by itself enough to switch it on. The apt-daily timers read /etc/apt/apt.conf.d/20auto-upgrades, and on this host no package owns that file: `dpkg -S` says it came from nothing, which means the original script wrote it. So the section checks for it and offers to write it, rather than assuming the install did. Beyond that it only reports, because the interesting facts about unattended upgrades are not whether it installed: It never reboots on its own, deliberately. A kernel or libc update is installed and then not used, and the machine keeps running the old one until it restarts. Nothing announces that except /var/run/reboot-required, which nobody reads. The section prints it, names the packages waiting, and puts it in the summary — it is the failure people do not notice for months. Ubuntu's Allowed-Origins includes plain ${distro_codename} as well as -security, so this takes ordinary updates too, not only security ones. Verified both paths: this host reports enabled with no reboot pending, and pointing AUTO_UPGRADES at a temp file exercises the enable path and writes the three periodic settings. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/setup/machine-setup/lib/packages.sh | 11 +++- scripts/setup/machine-setup/machine-setup.sh | 65 +++++++++++++++++++- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/scripts/setup/machine-setup/lib/packages.sh b/scripts/setup/machine-setup/lib/packages.sh index 30340db5..c7a31a30 100644 --- a/scripts/setup/machine-setup/lib/packages.sh +++ b/scripts/setup/machine-setup/lib/packages.sh @@ -51,7 +51,14 @@ LAST_SKIPPED=() # are the environment: nothing calls them, they are here because a box you use # should have them. # -# Two entries reach beyond simply existing on the machine. +# Three entries reach beyond simply existing on the machine. +# +# unattended-upgrades installs updates on a timer with nobody watching. apt only: +# it is a Debian and Ubuntu package, dnf's equivalent is dnf-automatic and pacman +# has no equivalent at all, so it is not a name to translate. Installing the +# package is not by itself enough to switch it on — /etc/apt/apt.conf.d/20auto-upgrades +# is what the apt-daily timers read, and on this host no package owns that file. +# The section makes sure it is there. # # fail2ban is not a tool, it is a daemon: installing it starts it, and Ubuntu # ships /etc/fail2ban/jail.d/defaults-debian.conf with `[sshd] enabled = true`. @@ -76,7 +83,7 @@ pkgs_core() { echo curl ca-certificates gnupg git jq unzip \ apt-transport-https lsb-release software-properties-common \ wget zip build-essential btop htop tree tmux ripgrep fd-find net-tools \ - fail2ban + fail2ban unattended-upgrades ;; pacman) echo curl ca-certificates gnupg git jq unzip \ diff --git a/scripts/setup/machine-setup/machine-setup.sh b/scripts/setup/machine-setup/machine-setup.sh index e9177872..08c7dbe8 100755 --- a/scripts/setup/machine-setup/machine-setup.sh +++ b/scripts/setup/machine-setup/machine-setup.sh @@ -1203,13 +1203,76 @@ if ! skip; then step_ok fi +# ============================================================================= +# 19. Unattended upgrades +# ============================================================================= +# +# The package comes from core utils. This makes sure it is actually switched on, +# and reports the one thing about it nobody notices. + +AUTO_UPGRADES=/etc/apt/apt.conf.d/20auto-upgrades + +step "Unattended upgrades" +if ! skip; then + echo "" + info "Unattended upgrades — security updates installed on a timer, unattended" + + if ! pkg_is_installed unattended-upgrades; then + echo " not installed — it is part of core utils, which was declined or skipped" + SUMMARY+=("Unattended upgrades: not installed") + else + UU_ENABLED=false + grep -qs '^APT::Periodic::Unattended-Upgrade "1"' "$AUTO_UPGRADES" && UU_ENABLED=true + + echo " package: installed" + echo " enabled: $($UU_ENABLED && echo 'yes' || echo 'no')" + echo " timers: $(systemctl is-enabled apt-daily.timer 2>/dev/null), $(systemctl is-enabled apt-daily-upgrade.timer 2>/dev/null)" + + if $UU_ENABLED; then + SUMMARY+=("Unattended upgrades: enabled") + else + echo "" + echo " The package is there but ${AUTO_UPGRADES} does not switch it on," + echo " so the timers run and do nothing. Writing that file is the whole" + echo " of enabling it." + if confirm "Enable it?"; then + cat >"$AUTO_UPGRADES" <<'EOF' +// Written by machine-setup. +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +APT::Periodic::AutocleanInterval "7"; +EOF + ok "enabled — updates apply daily, package cache cleaned weekly" + SUMMARY+=("Unattended upgrades: enabled") + else + warn "skipped by request" + SUMMARY+=("Unattended upgrades: installed but NOT enabled") + fi + fi + + # The failure mode people do not notice for months: a kernel update is + # installed but the machine keeps running the old one until it reboots, and + # nothing says so except this file. + echo "" + if [[ -f /var/run/reboot-required ]]; then + warn "a reboot is pending — updates are installed but not all of them are in use" + [[ -r /var/run/reboot-required.pkgs ]] && sed 's/^/ /' /var/run/reboot-required.pkgs + echo " Unattended upgrades never reboots on its own, deliberately. Until" + echo " this machine restarts it keeps running the old kernel or library." + SUMMARY+=("Reboot: PENDING — updates installed but not active") + else + echo " no reboot pending" + fi + fi + step_ok +fi + # ============================================================================= # NOT PORTED YET # ============================================================================= # # Sections still to move across from scripts/setup-old/setup-ubuntu.sh, in order: # -# unattended-upgrades · # git config · docker · zsh + prompt (incl. .tmux.conf) · tailscale · neovim · js runtimes · # dev tools · ufw · zshrc #