--- # ══════════════════════════════════════════════════════════════════════════════ # Security Updates Role # # 1. Configures apt to allow Docker CE security patches (not major upgrades) # 2. Deploys a container image update script (pulls new base images, rebuilds # if changed, restarts affected services) # 3. Deploys a k3s patch update script (stays on current channel, patch only) # 4. Sets up systemd timers for all of the above # 5. Sends admin email when manual intervention is required # ══════════════════════════════════════════════════════════════════════════════ # ── 1. Docker CE: pin major version, allow patch updates ──────────────────── - name: Install apt-mark hold for Docker CE (prevent major version jumps) ansible.builtin.shell: | current=$(dpkg-query -W -f='${Version}' docker-ce 2>/dev/null | grep -oP '^\d+' || echo "") if [ -n "$current" ] && [ "$current" = "{{ docker_major_version_pin }}" ]; then # Same major — ensure NOT held so patches flow through unattended-upgrades apt-mark unhold docker-ce docker-ce-cli containerd.io 2>/dev/null || true else # Different major — hold to prevent auto-upgrade apt-mark hold docker-ce docker-ce-cli containerd.io 2>/dev/null || true fi changed_when: false - name: Deploy Docker version guard script ansible.builtin.template: src: docker-version-guard.sh.j2 dest: /usr/local/bin/pw-docker-version-guard owner: root group: root mode: "0755" # ── 2. Container base image security updates ─────────────────────────────── - name: Deploy container image update script ansible.builtin.template: src: container-security-update.sh.j2 dest: /usr/local/bin/pw-container-security-update owner: root group: root mode: "0755" - name: Deploy container update systemd service ansible.builtin.template: src: pw-container-update.service.j2 dest: /etc/systemd/system/pw-container-update.service owner: root group: root mode: "0644" notify: Reload systemd - name: Deploy container update systemd timer ansible.builtin.template: src: pw-container-update.timer.j2 dest: /etc/systemd/system/pw-container-update.timer owner: root group: root mode: "0644" notify: - Reload systemd - Enable container update timer # ── 3. k3s patch updates ─────────────────────────────────────────────────── - name: Deploy k3s patch update script ansible.builtin.template: src: k3s-security-update.sh.j2 dest: /usr/local/bin/pw-k3s-security-update owner: root group: root mode: "0755" - name: Deploy k3s update systemd service ansible.builtin.template: src: pw-k3s-update.service.j2 dest: /etc/systemd/system/pw-k3s-update.service owner: root group: root mode: "0644" notify: Reload systemd - name: Deploy k3s update systemd timer ansible.builtin.template: src: pw-k3s-update.timer.j2 dest: /etc/systemd/system/pw-k3s-update.timer owner: root group: root mode: "0644" notify: - Reload systemd - Enable k3s update timer # ── 4. Admin alert helper ────────────────────────────────────────────────── - name: Deploy admin alert script ansible.builtin.template: src: pw-security-alert.sh.j2 dest: /usr/local/bin/pw-security-alert owner: root group: root mode: "0755" # ── 5. Ensure needrestart is installed for library/service detection ─────── - name: Install needrestart for detecting outdated services ansible.builtin.apt: name: needrestart state: present - name: Configure needrestart — auto-restart services, never interactive ansible.builtin.copy: content: | # Auto-restart services after library updates (no prompts) $nrconf{restart} = 'a'; # Don't restart these (handled by our own scripts) $nrconf{blacklist_rc} = [qr(^docker), qr(^containerd), qr(^k3s)]; dest: /etc/needrestart/conf.d/pw-security.conf owner: root group: root mode: "0644"