Auto-update legacy-of-lunatic-kingdom weekly
Auto-reboot stays off given data on /mnt, so node-exporter surfaces
last-run, pending-security, and reboot-required to keep the runs
observable.
Assisted-by: Claude Opus 4.8 via Claude Code
diff --git a/legacy-of-lunatic-kingdom/main.yml b/legacy-of-lunatic-kingdom/main.yml
index c7abf92..f0e61c3 100644
--- a/legacy-of-lunatic-kingdom/main.yml
+++ b/legacy-of-lunatic-kingdom/main.yml
@@ -10,19 +10,38 @@
- net-tools # ifconfig
- neovim
- prometheus-node-exporter
+ - prometheus-node-exporter-collectors # apt_info + reboot-required metrics
- python3-lxml # ansible bcrypt
state: present
update_cache: true
- - name: Include /mnt in node-exporter
+ - name: Configure node-exporter collectors
+ vars:
+ # The systemd + apt collectors expose unattended-upgrades health to the
+ # node-exporter target (last run, pending security updates, reboot
+ # needed). See playbooks/unattended-upgrades.yml.
+ node_exporter_args:
+ - --collector.textfile.directory=/var/lib/prometheus/node-exporter
+ - --collector.systemd
+ - --collector.systemd.unit-include=apt-daily.*\.(timer|service)
+ - >-
+ --collector.filesystem.mount-points-exclude=^/(dev|proc|run|sys|media|var/lib/docker/.+|var/lib/containers/storage/.+)($|/)
ansible.builtin.lineinfile:
path: /etc/default/prometheus-node-exporter
regexp: '^ARGS='
- line: 'ARGS="--collector.filesystem.mount-points-exclude=^/(dev|proc|run|sys|media|var/lib/docker/.+|var/lib/containers/storage/.+)($|/)"'
+ line: 'ARGS="{{ node_exporter_args | join(" ") }}"'
create: true
mode: '0644'
notify: Restart node exporter
+ # Periodically regenerates apt.prom (pending upgrades, reboot-required) in
+ # the textfile directory above.
+ - name: Enable node-exporter apt collector
+ ansible.builtin.systemd:
+ name: prometheus-node-exporter-apt.timer
+ enabled: true
+ state: started
+
handlers:
- name: Restart node exporter
ansible.builtin.systemd:
@@ -60,9 +79,10 @@
state: restarted
# TODO disallow network access from non-tailscale interfaces
-- import_playbook: ../playbooks/tailscale.yml # noqa: name[play]
-- import_playbook: ../playbooks/docker.yml # noqa: name[play]
-- import_playbook: ../playbooks/syncthing.yml # noqa: name[play]
+- import_playbook: ../playbooks/tailscale.yml # noqa: name[play]
+- import_playbook: ../playbooks/docker.yml # noqa: name[play]
+- import_playbook: ../playbooks/syncthing.yml # noqa: name[play]
+- import_playbook: ../playbooks/unattended-upgrades.yml # noqa: name[play]
# TODO
# - restic
diff --git a/playbooks/unattended-upgrades.yml b/playbooks/unattended-upgrades.yml
new file mode 100644
index 0000000..24798fb
--- /dev/null
+++ b/playbooks/unattended-upgrades.yml
@@ -0,0 +1,63 @@
+# https://wiki.debian.org/UnattendedUpgrades
+- name: Configure unattended upgrades
+ tags: unattended-upgrades
+ hosts: all
+ become: true
+ tasks:
+
+ - name: Assert distribution is Debian
+ ansible.builtin.assert:
+ that:
+ - ansible_facts["distribution"] == "Debian"
+ fail_msg: "This playbook only supports Debian distributions"
+
+ # sudo apt-get install unattended-upgrades
+ - name: Install unattended-upgrades
+ ansible.builtin.apt:
+ name: unattended-upgrades
+ state: present
+ update_cache: true
+
+ # Refresh package lists and pre-download upgrades daily (via apt-daily.timer)
+ # so the weekly apply below is fast. Origins stay at the package default
+ # (security only), the safe choice for an unattended box holding data on /mnt.
+ - name: Enable periodic unattended upgrades
+ ansible.builtin.copy:
+ content: |
+ APT::Periodic::Update-Package-Lists "1";
+ APT::Periodic::Download-Upgradeable-Packages "1";
+ APT::Periodic::Unattended-Upgrade "1";
+ APT::Periodic::AutocleanInterval "7";
+ dest: /etc/apt/apt.conf.d/20auto-upgrades
+ mode: "0644"
+
+ - name: Create apt-daily-upgrade.timer override directory
+ ansible.builtin.file:
+ path: /etc/systemd/system/apt-daily-upgrade.timer.d
+ state: directory
+ mode: "0755"
+
+ # Apply upgrades weekly instead of daily. The empty OnCalendar clears the
+ # packaged daily schedule before setting the weekly one (OnCalendar is
+ # additive otherwise). Persistent catches up a run missed while powered off.
+ - name: Apply unattended upgrades weekly
+ ansible.builtin.copy:
+ content: |
+ [Timer]
+ OnCalendar=
+ OnCalendar=Sun *-*-* 03:00
+ RandomizedDelaySec=30m
+ Persistent=true
+ dest: /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf
+ mode: "0644"
+ notify: Reload apt-daily-upgrade timer
+
+ handlers:
+
+ - name: Reload apt-daily-upgrade timer
+ ansible.builtin.systemd:
+ name: apt-daily-upgrade.timer
+ state: restarted
+ daemon_reload: true
+
+# vim: ft=yaml.ansible