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>
This commit is contained in:
9
roles/unattended_upgrades/README.md
Normal file
9
roles/unattended_upgrades/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# unattended_upgrades
|
||||
|
||||
Installs and configures `unattended-upgrades` for automatic security
|
||||
patching, separate from `update-packages.yml` (which handles deliberate,
|
||||
scheduled full-package updates — see the repo README). Security-only by
|
||||
default. Reboots when required, at a fixed scheduled time (default 03:00),
|
||||
rather than never or immediately — see `defaults/main.yml` to change this.
|
||||
Mail-on-failure is supported but disabled by default since no mail
|
||||
transport is configured on these hosts yet.
|
||||
21
roles/unattended_upgrades/defaults/main.yml
Normal file
21
roles/unattended_upgrades/defaults/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
# Restrict to security-origin updates only (not a full dist-upgrade).
|
||||
unattended_upgrades_security_only: true
|
||||
|
||||
# Extra Origins-Pattern lines appended verbatim, for when
|
||||
# unattended_upgrades_security_only is turned off later (e.g. to also allow
|
||||
# the "-updates" pocket). Left empty by default.
|
||||
unattended_upgrades_origins_extra: []
|
||||
|
||||
# Reboot handling. Off by default would mean patches needing a reboot never
|
||||
# take effect until someone reboots manually; scheduled means an automatic
|
||||
# reboot at a fixed, low-traffic time on the days it's actually needed.
|
||||
unattended_upgrades_auto_reboot: true
|
||||
unattended_upgrades_auto_reboot_time: "03:00"
|
||||
|
||||
unattended_upgrades_remove_unused_deps: true
|
||||
|
||||
# Set to a mail address (and ensure a working mail transport is configured
|
||||
# on the host) to get notified on failure. Empty disables mail entirely.
|
||||
unattended_upgrades_mail_to: ""
|
||||
unattended_upgrades_mail_on_only_error: true
|
||||
31
roles/unattended_upgrades/tasks/main.yml
Normal file
31
roles/unattended_upgrades/tasks/main.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
- name: Install unattended-upgrades
|
||||
ansible.builtin.apt:
|
||||
name: unattended-upgrades
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Configure unattended-upgrades behavior
|
||||
ansible.builtin.template:
|
||||
src: 50unattended-upgrades.j2
|
||||
dest: /etc/apt/apt.conf.d/50unattended-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable periodic apt update / unattended-upgrade timers
|
||||
ansible.builtin.template:
|
||||
src: 20auto-upgrades.j2
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Ensure apt daily timers are enabled and running
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- apt-daily.timer
|
||||
- apt-daily-upgrade.timer
|
||||
7
roles/unattended_upgrades/templates/20auto-upgrades.j2
Normal file
7
roles/unattended_upgrades/templates/20auto-upgrades.j2
Normal file
@@ -0,0 +1,7 @@
|
||||
// Managed by Ansible (roles/unattended_upgrades) — changes will be overwritten.
|
||||
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Download-Upgradeable-Packages "1";
|
||||
APT::Periodic::AutocleanInterval "7";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
APT::Periodic::Verbose "1";
|
||||
29
roles/unattended_upgrades/templates/50unattended-upgrades.j2
Normal file
29
roles/unattended_upgrades/templates/50unattended-upgrades.j2
Normal file
@@ -0,0 +1,29 @@
|
||||
// Managed by Ansible (roles/unattended_upgrades) — changes will be overwritten.
|
||||
|
||||
Unattended-Upgrade::Origins-Pattern {
|
||||
{% if unattended_upgrades_security_only %}
|
||||
"origin=${distro_id},codename=${distro_codename},label=${distro_id}-Security";
|
||||
"origin=${distro_id},codename=${distro_codename}-security,label=${distro_id}-Security";
|
||||
"origin=Debian,codename=${distro_codename},label=Debian-Security";
|
||||
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
|
||||
{% else %}
|
||||
"origin=${distro_id},codename=${distro_codename}";
|
||||
"origin=${distro_id},codename=${distro_codename}-security";
|
||||
"origin=${distro_id},codename=${distro_codename}-updates";
|
||||
{% endif %}
|
||||
{% for origin in unattended_upgrades_origins_extra %}
|
||||
"{{ origin }}";
|
||||
{% endfor %}
|
||||
};
|
||||
|
||||
Unattended-Upgrade::Remove-Unused-Dependencies "{{ unattended_upgrades_remove_unused_deps | lower }}";
|
||||
|
||||
Unattended-Upgrade::Automatic-Reboot "{{ unattended_upgrades_auto_reboot | lower }}";
|
||||
Unattended-Upgrade::Automatic-Reboot-Time "{{ unattended_upgrades_auto_reboot_time }}";
|
||||
|
||||
Unattended-Upgrade::SyslogEnable "true";
|
||||
|
||||
{% if unattended_upgrades_mail_to %}
|
||||
Unattended-Upgrade::Mail "{{ unattended_upgrades_mail_to }}";
|
||||
Unattended-Upgrade::MailOnlyOnError "{{ unattended_upgrades_mail_on_only_error | lower }}";
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user