- replace inventory/dmc12.yml with cloudlorean.yml (+ group_vars) and update
all README/AGENTS call examples and the inventory table
- move admin_password hash into encrypted vault.yml; remove plaintext copies
from roles/bootstrap/defaults and group_vars/external.yml
- bootstrap.yml loads vault.yml via vars_files (same pattern as monitoring)
- monitoring: PSK config/registration updates, docker role defaults,
os-updates logging/reboot refinements, ansible.cfg/execute.sh tweaks
- add .project-wiki knowledge base and .github agent instructions
Root configuration (ansible.cfg, execute.sh), Docker runtime
(docker/), all inventories and group_vars, all 6 playbooks plus
bootstrap.yml, and all 7 roles (tasks/, defaults/, templates/,
handlers/). Git history inspected for inventory renames. Vault-encrypted
files (vault.yml) were not decrypted.
Confirmed Findings
Project Shape
Central Ansible collection for provisioning, hardening, updating, and
monitoring Debian hosts; 7 roles, 1 top-level playbook (bootstrap.yml)
and 5 playbooks under playbooks/.
Execution environment: Docker image ansible:deb13 built from
debian:trixie-slim with ansible-core~=2.20.6; collections pinned in
docker/requirements.yml (ansible.posix 2.2.0, community.general
13.0.1, community.docker 5.2.0, community.zabbix 4.2.0).
execute.sh creates an IPv6-enabled bridge network ansible-dualstack,
starts an interactive container with the repo mounted at /ansible and an
ansible_ssh_keys volume at /root/.ssh, injects SSH client config with
host-key checking disabled, then attaches.
ansible.cfg: host_key_checking = False, roles_path = ./roles,
forks = 20, gathering = smart, internal_poll_interval = 0.001,
SSH pipelining and ControlPersist=60s, known hosts set to /dev/null.
Playbooks
All playbooks run hosts: all, user: admin, become: true, and start
with a Debian os_family guard that fails non-Debian hosts.
Exception: playbooks/hardening/manage-ssh-keys.yml has no Debian
guard, no become, and no vars_files; it binds the manage-ssh-keys
role directly.
playbooks/monitoring.yml loads ../vault.yml via a playbook-relative
path; other playbooks do not load vault.yml explicitly.
playbooks/os-updates-deb.yml chains os-updates then healthcheck
(post-update quality gate).
Roles
bootstrap: subtasks for basic packages, admin user (+sudo, authorized
keys), MOTD, keyboard layout, OpenSSH install/config/keys, bashrc, sysctl;
then composes the docker role (skippable via skip_docker) and the
monitoring role (skippable via skip_monitoring). Tags: motd, ssh,
bashrc, sysctl.
docker: official Docker apt repository + docker-ce, CLI,
containerd.io, buildx and compose plugins; template
sources.list.j2; codename derived from facts.
os-updates: optional mirror rewrite (os_also_update_mirror, deb822 +
legacy templates, codename whitelist trixie|bookworm|bullseye), full apt
upgrade, kernel-comparison reboot decision with async reboot +
wait_for_connection (600s timeout), reboot deferred on hosts in the
proxmox group unless os_update_reboot_on_proxmox is true, LXC hosts
skip kernel/reboot logic; preflight/postflight logging delegated to the
controller (logs/<inventory>/<hostname>/update.log).
healthcheck: compares docker ps -a vs running containers, writes a
quality_gate section into the same update log, fails the play when
healthcheck_fail_on_unhealthy is true (default false).
monitoring: Zabbix 7.0 release package from repo.zabbix.com,
zabbix-agent2, Docker plugin config when socket exists, per-host PSK
generated on the controller (persisted in .zabbix-psk/<hostname>.psk,
mode 0700, openssl rand -hex 32), deployed to /etc/zabbix/ zabbix_agent2.psk (0600), TLS connect/accept = PSK, and API host
registration via community.zabbix.zabbix_host over httpapi with
template union including Docker by Zabbix agent 2 when the Docker socket
is present.
hawser: requires existing Docker host + compose file at
/opt/hawser/docker-compose.yml, re-renders it from template, then
docker_compose_v2 with pull: always.
manage-ssh-keys: ensures ~/.ssh (0700), adds good_keys, removes
bad_keys from the admin user's authorized keys.
Inventories And Variables
inventory/cloudlorean.yml (untracked): site with groups debian (13
hosts, 192.168.212.0/24) and proxmox (dmc12 192.168.212.10,
pbs 192.168.212.11); per-host ssh_service_name: ssh on gitea and
ipam.
inventory/home.yml: site home, 6 Debian hosts + tardis (Proxmox),
10.13.37.0/24.
inventory/external.yml: 4 IPv6-only Debian hosts.
inventory/dmc12.yml is deleted in the working tree but not committed
(git status: D); inventory/cloudlorean.yml and
inventory/group_vars/cloudlorean.yml are untracked. Git history confirms
dmc12.yml was added in d2e8ce4 and never tracked as renamed.
group_vars per site override Zabbix servers, API URL
(https://mon.cloudlorean.de/api_jsonrpc.php), proxy
(gatekeeper.cloudlorean.de / gatekeeper.meyer-kempen.de), host groups
and templates. group_vars/debian.yml hardcodes
os_update_version_codename: "trixie" (AGENTS.md warns about this).
admin_authorized_keys and the SHA-512 admin_password hash appear in
plaintext in roles/bootstrap/defaults/main.yml and
inventory/group_vars/external.yml (see ALERT-20260909-001).
vault.yml is tracked but encrypted; .vault_pass, setenv.sh,
.zabbix-psk/, logs/ are git-ignored (verified via git check-ignore).
Inferred Findings
The environment formerly called dmc12 was renamed to cloudlorean;
host dmc12 is now a Proxmox node within the cloudlorean site
(confidence: inferred from logs/.zabbix-psk paths and git status).
Operators appear to be "Niklas" and "Dennis" (SSH key comments in
bootstrap defaults). Formal ownership not documented.
All sites share one Zabbix server (mon.cloudlorean.de) with optional
per-site proxies (confidence: inferred from group_vars).
Home site is referred to as "Meyer-Kempen" in Zabbix host groups/proxy
name (confidence: inferred).
Unknowns
Whether vault.yml also defines admin_password (overriding the
committed defaults hash) - vault not decrypted.
Whether monitoring_zabbix_passive_servers in
inventory/group_vars/external.yml (2a01:4f8:1c1e:62dd::1, the
healthcheck host's own address) is intentional (Zabbix server/proxy on
that host) or a misconfiguration.
Which Docker template name exists on the Zabbix server: role default
Docker by Zabbix agent2 vs group_vars Docker by Zabbix agent 2.
Formal stakeholders and success criteria beyond the healthcheck gate.
Important Paths
bootstrap.yml, playbooks/*.yml - entrypoints
roles/bootstrap/, roles/docker/, roles/monitoring/,
roles/os-updates/, roles/healthcheck/, roles/hawser/,
roles/manage-ssh-keys/ - role implementations