--- # playbooks/onboarding/watchtower_update.yml # OS package update for the Ansible control node (Watchtower). # # ───────────────────────────────────────────────────────────────────────────── # ⚠️ HUMAN-TRIGGERED ONLY — do not automate or schedule. # Watchtower is not a Swarm member, so no drain/restore is needed. # Reboot will briefly interrupt Ansible control plane connectivity. # ───────────────────────────────────────────────────────────────────────────── # # What this does: # 1. Runs apt dist-upgrade # 2. Reboots if a newer kernel was installed and waits for return # # NOTE: Because Watchtower connects to itself via ansible_connection=local, # the reboot module uses localhost semantics (the node reboots and # Ansible waits for the local machine to come back). # # Usage: # ansible-playbook -i inventory/hosts.ini playbooks/onboarding/watchtower_update.yml # # # Dry-run: # ansible-playbook -i inventory/hosts.ini playbooks/onboarding/watchtower_update.yml --check # # # Update packages but skip reboot even if kernel changed: # ansible-playbook -i inventory/hosts.ini playbooks/onboarding/watchtower_update.yml --skip-tags reboot - name: Watchtower control node OS update hosts: watchtower become: true tasks: - name: Update apt cache ansible.builtin.apt: update_cache: true cache_valid_time: 0 - name: Run apt dist-upgrade ansible.builtin.apt: upgrade: dist update_cache: false register: dist_upgrade_result tags: [update] - name: Check if a newer kernel is installed but not yet booted ansible.builtin.shell: | LATEST=$(ls /boot/vmlinuz-* | sort -V | tail -1 | sed 's|/boot/vmlinuz-||') RUNNING=$(uname -r) if [ "$LATEST" != "$RUNNING" ]; then echo "reboot_needed"; fi register: reboot_check changed_when: false check_mode: false tags: [reboot] - name: Reboot if a newer kernel is installed ansible.builtin.reboot: msg: "Rebooting into updated kernel — initiated by watchtower_update.yml" reboot_timeout: 300 when: reboot_check.stdout | trim == 'reboot_needed' tags: [reboot] - name: Wait for Watchtower to return post-reboot ansible.builtin.wait_for_connection: delay: 10 timeout: 300 when: reboot_check.stdout | trim == 'reboot_needed' tags: [reboot] - name: Report result ansible.builtin.debug: msg: >- ✅ Watchtower updated. {{ 'Rebooted into new kernel.' if reboot_check.stdout | trim == 'reboot_needed' else 'No kernel change — reboot not required.' }}