homelab/ansible/archive/playbooks/docker/heimdall_baseline.yml

157 lines
5.6 KiB
YAML

---
# playbooks/docker/heimdall_baseline.yml
# Idempotent OS baseline enforcement for the Heimdall edge router host.
#
# ─────────────────────────────────────────────────────────────────────────────
# PURPOSE: Ongoing OS drift enforcement — safe to run any time, safe to schedule.
# Does NOT upgrade packages. Does NOT reboot.
# Does NOT touch the Traefik/Redis application stack.
# For the application stack: use playbooks/self-heal/heimdall.yml
# For OS updates: use playbooks/docker/heimdall_update.yml
# For audit: use playbooks/docker/heimdall_audit.yml
# ─────────────────────────────────────────────────────────────────────────────
#
# What this enforces (all idempotent):
# 0. Packages: Required system packages present (docker-ce, nfs-common, etc.)
# 1. Storage: Swap disabled (swapoff + fstab + zram masked)
# 2. Sysctl: vm.swappiness=0, bridge netfilter, ip_forward
# 3. Docker: /etc/docker/daemon.json with log rotation
#
# Usage:
# ansible-playbook -i inventory/hosts.ini playbooks/docker/heimdall_baseline.yml
#
# # Dry-run:
# ansible-playbook -i inventory/hosts.ini playbooks/docker/heimdall_baseline.yml --check --diff
#
# # Target a specific section:
# ansible-playbook -i inventory/hosts.ini playbooks/docker/heimdall_baseline.yml --tags sysctl
- name: Heimdall OS baseline enforcement
hosts: heimdall
become: true
vars:
lab_user: "{{ lab_ansible_user | default('chester') }}"
handlers:
- name: Restart Docker
ansible.builtin.service:
name: docker
state: restarted
tasks:
- name: "0. Packages: ensure required system packages are present"
tags: [packages, baseline]
ansible.builtin.apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- nfs-common
- curl
- htop
- ca-certificates
state: present
update_cache: true
- name: "1. Storage: disable swap"
tags: [storage, baseline]
block:
- name: Disable swap immediately (covers traditional + zram)
ansible.builtin.command: swapoff -a
when: ansible_swaptotal_mb > 0
changed_when: ansible_swaptotal_mb > 0
- name: Comment out swap entries in /etc/fstab
ansible.builtin.replace:
path: /etc/fstab
regexp: '^([^#].*\s+swap\s+.*)$'
replace: '# \1'
- name: Remove zram-generator config to prevent zram swap at boot
ansible.builtin.copy:
dest: /etc/systemd/zram-generator.conf
owner: root
group: root
mode: '0644'
content: |
# Managed by Ansible — heimdall_baseline.yml
# Empty config disables zram swap on Ubuntu 24.04.
- name: Stop and mask systemd-zram-generator service if present
ansible.builtin.systemd:
name: systemd-zram-generator
state: stopped
enabled: false
masked: true
failed_when: false
- name: Swapoff zram devices explicitly
ansible.builtin.shell: |
for dev in $(ls /dev/zram* 2>/dev/null); do
swapoff "$dev" 2>/dev/null || true
done
changed_when: false
- name: "2. Sysctl: Docker networking parameters"
tags: [sysctl, baseline]
block:
- name: Ensure br_netfilter module is loaded
community.general.modprobe:
name: br_netfilter
state: present
- name: Persist br_netfilter module load at boot
ansible.builtin.copy:
dest: /etc/modules-load.d/br_netfilter.conf
content: "br_netfilter\n"
owner: root
group: root
mode: '0644'
- name: Apply and persist sysctl parameters
ansible.posix.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
sysctl_file: /etc/sysctl.d/90-heimdall.conf
state: present
reload: true
loop:
- { key: vm.swappiness, value: "0" }
- { key: net.bridge.bridge-nf-call-iptables, value: "1" }
- { key: net.bridge.bridge-nf-call-ip6tables, value: "1" }
- { key: net.ipv4.ip_forward, value: "1" }
- name: "3. Docker: daemon configuration and log rotation"
tags: [docker, baseline]
block:
- name: Ensure /etc/docker directory exists
ansible.builtin.file:
path: /etc/docker
state: directory
owner: root
group: root
mode: '0755'
- name: Deploy Docker daemon.json with log rotation
ansible.builtin.copy:
dest: /etc/docker/daemon.json
owner: root
group: root
mode: '0644'
content: |
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
notify: Restart Docker
- name: Ensure '{{ lab_user }}' is in the docker group
ansible.builtin.user:
name: "{{ lab_user }}"
groups: docker
append: true