rename dmc12 inventory to cloudlorean and vault admin_password

- 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
This commit is contained in:
DerLinkman
2026-09-09 14:14:18 +02:00
parent a31751af1d
commit 30f3e9a4c6
96 changed files with 3602 additions and 138 deletions
@@ -0,0 +1,65 @@
---
id: MOD-001
type: module
status: active
title: Bootstrap Role
created: 2026-09-09
updated: 2026-09-09
tags: [module, bootstrap, ansible]
related: [MOD-002, MOD-003, REQ-001]
source_paths:
- roles/bootstrap/
confidence: confirmed
---
# Bootstrap Role
## Responsibility
Full initial setup of a Debian host: packages, admin user, SSH, MOTD,
keyboard layout, bashrc, sysctl; then composes Docker and monitoring.
## Source Paths
- `roles/bootstrap/tasks/main.yml` - orchestration only
- Subtasks: `install-basicpackages.yml`, `create-admin-user.yml`,
`set-motd.yml`, `set-keyboardlayout.yml`, `install-openssh.yml`,
`configure-ssh.yml`, `add-ssh-keys.yml`, `setup-bashrc.yml`,
`configure-sysctl.yml`
- Templates: `authorized_keys.j2`, `keyboard.j2`, `sshd.conf.j2`,
`sudoers-admin.j2`
## Public Interfaces
- Playbook: `bootstrap.yml` (top level, Debian guard, `become`, `user: admin`,
`vars_files: vault.yml`)
- Skip flags: `skip_docker`, `skip_monitoring` (control role composition)
- Tags: `motd`, `ssh`, `bashrc`, `sysctl`
## Important Flows
1. Basic packages → admin user (+sudo via `sudoers-admin.j2`, authorized
keys via `authorized_keys.j2`) → MOTD → keyboard layout.
2. OpenSSH install, hardening config (`sshd.conf.j2`), authorized keys.
3. bashrc, sysctl.
4. `import_role: docker` (when `not skip_docker`), then
`import_role: monitoring` (when `not skip_monitoring`).
## Dependencies
- Composed roles: [docker](./MOD-002-docker-role.md),
[monitoring](./MOD-003-monitoring-role.md).
- `admin_authorized_keys` (public keys, plaintext OK) from
`defaults/main.yml`; `admin_password` (SHA-512 hash) lives encrypted in
`vault.yml`, loaded via `vars_files` in `bootstrap.yml` (resolved
ALERT-20260909-001).
## Tests
- None automated; manual runs via `./execute.sh`.
## Notes For Agents
- `sshd` service name differs per host (`ssh_service_name`, set for `gitea`
and `ipam` in `inventory/cloudlorean.yml`).
- Keep `tasks/main.yml` as pure import list when extending.
@@ -0,0 +1,52 @@
---
id: MOD-002
type: module
status: active
title: Docker Role
created: 2026-09-09
updated: 2026-09-09
tags: [module, docker, ansible]
related: [MOD-001, MOD-006, REQ-002]
source_paths:
- roles/docker/
confidence: confirmed
---
# Docker Role
## Responsibility
Install Docker Engine from the official Docker apt repository.
## Source Paths
- `roles/docker/tasks/main.yml` → `install-docker.yml`
- Template: `roles/docker/templates/sources.list.j2`
- Handlers: `roles/docker/handlers/main.yml`
## Public Interfaces
- Playbook: `playbooks/docker.yml`
- Defaults: `docker_mirror` (download.docker.com/linux/debian),
`os_version_codename` (derived from `ansible_facts['distribution_release']`),
`docker_packages` (docker-ce, docker-ce-cli, containerd.io, buildx and
compose plugins).
## Important Flows
1. Set up the official Docker apt repository (key + `sources.list.j2`).
2. Install `docker_packages` (handlers restart the service when needed).
## Dependencies
- Used standalone (`playbooks/docker.yml`) and composed by
[bootstrap](./MOD-001-bootstrap-role.md). Prerequisite for
[hawser](./MOD-006-hawser-role.md).
## Tests
- None automated.
## Notes For Agents
- Codename comes from host facts; no LXC-specific handling observed.
@@ -0,0 +1,77 @@
---
id: MOD-003
type: module
status: active
title: Monitoring Role (Zabbix Agent 2)
created: 2026-09-09
updated: 2026-09-09
tags: [module, monitoring, zabbix, ansible]
related: [MOD-001, TECH-INTEGRATIONS-ZABBIX, REQ-003, NFR-002]
source_paths:
- roles/monitoring/
confidence: confirmed
---
# Monitoring Role (Zabbix Agent 2)
## Responsibility
Install Zabbix Agent 2, configure TLS-PSK and the Docker plugin, and
register/update the host on the Zabbix server via the API.
## Source Paths
- `roles/monitoring/tasks/main.yml` → `validate.yml`,
`install-repository.yml`, `install-agent.yml`, `configure-docker.yml`,
`configure-psk.yml`, `configure-agent.yml`, `register-host.yml`
- Templates: `zabbix_agent2.conf.j2`, `docker.conf.j2`
## Public Interfaces
- Playbook: `playbooks/monitoring.yml` (loads `../vault.yml`)
- Tag: `monitoring`
- Key variables (`defaults/main.yml`, overridden per site in
`inventory/group_vars/<site>.yml`): `monitoring_zabbix_version` (7.0),
`monitoring_zabbix_passive_servers`, `monitoring_zabbix_active_servers`,
`monitoring_zabbix_api_url`, `monitoring_zabbix_api_user`,
`monitoring_zabbix_api_password` (vault), `monitoring_zabbix_register_host`,
`monitoring_zabbix_proxy` / `monitoring_zabbix_proxy_address`,
`monitoring_zabbix_host_groups`, `monitoring_zabbix_templates`,
`monitoring_zabbix_docker_templates`, PSK settings
(`monitoring_zabbix_psk_bits: 256`,
`monitoring_zabbix_psk_store: {{ role_path }}/../../.zabbix-psk`).
## Important Flows
1. Validate inputs → add repo.zabbix.com repo → install `zabbix-agent2`.
2. Docker plugin config when `/var/run/docker.sock` exists.
3. PSK: generate once on the controller (`openssl rand -hex 32`, umask 077,
`creates:` guard), persist under `.zabbix-psk/<hostname>.psk` (0700),
validate hex format/length, deploy to `/etc/zabbix/zabbix_agent2.psk`
(0600), notify restart handler.
4. Agent config: TLS connect/accept = PSK, identity =
`monitoring_zabbix_host_name`, passive/active servers, listen port 10050.
5. Registration: `community.zabbix.zabbix_host` over httpapi (connection
params derived from `monitoring_zabbix_api_url` via `urlsplit`), agent
interface from `ansible_host`, template union adds
`monitoring_zabbix_docker_templates` when the Docker socket is present,
`monitored_by` switches to proxy when `monitoring_zabbix_proxy` is set.
## Dependencies
- `community.zabbix` collection; vault variable
`monitoring_zabbix_api_password`.
- Composed by [bootstrap](./MOD-001-bootstrap-role.md) unless
`skip_monitoring`.
## Tests
- None automated.
## Notes For Agents
- PSK store is controller-side state; never commit it (git-ignored). When
renaming a host, migrate/regenerate the PSK, otherwise registration
drifts (documented in AGENTS.md).
- Template name mismatch between role default (`Docker by Zabbix agent2`)
and group_vars (`Docker by Zabbix agent 2`) - see open question OQ-005.
@@ -0,0 +1,73 @@
---
id: MOD-004
type: module
status: active
title: OS Updates Role
created: 2026-09-09
updated: 2026-09-09
tags: [module, os-updates, ansible]
related: [MOD-005, NFR-003, NFR-006, REQ-004]
source_paths:
- roles/os-updates/
confidence: confirmed
---
# OS Updates Role
## Responsibility
Upgrade Debian packages with optional mirror rewrite, kernel-based reboot
handling, and controller-side update logging.
## Source Paths
- `roles/os-updates/tasks/main.yml` → `update_mirrors.yml` (optional),
`upgrade_packages.yml` → `logging_preflight.yml`, `reboot.yml`,
`logging_postflight.yml`
- Templates: `sources.list.j2`, `sources.list-deb822.j2`
- Handlers: apt cleanup, apt autoremove
## Public Interfaces
- Playbook: `playbooks/os-updates-deb.yml` (chains
[healthcheck](./MOD-005-healthcheck-role.md))
- Key variables: `os_update_auto_upgrade`, `os_also_update_mirror` (false),
`os_update_mirrors` (main + security mirror),
`os_update_version_codename` (role default: host facts;
`group_vars/debian.yml` hardcodes `trixie`),
`os_update_debian_codenames` (trixie, bookworm, bullseye),
`os_update_reboot_on_proxmox` (false),
`os_update_logging_enabled` (true), `os_update_log_dir` (/ansible/logs),
`os_update_log_file` (logs/<inventory>/<hostname>/update.log).
## Important Flows
1. Mirror rewrite (only when `os_also_update_mirror`) with
`ignore_errors: true`; only whitelisted Debian codenames are rewritten in
`sources.list.d`.
2. Preflight logging: refresh cache, record start epoch/ISO, parse
`apt list --upgradable` into names/versions/count.
3. `apt upgrade: full` (notifies cleanup/autoremove handlers).
4. Reboot decision: compare running kernel (`uname -r`) vs newest installed
`linux-image-*`; skipped on LXC (`virtualization_type != lxc`). On
`proxmox` group hosts the reboot is deferred unless
`os_update_reboot_on_proxmox`. Otherwise: async `/sbin/reboot`,
`wait_for_connection` (10s delay, 600s timeout), downtime and kernel
after reboot recorded.
5. Postflight logging: duration, upgrade result, reboot details, kernel
before/after appended to the update log (`delegate_to: localhost`).
## Dependencies
- None (ansible.builtin only). Paired with healthcheck at playbook level.
## Tests
- None automated.
## Notes For Agents
- Logging facts are shared with the healthcheck role via the same log file
and start timestamp conventions.
- Old-style module names (apt, file, blockinfile) remain here; use FQCN for
new tasks.
@@ -0,0 +1,59 @@
---
id: MOD-005
type: module
status: active
title: Healthcheck Role
created: 2026-09-09
updated: 2026-09-09
tags: [module, healthcheck, docker, ansible]
related: [MOD-004, REQ-004, NFR-003]
source_paths:
- roles/healthcheck/
confidence: confirmed
---
# Healthcheck Role
## Responsibility
Post-update quality gate: verify that every Docker container on the host is
running and record the result in the update log.
## Source Paths
- `roles/healthcheck/tasks/main.yml` (single file, no subtasks)
- `roles/healthcheck/defaults/main.yml`
## Public Interfaces
- Playbook: `playbooks/os-updates-deb.yml` (runs after os-updates)
- Key variables: `healthcheck_fail_on_unhealthy` (default false),
`healthcheck_logging_enabled` (derives from `os_update_logging_enabled`),
`healthcheck_log_file` (reuses os-updates log path conventions).
## Important Flows
1. Detect Docker binary (`which docker`, tolerant).
2. If Docker present: list all container names and running container names
(`docker ps -a` / `docker ps --filter status=running`), compute
non-running set.
3. If Docker absent: neutral result (0 containers, passed).
4. Append a `quality_gate:` section (docker_installed, total/running counts,
non-running list, healthcheck_passed) to
`logs/<inventory>/<hostname>/update.log` via `blockinfile` delegated to
localhost.
5. Fail the play when `healthcheck_fail_on_unhealthy` is true and any
container is not running.
## Dependencies
- Shares log file conventions with [os-updates](./MOD-004-os-updates-role.md).
## Tests
- None automated.
## Notes For Agents
- The gate does not fail by default; set `healthcheck_fail_on_unhealthy`
to make failures visible in CI-like runs.
@@ -0,0 +1,57 @@
---
id: MOD-006
type: module
status: active
title: Hawser Role
created: 2026-09-09
updated: 2026-09-09
tags: [module, hawser, docker, ansible]
related: [MOD-002, REQ-005]
source_paths:
- roles/hawser/
confidence: confirmed
---
# Hawser Role
## Responsibility
Update the Hawser Docker Compose stack on a host that already runs Docker.
## Source Paths
- `roles/hawser/tasks/main.yml` → `update-stack.yml`
- Template: `roles/hawser/templates/docker-compose.yml.j2`
- Handlers: `roles/hawser/handlers/main.yml`
## Public Interfaces
- Playbook: `playbooks/upgrade-hawser.yml`
- Key variables: `hawser_project_name` (hawser),
`hawser_compose_dir` (/opt/hawser), `hawser_port` (2376),
`hawser_stacks_volume` (hawser_stacks),
`hawser_allow_insecure_no_auth` (true - documented as requiring an
otherwise secured network).
## Important Flows
1. Gather Docker host info (`community.docker.docker_host_info`,
`ignore_errors: true`).
2. Require existing compose file at `<hawser_compose_dir>/docker-compose.yml`;
re-render it from the template.
3. `community.docker.docker_compose_v2` with `state: present`,
`pull: always` to pull latest images and recreate the stack.
## Dependencies
- Requires Docker on the target (role skips gracefully when Docker is not
reachable). Collection: `community.docker`.
## Tests
- None automated.
## Notes For Agents
- `hawser_allow_insecure_no_auth: true` allows token-less standard mode on
non-loopback addresses; treat as a deliberate, documented trade-off.
@@ -0,0 +1,58 @@
---
id: MOD-007
type: module
status: active
title: Manage SSH Keys Role
created: 2026-09-09
updated: 2026-09-09
tags: [module, ssh, hardening, ansible]
related: [REQ-006, ALERT-20260909-001]
source_paths:
- roles/manage-ssh-keys/
confidence: confirmed
---
# Manage SSH Keys Role
## Responsibility
Harden SSH access by enforcing an allow list (`good_keys`) and removing
deny-listed keys (`bad_keys`) from the target user's authorized keys.
## Source Paths
- `roles/manage-ssh-keys/tasks/main.yml` → `validate-authorized-keys.yml`,
`add-goodkeys.yml`, `remove-badkeys.yml`
- Handlers: `roles/manage-ssh-keys/handlers/main.yml`
## Public Interfaces
- Playbook: `playbooks/hardening/manage-ssh-keys.yml`
(binds the role directly; **no Debian guard, no `become`**)
- Key variables: `ssh_user` (admin), `good_keys` (allow list),
`bad_keys` (deny list; supports env-provided JSON overrides via commented
vars in the playbook).
- Conditional execution: `good_keys.defined and good_keys | length > 0`
(same for `bad_keys`).
## Important Flows
1. Validate/ensure `~/.ssh` of the logged-in user (0700).
2. Add `good_keys` to authorized keys.
3. Remove `bad_keys` from authorized keys.
## Dependencies
- None (ansible.builtin).
## Tests
- None automated.
## Notes For Agents
- The playbook deviates from the documented convention (Debian guard,
`become: true`); treat as an intentional gap to confirm before adding
more hardening playbooks.
- Keys in `defaults/main.yml` are public keys (not secrets); the same allow
list also exists in `roles/bootstrap/defaults/main.yml`.