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:
@@ -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`.
|
||||
Reference in New Issue
Block a user