diff --git a/.gitea/workflows/lint.yml b/.gitea/workflows/lint.yml index e43b2be..72eb610 100644 --- a/.gitea/workflows/lint.yml +++ b/.gitea/workflows/lint.yml @@ -12,10 +12,8 @@ on: pull_request: env: - # ansible-lint and ansible-core install as SEPARATE uv tools, each with its own - # venv. Collections installed under the ansible-core tool are invisible to - # ansible-lint, which then reports every module as `syntax-check[unknown-module]` - # — a false failure that looks exactly like a real one. Pin both to a shared path. + # ansible-lint and ansible-core install as separate uv tools. Install Galaxy + # collections into this shared path so both isolated environments can see them. ANSIBLE_COLLECTIONS_PATH: /root/.ansible/collections jobs: @@ -66,7 +64,10 @@ jobs: # with "No module named 'winrm'" (CLAUDE.md documents this trap). run: | for i in 1 2 3 4 5; do - uv tool install ansible-core --with ansible --with paramiko --with pywinrm --quiet && break + # Do not add the `ansible` meta-package here: it bundles collections + # inside this uv venv, making Galaxy skip the shared path below while + # ansible-lint's separate venv still cannot resolve the modules. + uv tool install ansible-core --with paramiko --with pywinrm --quiet && break echo "attempt $i failed"; sleep 10 done for i in 1 2 3 4 5; do diff --git a/CHANGELOG.md b/CHANGELOG.md index c1293ad..5c6886c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ What changed in this homelab, when, and why. Newest first. | secrets | Recorded that ESO 2.8.0, five ExternalSecrets and the scoped OpenBao Kubernetes-auth path already exist; the next gate is live recovery testing and migration of any remaining manual Secrets | | Terraform | Recorded Gitea 1.27 State Registry as the preferred candidate for local roots after version and recovery testing; the OCI recovery root remains in OCI Object Storage to avoid a home-control-plane dependency loop | | cleanup | Removed the retired NapCat tree, the Contour and Kanidm archive trees, and seven generated Terraform plan files before establishing the clean Git baseline; plans may embed complete state and remain globally ignored | -| CI | Added a review-first Gitea Actions runner bootstrap: official actions chart 0.1.1, pinned runner 2.3.0, one persistent instance-scoped Kubernetes runner with capacity four, plus an ESO reference to its registration token in OpenBao. The first deployment proved that rootlesskit is blocked by the node's AppArmor unprivileged-userns policy; because the chart requires privileged DinD in either mode, the reviewed fix uses regular DinD instead of weakening the host-wide policy. The runner image intentionally carries neither `uv` nor Terraform: Terraform uses its versioned setup action, while `uv` is pinned and installed from official PyPI because the nested job network reaches PyPI but times out against the GitHub API queried by `setup-uv` | +| CI | Added a review-first Gitea Actions runner bootstrap: official actions chart 0.1.1, pinned runner 2.3.0, one persistent instance-scoped Kubernetes runner with capacity four, plus an ESO reference to its registration token in OpenBao. The first deployment proved that rootlesskit is blocked by the node's AppArmor unprivileged-userns policy; because the chart requires privileged DinD in either mode, the reviewed fix uses regular DinD instead of weakening the host-wide policy. The runner image intentionally carries neither `uv` nor Terraform: Terraform uses its versioned setup action, while `uv` is pinned and installed from official PyPI because the nested job network reaches PyPI but times out against the GitHub API queried by `setup-uv`. Ansible installs only `ansible-core` in its tool venv and puts declared Galaxy collections in a shared path visible to ansible-lint; installing the `ansible` meta-package had made Galaxy falsely skip that shared installation | | identity | Declared the Samba AD `gitea-admins` group with `panxiao81` as its initial member. Gitea already maps this OIDC group to site administrators; the local `gitea_admin` account remains as break-glass access | `Carried forward`: re-verify OpenBao/ESO recovery and remaining Secret inventory; diff --git a/infrastructure/proxmox/ansible/roles/pve_auth/tasks/main.yml b/infrastructure/proxmox/ansible/roles/pve_auth/tasks/main.yml index 7c32af5..cebf397 100644 --- a/infrastructure/proxmox/ansible/roles/pve_auth/tasks/main.yml +++ b/infrastructure/proxmox/ansible/roles/pve_auth/tasks/main.yml @@ -56,7 +56,7 @@ # --check-connection makes PVE actually bind before saving, so a wrong DN, # password, or an untrusted certificate fails HERE instead of silently # producing a realm nobody can log in to. - ansible.builtin.shell: + ansible.builtin.shell: # noqa command-instead-of-shell cmd: >- pveum realm add {{ pve_auth_realm }} --type ad {{ _realm_opts }} --password '{{ pve_auth_bind_password }}' @@ -95,7 +95,7 @@ run_once: true - name: Update the realm - ansible.builtin.shell: + ansible.builtin.shell: # noqa command-instead-of-shell cmd: >- pveum realm modify {{ pve_auth_realm }} {{ _realm_opts }} --password '{{ pve_auth_bind_password }}' diff --git a/infrastructure/proxmox/ansible/roles/pve_linstor/tasks/storage.yml b/infrastructure/proxmox/ansible/roles/pve_linstor/tasks/storage.yml index 17fe7c7..76f0d3d 100644 --- a/infrastructure/proxmox/ansible/roles/pve_linstor/tasks/storage.yml +++ b/infrastructure/proxmox/ansible/roles/pve_linstor/tasks/storage.yml @@ -37,7 +37,7 @@ - name: Refuse to proceed unless that really is a whole disk # Last line of defence: sgdisk against a partition is destructive, so verify # the derived device is TYPE=disk and not a partition before touching it. - ansible.builtin.shell: + ansible.builtin.command: cmd: "lsblk -dno TYPE {{ _ssd_disk.stdout | trim }}" register: _ssd_type changed_when: false @@ -101,7 +101,7 @@ # Same guard as the SSD path. wipefs/vgcreate against a partition by mistake is # how the pve VG on pve2/pve3 got destroyed on 2026-07-25; assert the device # type rather than trusting the variable. - ansible.builtin.shell: + ansible.builtin.command: cmd: "lsblk -dno TYPE {{ pve_linstor_hdd_disk }}" register: _hdd_type changed_when: false diff --git a/infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/legacy.yml b/infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/legacy.yml index e253b9b..34f3ad9 100644 --- a/infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/legacy.yml +++ b/infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/legacy.yml @@ -6,7 +6,7 @@ - name: Inject legacy protocol settings into smb.conf [global] ansible.builtin.blockinfile: path: /etc/samba/smb.conf - marker: "\t# {mark} ANSIBLE MANAGED — legacy clients (INSECURE)" + marker: "\t# {mark} ANSIBLE MANAGED — legacy clients (INSECURE)" # noqa no-tabs insertafter: '^\[global\]' block: |2 server min protocol = NT1