5aaa7020ac
Review fixes: - Availability plays: "ping_result is succeeded" is true for unreachable hosts, so offline hosts were added to reachable_hosts and failed the next play. Test reachability explicitly (7 playbooks). - bootstrap_lxc: vim-enhanced and mtr-tiny package names, enable CRB next to EPEL, add the root key without replacing authorized_keys, validate sshd_config edits and restart sshd only on change. - backup_docker: the command module does not expand $(...); fix rsync filter order and add --exclude=*; restart only the containers that were stopped, even when rsync fails; read the storage address from the inventory; keep semaphore and semaphore-db running. - new_lxc: community.general.proxmox no longer exists, use community.proxmox; node is mini-pc; valid hostname; password or token auth; let the module pick the VMID; longer timeout. - proxmox-backup: surface the vzdump exit code, let vzdump prune with keep-last, drop the rename/prune steps that globbed *.zstd. - time-region: chrony regex no longer comments out its own server line; /etc/localtime as a symlink; reuse facts across plays. - update_pihole_blocklists: FQCN, become: true, changed_when. - ansible.cfg gathering = smart; update_system only pings ubuntu/rocky. Telegram alerts: - health_check: filesystems above disk_warn_pct (default 80), excluding efivarfs, and offline hosts. - service_check: services not running. - One message per run from localhost, credentials from Semaphore (TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID), no_log on the send task, prints the alert text when Telegram is not configured. Claude-Session: https://claude.ai/code/session_01XEizHawueRXUcxQELRZ8kq
145 lines
4.7 KiB
YAML
145 lines
4.7 KiB
YAML
---
|
|
# Enables automatic security updates: unattended-upgrades on Ubuntu and
|
|
# dnf-automatic on Rocky Linux. Neither reboots automatically; use
|
|
# reboot_check.yml for that.
|
|
|
|
- name: Check Host Availability
|
|
hosts: ubuntu:rocky
|
|
gather_facts: false
|
|
ignore_unreachable: true
|
|
|
|
tasks:
|
|
- name: Ping hosts to check availability
|
|
ansible.builtin.ping:
|
|
register: ping_result
|
|
ignore_errors: true
|
|
ignore_unreachable: true
|
|
|
|
- name: Add reachable hosts to group
|
|
ansible.builtin.group_by:
|
|
key: reachable_hosts
|
|
when: ping_result is reachable and ping_result is succeeded
|
|
|
|
- name: Report offline hosts
|
|
ansible.builtin.debug:
|
|
msg: "{{ inventory_hostname }} - OFFLINE"
|
|
when: ping_result is unreachable or ping_result is failed
|
|
delegate_to: localhost
|
|
|
|
- name: Auto Updates - Ubuntu
|
|
hosts: ubuntu:&reachable_hosts
|
|
become: true
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Install unattended-upgrades
|
|
ansible.builtin.apt:
|
|
name: unattended-upgrades
|
|
state: present
|
|
update_cache: true
|
|
cache_valid_time: 3600
|
|
|
|
- name: Enable periodic package list refresh and upgrades
|
|
ansible.builtin.copy:
|
|
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
|
content: |
|
|
// Managed by Ansible (playbooks/auto_updates.yml)
|
|
APT::Periodic::Update-Package-Lists "1";
|
|
APT::Periodic::Unattended-Upgrade "1";
|
|
APT::Periodic::AutocleanInterval "7";
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
|
|
- name: Configure unattended-upgrades behaviour
|
|
ansible.builtin.copy:
|
|
dest: /etc/apt/apt.conf.d/52unattended-upgrades-local
|
|
content: |
|
|
// Managed by Ansible (playbooks/auto_updates.yml)
|
|
// Allowed origins (security / ESM) come from the stock 50unattended-upgrades.
|
|
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
|
Unattended-Upgrade::Automatic-Reboot "false";
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
|
|
- name: Enable apt timers
|
|
ansible.builtin.systemd:
|
|
name: "{{ item }}"
|
|
enabled: true
|
|
state: started
|
|
loop:
|
|
- apt-daily.timer
|
|
- apt-daily-upgrade.timer
|
|
|
|
- name: Dry-run unattended-upgrade
|
|
ansible.builtin.command: unattended-upgrade --dry-run -v
|
|
register: uu_dry_run
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: List apt timers # noqa: command-instead-of-module (read-only listing)
|
|
ansible.builtin.command: systemctl list-timers apt-daily* --no-pager --all
|
|
register: apt_timers
|
|
changed_when: false
|
|
|
|
- name: Print report
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
======================================================
|
|
HOST: {{ inventory_hostname }} ({{ ansible_host }})
|
|
======================================================
|
|
TIMERS:
|
|
{{ apt_timers.stdout }}
|
|
------------------------------------------------------
|
|
DRY RUN (last lines):
|
|
{{ (uu_dry_run.stdout_lines + uu_dry_run.stderr_lines)[-6:] | join('\n') }}
|
|
======================================================
|
|
|
|
- name: Auto Updates - Rocky Linux
|
|
hosts: rocky:&reachable_hosts
|
|
become: true
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Install dnf-automatic
|
|
ansible.builtin.dnf:
|
|
name: dnf-automatic
|
|
state: present
|
|
|
|
- name: Configure dnf-automatic for security updates
|
|
community.general.ini_file:
|
|
path: /etc/dnf/automatic.conf
|
|
section: "{{ item.section }}"
|
|
option: "{{ item.option }}"
|
|
value: "{{ item.value }}"
|
|
mode: '0644'
|
|
loop:
|
|
- { section: commands, option: upgrade_type, value: security }
|
|
- { section: commands, option: download_updates, value: "yes" }
|
|
- { section: commands, option: apply_updates, value: "yes" }
|
|
- { section: emitters, option: emit_via, value: stdio }
|
|
loop_control:
|
|
label: "{{ item.section }}/{{ item.option }} = {{ item.value }}"
|
|
|
|
- name: Enable dnf-automatic timer
|
|
ansible.builtin.systemd:
|
|
name: dnf-automatic.timer
|
|
enabled: true
|
|
state: started
|
|
|
|
- name: List dnf-automatic timers # noqa: command-instead-of-module (read-only listing)
|
|
ansible.builtin.command: systemctl list-timers dnf-automatic* --no-pager --all
|
|
register: dnf_timers
|
|
changed_when: false
|
|
|
|
- name: Print report
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
======================================================
|
|
HOST: {{ inventory_hostname }} ({{ ansible_host }})
|
|
======================================================
|
|
TIMERS:
|
|
{{ dnf_timers.stdout }}
|
|
======================================================
|