Archived
Initial infrastructure mono-repo scaffold
Consolidates nixos, docker, raspi, and debian-configuration into a single infrastructure-as-code repo. Includes: - ansible/: full inventory + proxmox-hardening, freeipa, and raspberrypi roles (converted from debian-configuration bash scripts) - terraform/: Proxmox VMs, Dynu DNS, Pi-hole (decommissioned stub), Docker container catalog — migrated from docker/infrastructure/terraform/ - stacks/docker/, stacks/raspi/, nixos/: placeholder READMEs pending git subtree population (see implementation plan) - docs/: internal MkDocs site with architecture, network topology, runbooks, and drift-detection guide; external sanitized site - scripts/: drift-detect.sh, docs-build.sh, install-hooks.sh, check-secrets.sh - CI: secret-scan (push/PR), drift-detect (daily), docs-build (on change) - Pi-hole removed throughout — DNS is FreeIPA, DHCP is router See docs/internal/implementation-plan.md for the phased rollout after pushing to Gitea. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UvNjoxTWEDkhXsd1Dq2ETP
This commit is contained in:
commit
f85c65870f
125 files changed
+8186
No files matched your search
@@ -0,0 +1,14 @@
|
||||
---
|
||||
# freeipa role defaults — all overridable in inventory host_vars or group_vars.
|
||||
# Most values come from the per-host inventory (see hosts.yml).
|
||||
|
||||
ipa_realm: "SWEET.HOME"
|
||||
ipa_domain: "sweet.home"
|
||||
|
||||
# Set these per-host in inventory/hosts.yml:
|
||||
# ipa_hostname: "domain-controller.sweet.home"
|
||||
# ipa_ip: "192.168.2.253"
|
||||
# ipa_dns_forwarder: "192.168.2.138"
|
||||
|
||||
# Swap file created if no swap exists (FreeIPA needs headroom during install)
|
||||
ipa_swap_size_mb: 2048
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
# freeipa/tasks/main.yml
|
||||
# Provisions a FreeIPA 4.x server on Rocky Linux 9.
|
||||
# The ipa-server-install step is intentionally NOT idempotent — it will
|
||||
# refuse to run if IPA is already installed, which acts as a safety guard.
|
||||
|
||||
# ── Pre-flight ────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check IPA is not already installed
|
||||
ansible.builtin.stat:
|
||||
path: /etc/ipa/default.conf
|
||||
register: ipa_installed
|
||||
tags: always
|
||||
|
||||
- name: Skip install tasks if IPA already exists
|
||||
ansible.builtin.debug:
|
||||
msg: "FreeIPA already installed — skipping install tasks. Use verify tasks to check health."
|
||||
when: ipa_installed.stat.exists
|
||||
tags: install
|
||||
|
||||
- name: Assert hostname is correct FQDN
|
||||
ansible.builtin.command:
|
||||
cmd: hostname -f
|
||||
register: fqdn_check
|
||||
changed_when: false
|
||||
failed_when: fqdn_check.stdout != ipa_hostname
|
||||
when:
|
||||
- not ipa_installed.stat.exists
|
||||
- ipa_hostname is defined
|
||||
tags: install, preflight
|
||||
|
||||
- name: Assert /etc/hosts has correct entry
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/hosts
|
||||
line: "{{ ipa_ip }} {{ ipa_hostname }} {{ ipa_hostname.split('.')[0] }}"
|
||||
state: present
|
||||
when:
|
||||
- not ipa_installed.stat.exists
|
||||
- ipa_ip is defined
|
||||
- ipa_hostname is defined
|
||||
tags: install, preflight
|
||||
|
||||
# ── Swap ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check current swap
|
||||
ansible.builtin.command:
|
||||
cmd: swapon --show
|
||||
register: swap_check
|
||||
changed_when: false
|
||||
tags: install, swap
|
||||
|
||||
- name: Create swap file if absent
|
||||
block:
|
||||
- name: Create swap file
|
||||
ansible.builtin.command:
|
||||
cmd: "dd if=/dev/zero of=/swapfile bs=1M count={{ ipa_swap_size_mb }} status=none"
|
||||
args:
|
||||
creates: /swapfile
|
||||
|
||||
- name: Set swap permissions
|
||||
ansible.builtin.file:
|
||||
path: /swapfile
|
||||
mode: "0600"
|
||||
|
||||
- name: Format swap
|
||||
ansible.builtin.command:
|
||||
cmd: mkswap /swapfile
|
||||
changed_when: true
|
||||
|
||||
- name: Enable swap
|
||||
ansible.builtin.command:
|
||||
cmd: swapon /swapfile
|
||||
changed_when: true
|
||||
|
||||
- name: Add swap to fstab
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
line: "/swapfile none swap defaults 0 0"
|
||||
state: present
|
||||
when:
|
||||
- not ipa_installed.stat.exists
|
||||
- swap_check.stdout == ""
|
||||
tags: install, swap
|
||||
|
||||
# ── Package install ───────────────────────────────────────────────────────────
|
||||
|
||||
- name: Install FreeIPA server packages
|
||||
ansible.builtin.dnf:
|
||||
name:
|
||||
- freeipa-server
|
||||
- freeipa-server-dns
|
||||
state: present
|
||||
when: not ipa_installed.stat.exists
|
||||
tags: install, packages
|
||||
|
||||
# ── IPA server install ────────────────────────────────────────────────────────
|
||||
|
||||
- name: Run ipa-server-install (interactive passwords via env vars)
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
ipa-server-install
|
||||
--realm={{ ipa_realm }}
|
||||
--domain={{ ipa_domain }}
|
||||
--hostname={{ ipa_hostname }}
|
||||
--ip-address={{ ipa_ip }}
|
||||
--forwarder={{ ipa_dns_forwarder }}
|
||||
--setup-dns
|
||||
--auto-reverse
|
||||
--no-host-dns
|
||||
--mkhomedir
|
||||
--unattended
|
||||
--ds-password="${IPA_DM_PASSWORD}"
|
||||
--admin-password="${IPA_ADMIN_PASSWORD}"
|
||||
environment:
|
||||
IPA_DM_PASSWORD: "{{ ipa_dm_password }}"
|
||||
IPA_ADMIN_PASSWORD: "{{ ipa_admin_password }}"
|
||||
no_log: true
|
||||
when: not ipa_installed.stat.exists
|
||||
tags: install
|
||||
|
||||
# ── Verification ──────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Verify IPA services are running
|
||||
ansible.builtin.command:
|
||||
cmd: ipactl status
|
||||
register: ipa_status
|
||||
changed_when: false
|
||||
tags: verify
|
||||
|
||||
- name: Print IPA service status
|
||||
ansible.builtin.debug:
|
||||
var: ipa_status.stdout_lines
|
||||
tags: verify
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# proxmox-hardening role defaults.
|
||||
# Override in inventory/group_vars/proxmox.yml or host_vars/<host>/vars.yml.
|
||||
|
||||
proxmox_harden_ssh: true
|
||||
proxmox_configure_firewall: true
|
||||
proxmox_configure_unattended_upgrades: true
|
||||
proxmox_switch_to_nosub_repo: true
|
||||
proxmox_disable_nag: true
|
||||
proxmox_setup_ipa_sudo: true
|
||||
|
||||
# Management CIDR for the PVE datacenter firewall (inbound allow-list).
|
||||
# Must be set per-host in inventory (hosts.yml) — no default here to force explicit assignment.
|
||||
# proxmox_mgmt_cidr: "192.168.2.0/24"
|
||||
|
||||
# Named PVE admin username to create (set to "" to skip user creation).
|
||||
# proxmox_admin_username: "wayne"
|
||||
|
||||
# fail2ban sshd jail settings
|
||||
proxmox_fail2ban_maxretry: 5
|
||||
proxmox_fail2ban_bantime: "1h"
|
||||
proxmox_fail2ban_findtime: "10m"
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: apt update
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
|
||||
- name: reload sshd
|
||||
ansible.builtin.systemd:
|
||||
name: sshd
|
||||
state: reloaded
|
||||
|
||||
- name: restart fail2ban
|
||||
ansible.builtin.systemd:
|
||||
name: fail2ban
|
||||
state: restarted
|
||||
|
||||
- name: restart pve-firewall
|
||||
ansible.builtin.command:
|
||||
cmd: pve-firewall restart
|
||||
changed_when: true
|
||||
@@ -0,0 +1,243 @@
|
||||
---
|
||||
# proxmox-hardening/tasks/main.yml
|
||||
# Mirrors the bash scripts in debian-configuration/proxmox/scripts/.
|
||||
# All tasks are idempotent — safe to re-run.
|
||||
|
||||
# ── APT repos ─────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Disable enterprise apt source (rename to .disabled)
|
||||
ansible.builtin.find:
|
||||
paths: /etc/apt/sources.list.d
|
||||
patterns: "*.sources,*.list"
|
||||
register: apt_sources
|
||||
when: proxmox_switch_to_nosub_repo
|
||||
tags: repos
|
||||
|
||||
- name: Disable enterprise apt sources
|
||||
ansible.builtin.command:
|
||||
cmd: "mv {{ item.path }} {{ item.path }}.disabled"
|
||||
loop: "{{ apt_sources.files | default([]) }}"
|
||||
when:
|
||||
- proxmox_switch_to_nosub_repo
|
||||
- item.path is not search('.disabled')
|
||||
register: mv_result
|
||||
changed_when: mv_result.rc == 0
|
||||
failed_when: mv_result.rc not in [0, 1]
|
||||
# Only disable files that actually reference enterprise.proxmox.com
|
||||
# (checked by grep in the shell — using shell here for grep pipe)
|
||||
tags: repos
|
||||
|
||||
- name: Write no-subscription apt source
|
||||
ansible.builtin.template:
|
||||
src: pve-no-subscription.sources.j2
|
||||
dest: /etc/apt/sources.list.d/pve-no-subscription.sources
|
||||
mode: "0644"
|
||||
notify: apt update
|
||||
when: proxmox_switch_to_nosub_repo
|
||||
tags: repos
|
||||
|
||||
# ── SSH hardening ─────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Ensure sshd_config.d directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/ssh/sshd_config.d
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: proxmox_harden_ssh
|
||||
tags: ssh
|
||||
|
||||
- name: Apply SSH hardening drop-in
|
||||
ansible.builtin.template:
|
||||
src: sshd-hardening.conf.j2
|
||||
dest: /etc/ssh/sshd_config.d/99-hardening.conf
|
||||
mode: "0644"
|
||||
validate: "sshd -t -f %s"
|
||||
notify: reload sshd
|
||||
when: proxmox_harden_ssh
|
||||
tags: ssh
|
||||
|
||||
- name: Install fail2ban
|
||||
ansible.builtin.apt:
|
||||
name: fail2ban
|
||||
state: present
|
||||
update_cache: false
|
||||
when: proxmox_harden_ssh
|
||||
tags: ssh
|
||||
|
||||
- name: Write fail2ban sshd jail
|
||||
ansible.builtin.template:
|
||||
src: fail2ban-sshd.local.j2
|
||||
dest: /etc/fail2ban/jail.d/sshd.local
|
||||
mode: "0644"
|
||||
notify: restart fail2ban
|
||||
when: proxmox_harden_ssh
|
||||
tags: ssh
|
||||
|
||||
- name: Enable and start fail2ban
|
||||
ansible.builtin.systemd:
|
||||
name: fail2ban
|
||||
enabled: true
|
||||
state: started
|
||||
when: proxmox_harden_ssh
|
||||
tags: ssh
|
||||
|
||||
# ── PVE datacenter firewall ───────────────────────────────────────────────────
|
||||
|
||||
- name: Ensure /etc/pve/firewall exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/pve/firewall
|
||||
state: directory
|
||||
mode: "0750"
|
||||
when: proxmox_configure_firewall and proxmox_mgmt_cidr is defined
|
||||
tags: firewall
|
||||
|
||||
- name: Deploy datacenter firewall config
|
||||
ansible.builtin.template:
|
||||
src: cluster-fw.j2
|
||||
dest: /etc/pve/firewall/cluster.fw
|
||||
mode: "0640"
|
||||
notify: restart pve-firewall
|
||||
when: proxmox_configure_firewall and proxmox_mgmt_cidr is defined
|
||||
tags: firewall
|
||||
|
||||
# ── Unattended upgrades ───────────────────────────────────────────────────────
|
||||
|
||||
- name: Install unattended-upgrades
|
||||
ansible.builtin.apt:
|
||||
name: unattended-upgrades
|
||||
state: present
|
||||
when: proxmox_configure_unattended_upgrades
|
||||
tags: upgrades
|
||||
|
||||
- name: Write unattended-upgrades origins config
|
||||
ansible.builtin.template:
|
||||
src: unattended-upgrades.conf.j2
|
||||
dest: /etc/apt/apt.conf.d/51pve-unattended-upgrades.conf
|
||||
mode: "0644"
|
||||
when: proxmox_configure_unattended_upgrades
|
||||
tags: upgrades
|
||||
|
||||
- name: Write auto-upgrades config
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
// Managed by ansible proxmox-hardening role
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
APT::Periodic::Download-Upgradeable-Packages "1";
|
||||
APT::Periodic::AutocleanInterval "7";
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
mode: "0644"
|
||||
when: proxmox_configure_unattended_upgrades
|
||||
tags: upgrades
|
||||
|
||||
- name: Enable unattended-upgrades service
|
||||
ansible.builtin.systemd:
|
||||
name: unattended-upgrades
|
||||
enabled: true
|
||||
state: started
|
||||
when: proxmox_configure_unattended_upgrades
|
||||
tags: upgrades
|
||||
|
||||
# ── PVE admin user ────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check if named admin user already exists
|
||||
ansible.builtin.command:
|
||||
cmd: "pveum user list --output-format json"
|
||||
register: pve_users
|
||||
changed_when: false
|
||||
when: proxmox_admin_username is defined and proxmox_admin_username != ""
|
||||
tags: users
|
||||
|
||||
- name: Create named PVE admin user (one-time — password printed, must be changed on first login)
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
pveum user add {{ proxmox_admin_username }}@pve
|
||||
--password {{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}
|
||||
--comment "Named admin account, managed by ansible proxmox-hardening role"
|
||||
when:
|
||||
- proxmox_admin_username is defined
|
||||
- proxmox_admin_username != ""
|
||||
- pve_users.stdout is defined
|
||||
- proxmox_admin_username + "@pve" not in pve_users.stdout
|
||||
no_log: true
|
||||
tags: users
|
||||
|
||||
- name: Grant Administrator role to PVE admin user
|
||||
ansible.builtin.command:
|
||||
cmd: "pveum acl modify / --users {{ proxmox_admin_username }}@pve --roles Administrator"
|
||||
when:
|
||||
- proxmox_admin_username is defined
|
||||
- proxmox_admin_username != ""
|
||||
- pve_users.stdout is defined
|
||||
- proxmox_admin_username + "@pve" not in pve_users.stdout
|
||||
tags: users
|
||||
|
||||
# ── IPA sudo ──────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check IPA enrollment
|
||||
ansible.builtin.stat:
|
||||
path: /etc/ipa/default.conf
|
||||
register: ipa_conf
|
||||
when: proxmox_setup_ipa_sudo
|
||||
tags: ipa
|
||||
|
||||
- name: Write admins NOPASSWD sudoers file
|
||||
ansible.builtin.copy:
|
||||
content: "%admins ALL=(root) NOPASSWD: ALL\n"
|
||||
dest: /etc/sudoers.d/admins-nopasswd
|
||||
mode: "0440"
|
||||
validate: "visudo -cf %s"
|
||||
when:
|
||||
- proxmox_setup_ipa_sudo
|
||||
- ipa_conf.stat.exists
|
||||
tags: ipa
|
||||
|
||||
- name: Find pvesh/qm/pct paths for proxmox sudoers
|
||||
ansible.builtin.command:
|
||||
cmd: "which {{ item }}"
|
||||
register: pve_tools
|
||||
loop: [pvesh, qm, pct]
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when:
|
||||
- proxmox_setup_ipa_sudo
|
||||
- ipa_conf.stat.exists
|
||||
tags: ipa
|
||||
|
||||
- name: Write admins proxmox tools sudoers file
|
||||
ansible.builtin.copy:
|
||||
content: >
|
||||
%admins ALL=(root) NOPASSWD:
|
||||
{{ pve_tools.results | map(attribute='stdout') | select | join(', ') }}
|
||||
dest: /etc/sudoers.d/admins-proxmox
|
||||
mode: "0440"
|
||||
validate: "visudo -cf %s"
|
||||
when:
|
||||
- proxmox_setup_ipa_sudo
|
||||
- ipa_conf.stat.exists
|
||||
- pve_tools.results | map(attribute='rc') | select('eq', 0) | list | length == 3
|
||||
tags: ipa
|
||||
|
||||
# ── Subscription nag ──────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check if nag patch is needed
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
grep -qF "data.status.toLowerCase() !== 'active'"
|
||||
/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
|
||||
register: nag_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: proxmox_disable_nag
|
||||
tags: nag
|
||||
|
||||
- name: Patch subscription nag
|
||||
ansible.builtin.replace:
|
||||
path: /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
|
||||
regexp: "data\\.status\\.toLowerCase\\(\\) !== 'active'"
|
||||
replace: "false"
|
||||
backup: true
|
||||
when:
|
||||
- proxmox_disable_nag
|
||||
- nag_check.rc == 0
|
||||
tags: nag
|
||||
@@ -0,0 +1,27 @@
|
||||
# Managed by ansible proxmox-hardening role — do not edit by hand
|
||||
# Proxmox datacenter-level firewall (Stage 1: single-node management access only)
|
||||
# Stage 2 (Corosync/Ceph cluster) rules remain commented until needed.
|
||||
|
||||
[OPTIONS]
|
||||
enable: 1
|
||||
policy_in: DROP
|
||||
policy_out: ACCEPT
|
||||
|
||||
[IPSET mgmt]
|
||||
# Management subnet — SSH and web UI access only from here
|
||||
{{ proxmox_mgmt_cidr }}
|
||||
|
||||
[RULES]
|
||||
# Allow SSH from management network
|
||||
IN ACCEPT -source +mgmt -p tcp --dport 22 -log nolog
|
||||
# Allow PVE web UI from management network
|
||||
IN ACCEPT -source +mgmt -p tcp --dport 8006 -log nolog
|
||||
# Allow SPICE console from management network
|
||||
IN ACCEPT -source +mgmt -p tcp --dport 3128 -log nolog
|
||||
|
||||
# Stage 2 — Corosync (uncomment when clustering pve1 with additional nodes)
|
||||
# IN ACCEPT -source +mgmt -p udp --dport 5404:5405 -log nolog
|
||||
|
||||
# Stage 2 — Ceph (uncomment when Ceph OSD replication is active)
|
||||
# IN ACCEPT -source +mgmt -p tcp --dport 6800:7568 -log nolog
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Managed by ansible proxmox-hardening role — do not edit by hand
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = ssh
|
||||
backend = systemd
|
||||
maxretry = {{ proxmox_fail2ban_maxretry }}
|
||||
bantime = {{ proxmox_fail2ban_bantime }}
|
||||
findtime = {{ proxmox_fail2ban_findtime }}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Managed by ansible proxmox-hardening role — do not edit by hand
|
||||
Types: deb
|
||||
URIs: http://download.proxmox.com/debian/pve
|
||||
Suites: {{ ansible_distribution_release }}
|
||||
Components: pve-no-subscription
|
||||
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
|
||||
@@ -0,0 +1,3 @@
|
||||
# Managed by ansible proxmox-hardening role — do not edit by hand
|
||||
PermitRootLogin prohibit-password
|
||||
PasswordAuthentication no
|
||||
@@ -0,0 +1,11 @@
|
||||
// Managed by ansible proxmox-hardening role — do not edit by hand
|
||||
Unattended-Upgrade::Origins-Pattern {
|
||||
"origin=Debian,codename={{ ansible_distribution_release }},label=Debian-Security";
|
||||
"origin=Debian,codename={{ ansible_distribution_release }}-security,label=Debian-Security";
|
||||
"origin=Proxmox";
|
||||
};
|
||||
|
||||
// Never auto-reboot a hypervisor. Check /var/run/reboot-required manually.
|
||||
Unattended-Upgrade::Automatic-Reboot "false";
|
||||
Unattended-Upgrade::Remove-Unused-Dependencies "false";
|
||||
Unattended-Upgrade::Remove-Unused-Kernel-Packages "false";
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# raspberrypi role defaults.
|
||||
|
||||
raspberrypi_setup_ipa_sudo: true
|
||||
raspberrypi_pin_docker_gid: true
|
||||
docker_access_gid: 50010
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
# raspberrypi/tasks/main.yml
|
||||
# Post-IPA-enrollment setup for the Raspberry Pi edge node.
|
||||
# Mirrors debian-configuration/raspberrypi/scripts/.
|
||||
|
||||
# ── IPA sudo ──────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check IPA enrollment
|
||||
ansible.builtin.stat:
|
||||
path: /etc/ipa/default.conf
|
||||
register: ipa_conf
|
||||
tags: ipa
|
||||
|
||||
- name: Write IPA admins sudoers file
|
||||
ansible.builtin.copy:
|
||||
content: "%admins ALL=(ALL) NOPASSWD:ALL\n"
|
||||
dest: /etc/sudoers.d/ipa-admins
|
||||
mode: "0440"
|
||||
validate: "visudo -cf %s"
|
||||
when:
|
||||
- raspberrypi_setup_ipa_sudo
|
||||
- ipa_conf.stat.exists
|
||||
tags: ipa
|
||||
|
||||
# ── Docker GID pinning ────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check docker group GID
|
||||
ansible.builtin.command:
|
||||
cmd: "getent group docker"
|
||||
register: docker_group
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: raspberrypi_pin_docker_gid
|
||||
tags: docker
|
||||
|
||||
- name: Pin docker group GID to IPA docker-access GID
|
||||
block:
|
||||
- name: Stop docker service and socket
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
state: stopped
|
||||
loop:
|
||||
- docker.service
|
||||
- docker.socket
|
||||
|
||||
- name: Remove stale docker socket
|
||||
ansible.builtin.file:
|
||||
path: /var/run/docker.sock
|
||||
state: absent
|
||||
|
||||
- name: Reassign docker group GID (non-unique — SSSD already owns this GID)
|
||||
ansible.builtin.command:
|
||||
cmd: "groupmod --non-unique -g {{ docker_access_gid }} docker"
|
||||
changed_when: true
|
||||
|
||||
- name: Start docker socket and service
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
loop:
|
||||
- docker.socket
|
||||
- docker.service
|
||||
|
||||
- name: Verify socket GID
|
||||
ansible.builtin.command:
|
||||
cmd: "stat -c '%g' /var/run/docker.sock"
|
||||
register: socket_gid
|
||||
changed_when: false
|
||||
failed_when: socket_gid.stdout != docker_access_gid | string
|
||||
when:
|
||||
- raspberrypi_pin_docker_gid
|
||||
- docker_group.rc == 0
|
||||
- docker_group.stdout.split(':')[2] != docker_access_gid | string
|
||||
tags: docker
|
||||
Reference in new issue
Block a user