fix(O1): scaffold docker_host role so make lint passes on main
playbooks/site.yml imports the docker_host role, but it didn't exist, so ansible-lint's syntax-check failed on a clean checkout — breaking CLAUDE.md's "main must always work" / "Never skip lint" (top open finding O1 from the 2026-06-11 review). Scaffold docker_host as a proper placeholder via the prescribed mechanism (make new-role): filled meta/main.yml + README, an honest no-task tasks/main.yml documenting planned scope (Docker engine + Compose, daemon hardening, nftables.d container rules per ADR-004/020), and the standard molecule scenario. This preserves site.yml's full-standard-state intent rather than dropping the play. Update STATUS.md (docker_host moves from "Not in git" to "scaffolded, no tasks") and the role/playbook READMEs to match. make lint: 0 failures, 0 warnings; check-tags OK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1da117d65b
commit
03d33f83dd
12 changed files with 118 additions and 9 deletions
|
|
@ -35,14 +35,14 @@ _Last reviewed: 2026-06-11._
|
||||||
| Thing | State |
|
| Thing | State |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `roles/base/` | **Partially built.** The `firewall` concern is implemented (nftables: catalog-driven default-deny + east-west allowlist + auto-rollback apply; ADR-020) with pytest + Molecule render/syntax tests. Other concerns (SSH hardening, fail2ban, auditd, packages, users) are **not** built yet, so `make deploy PLAYBOOK=site` has no real content to apply (the make target itself now works — see "Real and working today"). |
|
| `roles/base/` | **Partially built.** The `firewall` concern is implemented (nftables: catalog-driven default-deny + east-west allowlist + auto-rollback apply; ADR-020) with pytest + Molecule render/syntax tests. Other concerns (SSH hardening, fail2ban, auditd, packages, users) are **not** built yet, so `make deploy PLAYBOOK=site` has no real content to apply (the make target itself now works — see "Real and working today"). |
|
||||||
| `roles/docker_host/` | Not in git. Same. |
|
| `roles/docker_host/` | **Scaffolded, no tasks.** In git (meta/README/molecule filled), wired into `playbooks/site.yml` so the standard state is expressed end-to-end and `make lint` covers it, but it has no tasks yet — applying it is a no-op. Planned scope (Docker engine + Compose, daemon hardening, `nftables.d` container rules) in ADR-004/ADR-020. |
|
||||||
| `inventories/*/hosts.yml` | Structured stubs with empty host maps (`hosts: {}`); regenerated by `make tf-inventory` once Terraform has hosts |
|
| `inventories/*/hosts.yml` | Structured stubs with empty host maps (`hosts: {}`); regenerated by `make tf-inventory` once Terraform has hosts |
|
||||||
| `inventories/production/group_vars/{docker_hosts,proxmox_hosts}/` | Empty dirs |
|
| `inventories/production/group_vars/{docker_hosts,proxmox_hosts}/` | Empty dirs |
|
||||||
|
|
||||||
So `make deploy PLAYBOOK=site` has no real content to apply — `base` is only partially
|
So `make deploy PLAYBOOK=site` has no real content to apply — `base` is only partially
|
||||||
built (its `firewall` concern only) and the `docker_host` role does not exist yet. (The
|
built (its `firewall` concern only) and the `docker_host` role is scaffolded but has no
|
||||||
`make check`/`deploy` machinery itself now works — first proven by applying `dev_env` via
|
tasks yet. (The `make check`/`deploy` machinery itself now works — first proven by
|
||||||
`playbooks/workstation.yml`.)
|
applying `dev_env` via `playbooks/workstation.yml`.)
|
||||||
|
|
||||||
## Designed but not built
|
## Designed but not built
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ Top-level orchestration playbooks. No inline vars — configuration comes from
|
||||||
|
|
||||||
- `site.yml` — full standard state: applies `base` to all hosts and `docker_host`
|
- `site.yml` — full standard state: applies `base` to all hosts and `docker_host`
|
||||||
to docker hosts. **Note:** `base` is only partially built (its `firewall` concern)
|
to docker hosts. **Note:** `base` is only partially built (its `firewall` concern)
|
||||||
and `docker_host` does not exist yet, so this is incomplete — see `STATUS.md`.
|
and `docker_host` is scaffolded with no tasks yet, so this is incomplete — see `STATUS.md`.
|
||||||
- `workstation.yml` — applies the `dev_env` role (interactive developer environment)
|
- `workstation.yml` — applies the `dev_env` role (interactive developer environment)
|
||||||
to the `control` group; built and applied to `ubongo` (see `STATUS.md`).
|
to the `control` group; built and applied to `ubongo` (see `STATUS.md`).
|
||||||
- `bootstrap.yml` — first-run setup for a host that may not have Python yet;
|
- `bootstrap.yml` — first-run setup for a host that may not have Python yet;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
# site.yml — apply full standard state to all hosts
|
# site.yml — apply full standard state to all hosts
|
||||||
# Run via: make deploy PLAYBOOK=site
|
# Run via: make deploy PLAYBOOK=site
|
||||||
# NOTE: `base` is only partially built (its `firewall` concern; see STATUS.md) and the
|
# NOTE: `base` is only partially built (its `firewall` concern; see STATUS.md) and
|
||||||
# `docker_host` role does not exist yet, so this playbook applies base's firewall but is
|
# `docker_host` is scaffolded but has no tasks yet, so this playbook applies base's
|
||||||
# incomplete until `docker_host` is created.
|
# firewall but is otherwise incomplete until those roles gain content.
|
||||||
|
|
||||||
- name: Apply base configuration to all hosts
|
- name: Apply base configuration to all hosts
|
||||||
hosts: all
|
hosts: all
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@ Each role must have: a `molecule/default/` scenario (Debian 13), a populated
|
||||||
|
|
||||||
Current state: `base` is **partially built** — its `firewall` concern (nftables) is
|
Current state: `base` is **partially built** — its `firewall` concern (nftables) is
|
||||||
implemented and tested; the other concerns (SSH hardening, fail2ban, auditd, packages,
|
implemented and tested; the other concerns (SSH hardening, fail2ban, auditd, packages,
|
||||||
users) are not yet built. `docker_host` does **not exist yet**. `dev_env` (interactive
|
users) are not yet built. `docker_host` is **scaffolded but has no tasks yet**. `dev_env` (interactive
|
||||||
developer environment) is built and applied. See `STATUS.md` for the authoritative
|
developer environment) is built and applied. See `STATUS.md` for the authoritative
|
||||||
breakdown.
|
breakdown.
|
||||||
|
|
|
||||||
34
roles/docker_host/README.md
Normal file
34
roles/docker_host/README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# docker_host
|
||||||
|
|
||||||
|
Docker engine + Compose runtime applied to every host in the `docker_hosts` group.
|
||||||
|
Provides the container platform that the per-service roles (one service = one role,
|
||||||
|
ADR-004) deploy their Compose stacks onto.
|
||||||
|
|
||||||
|
> **Status: scaffolded, not yet implemented.** This role has no tasks yet — applying it
|
||||||
|
> is a no-op. It is wired into `playbooks/site.yml` so the full standard state is
|
||||||
|
> expressed end-to-end, and so `make lint` covers it. See `STATUS.md`.
|
||||||
|
|
||||||
|
## Planned scope
|
||||||
|
|
||||||
|
- Install Docker engine + the Compose plugin, version-pinned (ADR-011).
|
||||||
|
- Daemon hardening: `iptables: false` (the host `base` firewall owns nftables, ADR-020),
|
||||||
|
log driver, `live-restore`, user-namespace remapping where practical (ADR-002).
|
||||||
|
- Render container forward/NAT rules into `/etc/nftables.d/*.nft` — the include hook the
|
||||||
|
`base` role's ruleset exposes (see `roles/base/README.md`).
|
||||||
|
- Provide the runtime the service roles deploy their Compose files onto.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
None yet. Placeholders will use the `docker_host__*` namespace (CLAUDE.md convention).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- hosts: docker_hosts
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- role: docker_host
|
||||||
|
tags: [docker_host]
|
||||||
|
```
|
||||||
|
|
||||||
|
See ADR-004 (`docs/decisions/004-docker-model.md`) for the Docker & Compose model.
|
||||||
1
roles/docker_host/defaults/main.yml
Normal file
1
roles/docker_host/defaults/main.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
---
|
||||||
1
roles/docker_host/handlers/main.yml
Normal file
1
roles/docker_host/handlers/main.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
---
|
||||||
11
roles/docker_host/meta/main.yml
Normal file
11
roles/docker_host/meta/main.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: sjat
|
||||||
|
description: Docker engine + Compose runtime for boma docker_hosts (Debian 13).
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.17"
|
||||||
|
platforms:
|
||||||
|
- name: Debian
|
||||||
|
versions:
|
||||||
|
- trixie
|
||||||
|
dependencies: []
|
||||||
7
roles/docker_host/molecule/default/converge.yml
Normal file
7
roles/docker_host/molecule/default/converge.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: docker_host
|
||||||
31
roles/docker_host/molecule/default/molecule.yml
Normal file
31
roles/docker_host/molecule/default/molecule.yml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
options:
|
||||||
|
requirements-file: ../../requirements.yml
|
||||||
|
|
||||||
|
driver:
|
||||||
|
name: docker
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: instance
|
||||||
|
# Project-owned image built from .docker/molecule-debian13/Dockerfile
|
||||||
|
# and hosted in the Forgejo container registry.
|
||||||
|
# Build/push with: make molecule-image / make molecule-image-push
|
||||||
|
image: forgejo.nyumbani.baobab.band/sjat/molecule-debian13:latest
|
||||||
|
pre_build_image: true
|
||||||
|
privileged: true # required for systemd
|
||||||
|
cgroupns_mode: host
|
||||||
|
volumes:
|
||||||
|
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||||
|
command: /lib/systemd/systemd
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
inventory:
|
||||||
|
host_vars:
|
||||||
|
instance:
|
||||||
|
ansible_user: root
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
11
roles/docker_host/molecule/default/verify.yml
Normal file
11
roles/docker_host/molecule/default/verify.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
- name: Verify
|
||||||
|
hosts: all
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Add verification tasks here
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: true
|
||||||
|
msg: "Replace this with real assertions"
|
||||||
|
tags: [verify]
|
||||||
13
roles/docker_host/tasks/main.yml
Normal file
13
roles/docker_host/tasks/main.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
# docker_host — Docker engine + Compose runtime for hosts in the docker_hosts group.
|
||||||
|
#
|
||||||
|
# SCAFFOLDED, NOT YET IMPLEMENTED. This role is referenced by playbooks/site.yml so the
|
||||||
|
# full standard state is expressed end-to-end, but it has no tasks yet — applying it is a
|
||||||
|
# no-op. See STATUS.md ("Scaffolded but empty") and ADR-004 (Docker & Compose model).
|
||||||
|
#
|
||||||
|
# Planned scope (ADR-002/004/020):
|
||||||
|
# - install Docker engine + compose plugin (version-pinned, per ADR-011)
|
||||||
|
# - daemon hardening: iptables:false (host nftables owns the firewall, ADR-020),
|
||||||
|
# log-driver, live-restore, userns where practical
|
||||||
|
# - render container forward/NAT rules into /etc/nftables.d/*.nft (the base-role hook)
|
||||||
|
# - deploy per-service Compose stacks from the service roles (one service = one role)
|
||||||
Loading…
Add table
Reference in a new issue