Files
ansible/update-packages.yml
Martin Bauer f043606466 Add deliberate update playbook and unattended-upgrades role
Regular playbooks now use state: present, so they no longer upgrade
packages as a side effect. This adds two separate, explicit mechanisms
to keep the fleet patched instead:

- update-packages.yml: ad hoc / to-be-scheduled fleet-wide upgrade
  (safe by default, dist available via -e), plus
  update-packages-pinned-example.yml as a template for pinning or
  bumping a single package outside that.
- roles/unattended_upgrades: automatic security-only patching via
  unattended-upgrades, with a scheduled reboot window and mail
  left disabled pending a configured MTA. Applied to every host in
  full.yml and server.yml.

Also removes a leftover `upgrade: yes` apt task from pi_standard_setup
and server_basic_environment that was still doing a full upgrade on
every routine run, defeating the point of the state: present switch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-08 18:02:41 +02:00

51 lines
2.1 KiB
YAML

---
# Deliberate, fleet-wide package update run. Decoupled on purpose from
# full.yml/server.yml (which use state: present and must stay idempotent/
# no-op on routine runs) — this is the one place packages actually get
# upgraded.
#
# Ad hoc run:
# just update <limit>
# venv/bin/ansible-playbook update-packages.yml --limit <host_or_group>
#
# Dry run first:
# venv/bin/ansible-playbook update-packages.yml --limit <host_or_group> --check --diff
#
# Scheduling: not automated yet. When you're ready, the simplest option is
# a crontab entry on whichever machine you normally run ansible-playbook
# from, e.g. weekly at 04:00 on Sundays:
# 0 4 * * 0 cd /path/to/this/repo && venv/bin/ansible-playbook update-packages.yml >> update.log 2>&1
# Adjust the schedule by editing that line (`crontab -e`). Note this only
# fires if that machine is on and networked at the scheduled time.
#
# upgrade type tradeoff (update_packages_upgrade_type, default "safe"):
# safe - upgrades packages in place, never installs/removes packages to
# resolve dependencies. Won't silently swap out a kernel
# meta-package or drop something. Recommended default for an
# unattended/fleet-wide run.
# dist - full upgrade, will install/remove packages as needed (kernel
# transitions, etc). More thorough, more surprising. Use
# deliberately: `-e update_packages_upgrade_type=dist`.
- name: Update packages across the fleet
hosts: all
vars:
update_packages_upgrade_type: safe
update_packages_autoremove: false
tasks:
- name: Update apt cache and upgrade packages
ansible.builtin.apt:
update_cache: true
upgrade: "{{ update_packages_upgrade_type }}"
autoremove: "{{ update_packages_autoremove }}"
register: update_packages_result
- name: Check whether a reboot is required after this upgrade
ansible.builtin.stat:
path: /var/run/reboot-required
register: update_packages_reboot_required
- name: Report reboot required
ansible.builtin.debug:
msg: "Reboot required on {{ inventory_hostname }}"
when: update_packages_reboot_required.stat.exists