make install ships only the docker CLI, not the engine, so the manual
`dockerd` start in 01_bootstrap failed with `dockerd: not found`. The
deploy installs + starts the engine itself via sys-svc-container
(DinD-aware), so bootstrap now just boots nodes + make install.
make install now succeeds; the inner dockerd would not come up. Start it with --storage-driver=vfs (nested-friendly) and dump /tmp/dockerd.log on failure so the real cause is visible in CI.
Raw debian/manjaro/centos base images have no make/git/python, so 'make install' failed with 'make: not found'. Install per-distro prerequisites first (apt/pacman/dnf).
Wrap make install / inventory provision / deploy dedicated in timeouts with stdin from /dev/null and non-interactive env, and cap the connectivity check at 180s. A stuck step now fails the harness fast instead of hanging the CI job.
Replaces the linuxserver-image harness with a deploy-driven one: 01_bootstrap (6 empty containers + make install + DinD), 02_registration (per-host dedicated inventory via 'inventory provision' + full-mesh wg0.conf), 03_handshake ('deploy dedicated --id svc-net-wireguard' per host + all-pairs check). Adds the role's inventory-driven config path (mounts a per-host wg0.conf). NAT-flavor coverage follows once the mesh is green.
Replaces mode+nat with a flavor list [server|client|nat]; declares the WireGuard internal subnet in group_vars/all/08_networks.yml; makes the masquerade task idempotent and applied on the deployed host (drops the DOCKER_IN_CONTAINER gate); bumps svc-net-wireguard and test-e2e-cli to lifecycle beta. (Revision 2 of req 026, PR #323 review.)
Adds the infinito-nexus/core#323 cross-link and records nat.sh as proven in the fork CI run. The PR-cross-link AC stays open as the merge-time close-out (a fully-checked requirement is archive-ready per the completeness lint).
Pinning the gateway to 10.30.30.1 collided with the docker-reserved subnet gateway address (Address already in use). The source-based masquerade does not need a fixed IP, so let docker assign it.
Client mode (MTU 1400) and the NAT masquerade rules are now covered by the nat.sh e2e stage. Documents how NAT is tested and that the host-level task stays container-gated. Awaiting fork-CI confirmation of nat.sh.
nat.sh brings up a WireGuard client (MTU 1400) behind a masquerading gateway and verifies it reaches an upstream host only via the masquerade, plus rule present/absent assertions. Wired into test.sh after mesh.sh.
Server-mode deploy + the full DinD e2e (servers, handshakes, 6-node mesh) are now proven in the fork CI run. NAT and client mode remain unverified; documented why and how to test.
On the linuxserver Alpine image /etc/wireguard is a dangling symlink when the s6 init is bypassed (--entrypoint sleep), so key generation failed. Use a plain /tmp/wg workdir and 'wg-quick up /tmp/wg/wg0.conf' on every node.
The server-generated peer config has AllowedIPs=0.0.0.0/0, which routes the endpoint through the tunnel and deadlocks the handshake, and WireGuard never initiates without traffic. external.sh now narrows AllowedIPs to the server tunnel subnet, adds PersistentKeepalive, and pings the server tunnel IP to trigger the handshake.
tests/ -> files/test/ (test.sh/local.sh/external.sh/mesh.sh) + templates/test.env.j2 (the test-e2e-cli discovery marker). README and requirement 026 updated to the adopted contract.
The deployed role already binds the host WireGuard port; the e2e servers are reached by container name over the compose network, so publishing host ports only caused a 'port is already allocated' collision.
local.sh used docker-style 'compose -f … -p …'; the repo compose wrapper takes --chdir/--project. e2e.sh now disables CA injection so 'container run' stays a plain passthrough (the CA path drops --device/--sysctl).
The checkmk OMD site cannot live on NFS (fcntl locks return EBADF) and must stay node-local, but an unpinned single-replica service loses that data on a swarm reschedule. Pin checkmk to the manager so the task never leaves the node holding its data, and teach the nfs-false-data-loss lint to accept a manager-pinned role as justification (dropping checkmk's now-redundant per-volume opt-out).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename the meta/services.yml key across all roles, the roles_with_default_placement lookup (now roles_with_placement), the get_role_default_placement / iter_roles_with_default_placement helpers, and every consumer (swarm closure, compose_volumes filter, nfs_prep, container deploy template, constructor stage, extend_inventory) plus their tests and docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>