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 #