Compare commits
6 commits
4cfc3cddd5
...
8d2a064542
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d2a064542 | |||
| 4c8fb9e03b | |||
| d202b89480 | |||
| 9b3f8f826f | |||
| 44c4978b5f | |||
| 98eb09d8ba |
13 changed files with 261 additions and 80 deletions
|
|
@ -30,8 +30,8 @@ _Last reviewed: 2026-06-14._
|
|||
| `roles/dev_env/` — interactive developer environment | **Built + applied.** zsh + oh-my-zsh + oh-my-posh, tmux + TPM plugins, neovim; dotfiles deployed via GNU stow (re-derived from V4/fisi per ADR-013). Node.js from a pinned upstream tarball (not Debian's npm). Lint + Molecule (idempotent) green. **Applied to `ubongo`** for users `sjat` + `claude` (verified: zsh login shells, stow-symlinked `.zshrc`/`.tmux.conf` + nvim config, oh-my-zsh, tmux plugins; nvim v0.12.2, oh-my-posh 29.0.1). Run via `playbooks/workstation.yml` against the `control` group (no dedicated `workstations` group yet). |
|
||||
| `make check` / `make deploy PLAYBOOK=<name>` | **Works.** First end-to-end run (applying `dev_env`) surfaced + fixed latent bugs: Makefile `PLAYBOOK` var collision (binary path vs playbook-name arg) meant the targets never ran; `ansible.cfg` referenced uninstalled community.general callbacks (now built-in `default` + `ansible.posix.profile_tasks`); `acl` package added so Ansible can `become_user` an unprivileged user. The make targets now function — though `site`/`base`/`docker_host` content is still incomplete (see below). |
|
||||
| `roles/public_dns/` + `playbooks/dns.yml` | **Built + applied.** Manages wingu.me at Gandi LiveDNS as code (`community.general.gandi_livedns`, PAT from `vault.gandi.pat`); record data, anti-spoof baseline (SPF `-all` + DMARC reject), and the Gandi-defaults purge are defined + unit-tested (`tests/test_public_dns.py`). **Applied to wingu.me (2026-06-14):** purged Gandi's 13 seeded defaults; zone now holds only the SPF + DMARC TXT records; idempotent re-run clean. No null-MX (Gandi rejects `0 .`) — the MX is removed, so no MX + no apex A = no mail. M1 of the roadmap. |
|
||||
| `ubongo` — physical control / AI-worker host (ADR-015) | **Built (partial).** Debian 13.5 on a Lenovo M70q (i3-10100T, 16 GB, 256 GB SSD; no disk encryption — accepted risk). Full toolchain installed + pinned to `fisi` (Docker 29.5.3, rbw 1.15.0, Claude Code 2.1.173, ansible-core 2.17.14 + molecule via `make setup`/`make collections`). Repo cloned under a dedicated `claude` user (docker group, no sudo). Vault works via rbw (offline-cache decryption verified). SSH key-only (password + root login disabled). In the production inventory `control` group at 10.20.10.151. **`dev_env` now applied here** (zsh/tmux/nvim for `sjat` + `claude`, via `playbooks/workstation.yml`). Managed as the operator account `sjat` (`group_vars/control` sets `ansible_user: sjat`), not the `ansible` service user `group_vars/all` assumes — ubongo has no bootstrapped `ansible` user. **Pending:** NetBird mesh enrollment (so SSH is LAN-only); full `base` hardening (only the `firewall` concern exists, and it is NOT applied here — applying default-deny with no mesh would lock out inbound SSH on the physical NIC); proper `ansible`-user bootstrap (currently managed as `sjat`); OPNsense DHCP reservation for 10.20.10.151 (MAC `88:a4:c2:e0:ee:da`); Terraform state backup (now relevant — the offsite tfstate exists). |
|
||||
| `askari` — off-site Hetzner VPS (ADR-007/016, M2) | **Built + applied.** Provisioned by Terraform (`environments/offsite`, `hetznercloud/hcloud`) as **cx23 / hel1 / Debian 13.5** (CAX11/ARM was out of stock EU-wide on 2026-06-14 → cx23 is same-spec x86, cheaper). cloud-init created the `ansible` user + passwordless sudo; a TF-managed Hetzner Cloud Firewall allows SSH only from ubongo's WAN (`91.226.145.80`). Reachable from ubongo (`ansible offsite_hosts -m ping` ✓), in the `offsite_hosts` inventory (generated `offsite.yml`), published at `askari.wingu.me` → `77.42.120.136`. **SSH-hardened + fail2ban (M3).** **Docker + Caddy reverse proxy (M4a):** `docker_host` + `reverse_proxy` (vanilla Caddy, HTTP-01) applied; `https://test.askari.wingu.me` serves a valid Let's Encrypt cert ✓ (firewall opens 80/443/3478). **NetBird coordinator (M4b):** `netbird_coordinator` deployed — dashboard live at `https://netbird.askari.wingu.me` (valid LE cert), management API behind embedded Dex (401 unauth), STUN on 3478/udp. **Pending:** host firewall + mesh enrollment (M5 — incl. first-boot `/setup` admin + peer setup keys), offsite tfstate backup (ADR-022). |
|
||||
| `ubongo` — physical control / AI-worker host (ADR-015) | **Built (partial).** Debian 13.5 on a Lenovo M70q (i3-10100T, 16 GB, 256 GB SSD; no disk encryption — accepted risk). Full toolchain installed + pinned to `fisi` (Docker 29.5.3, rbw 1.15.0, Claude Code 2.1.173, ansible-core 2.17.14 + molecule via `make setup`/`make collections`). Repo cloned under a dedicated `claude` user (docker group, no sudo). Vault works via rbw (offline-cache decryption verified). SSH key-only (password + root login disabled). In the production inventory `control` group at 10.20.10.151. **`dev_env` now applied here** (zsh/tmux/nvim for `sjat` + `claude`, via `playbooks/workstation.yml`). Managed as the operator account `sjat` (`group_vars/control` sets `ansible_user: sjat`), not the `ansible` service user `group_vars/all` assumes — ubongo has no bootstrapped `ansible` user. **NetBird mesh-enrolled (M5, 2026-06-17):** `wt0` up at `100.99.146.14` via the `base` `mesh` concern; agent management now works because `claude`'s SSH key was added to `sjat`'s `authorized_keys` and `sjat` was granted `NOPASSWD` sudo (`/etc/sudoers.d/sjat-ansible`) — the interim until the proper `ansible`-user bootstrap. **Pending:** full `base` hardening (only `firewall` exists, NOT applied here — default-deny is the deferred mesh-hardening step now that `wt0` exists); proper `ansible`-user bootstrap (currently managed as `sjat`); OPNsense DHCP reservation for 10.20.10.151 (MAC `88:a4:c2:e0:ee:da`); Terraform state backup (now relevant — the offsite tfstate exists). |
|
||||
| `askari` — off-site Hetzner VPS (ADR-007/016, M2) | **Built + applied.** Provisioned by Terraform (`environments/offsite`, `hetznercloud/hcloud`) as **cx23 / hel1 / Debian 13.5** (CAX11/ARM was out of stock EU-wide on 2026-06-14 → cx23 is same-spec x86, cheaper). cloud-init created the `ansible` user + passwordless sudo; a TF-managed Hetzner Cloud Firewall allows SSH only from ubongo's WAN (`91.226.145.80`). Reachable from ubongo (`ansible offsite_hosts -m ping` ✓), in the `offsite_hosts` inventory (generated `offsite.yml`), published at `askari.wingu.me` → `77.42.120.136`. **SSH-hardened + fail2ban (M3).** **Docker + Caddy reverse proxy (M4a):** `docker_host` + `reverse_proxy` (vanilla Caddy, HTTP-01) applied; `https://test.askari.wingu.me` serves a valid Let's Encrypt cert ✓ (firewall opens 80/443/3478). **NetBird coordinator (M4b):** `netbird_coordinator` deployed — dashboard live at `https://netbird.askari.wingu.me` (valid LE cert), management API behind embedded Dex (401 unauth), STUN on 3478/udp. **NetBird peer (M5, 2026-06-17):** also enrolled as a mesh agent (`base` `mesh` concern) — `wt0` at `100.99.226.39`, Management+Signal Connected; the agent coexists with the coordinator. **Pending:** host firewall + moving askari's SSH onto `wt0` (deferred mesh-hardening; the Hetzner Cloud Firewall is its perimeter until then), offsite tfstate backup (ADR-022). |
|
||||
| `roles/docker_host/` (Docker engine) + `roles/reverse_proxy/` (Caddy, ADR-024) | **Built + applied** (askari, M4a). `docker_host` installs Docker CE + compose; `reverse_proxy` is boma's standard Caddy proxy (HTTP-01 for public hosts; routes from `reverse_proxy__routes`). **DNS-01 for mesh/LAN-only services is now built + proven (2026-06-15):** custom `caddy-gandi` image (`.docker/caddy-gandi/`, `make caddy-image`, pinned caddy-dns/gandi v1.1.0 → Bearer PAT), enabled per-instance via `reverse_proxy__acme_dns_provider: gandi` + `reverse_proxy__image`. Verified end-to-end — a real wildcard cert issued via LE **staging** + Gandi DNS-01 with `vault.gandi.pat`. M4a's deferral (version skew + Hetzner-IP build) is closed; image **pending registry push** (`make caddy-image-push` needs `docker login`). The `reverse_proxy` Caddyfile is bind-mounted as a **directory** (`./caddy` → `/etc/caddy`) so atomic re-renders are visible in-container and `caddy reload` actually applies new routes (a single-file mount pinned the stale inode). |
|
||||
| `roles/netbird_coordinator/` — NetBird control plane (ADR-016, M4b) | **Built + applied (askari, 2026-06-16). boma's FIRST real service role.** Self-hosted NetBird **v0.72.4**: a single combined `netbird-server` container (management + signal + relay + STUN + **embedded Dex IdP** at `/oauth2`) + `dashboard:v2.39.0`, on the shared `boma` network behind the M4a Caddy via gRPC-h2c + WebSocket + path routing (`reverse_proxy__routes` gained a raw-`caddy` route type). Secrets `vault.netbird.{auth_secret,datastore_key}` (self-generated). Carries the full service-role file set (SECURITY/VERIFY/ACCESS/BACKUP) — **first stateful role** (`backup__state: true`; encrypted SQLite at `/var/lib/netbird`, off-site backup pending `fisi`/ADR-022). **Verified live:** dashboard 200 + valid LE cert, `/api` 401 (auth-gated, routes OK), STUN up. **Not yet configured:** first-boot `/setup` admin + peer enrolment = M5. |
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ askari.)
|
|||
| CIS hardening (Debian L1+L2 + Docker) | ADR-002 / TODO 15 | Implemented by the (unbuilt) `base`/`docker_host` roles; brings AppArmor + AIDE as baseline. L2 partitions affect VM provisioning (ADR-006) |
|
||||
| Network IDS + security alerting | ADR-002 / TODO 15 | Suricata on OPNsense + AIDE/`auditd`/`fail2ban` alerting into the monitoring stack; not built |
|
||||
| NetBird mesh — coordinator on `askari` | ADR-016 | **BUILT + applied (M4b, 2026-06-16)** — moved up to "Real and working today" (`roles/netbird_coordinator/`). Self-hosted control plane on askari; replaces ADR-007 WireGuard. Mesh **peer enrolment = M5** (next row). |
|
||||
| NetBird agent enrollment in `base` | ADR-016 | **Design RESOLVED** (ADR-016). Every Linux host joins the mesh via the base role (setup keys in vault); SSH allowed only on `wt0`. **Build pending:** base role not built. |
|
||||
| NetBird agent enrollment in `base` | ADR-016 | **BUILT + applied (M5, 2026-06-17).** The `base` `mesh` concern (opt-in `base__mesh_enabled`) installs the pinned NetBird agent + runs `netbird up` with the reusable scoped key from `vault.netbird.setup_key`. Applied to **askari (`100.99.226.39`) + ubongo (`100.99.146.14`)** — both Management+Signal Connected; ubongo↔askari mesh ping verified. Enrollment is **additive** — the "SSH only on `wt0`" firewall lockdown is the deferred mesh-hardening follow-on, NOT applied. Road-warrior clients (laptops) are operator-enrolled. |
|
||||
| Service-UI verification (Level 4) | ADR-017 / ADR-008 | **Design RESOLVED** (ADR-017 + spec + plan); resolves ADR-015 deferred #2. `/verify-service` skill + `VERIFY.md` template + standards are authorable and present. **Build pending:** running needs ubongo + `playwright` plugin + Authentik + a staging deploy. |
|
||||
| Logging pipeline (Loki + Alloy + off-site subset) | ADR-018 | **Design RESOLVED** (ADR-018 + spec). All logs → on-cluster Loki; security subset write-only off-site to askari. **Build pending:** Alloy in `base`, `loki`/`grafana` service roles, OPNsense syslog — none built. |
|
||||
| Security alerting (AIDE/auditd/fail2ban/Suricata + log-silence) | ADR-002 / ADR-018 | Wired into Grafana on the Loki stack. Designed; depends on the logging pipeline + metrics stack (TODO 3.6). |
|
||||
|
|
|
|||
|
|
@ -69,6 +69,26 @@ _(append new raw signals here; the next kaizen review consumes them)_
|
|||
push-vs-not / subagent-vs-inline, since prose reminders have already failed this many
|
||||
times. Default behaviour: **push as backup and proceed subagent-driven without asking.**
|
||||
|
||||
- `[friction]` **A docs-only commit still tripped the `rbw`-locked pre-commit guard**
|
||||
(2026-06-17): committing only `docs/superpowers/specs/*.md` (no ansible content) was
|
||||
blocked needing the vault password, although the 2026-06-10 kaizen fix scoped the
|
||||
pre-commit `ansible-lint` hook (`always_run: false` + `files:` ansible content) so
|
||||
docs-/config-only commits skip it and need no vault. So either the hook's `files:`
|
||||
pattern still matches `docs/**` (or `.md`), or a blanket pre-commit step needs the
|
||||
vault regardless. → check `.pre-commit-config.yaml`'s `files:`/`exclude:` against the
|
||||
spec/plan paths; docs-only commits should not require `rbw`.
|
||||
|
||||
- `[friction]` **The agent can't manage `ubongo` (the control node it runs ON) without
|
||||
the operator granting access** (2026-06-17): enrolling `ubongo` in the mesh needed two
|
||||
manual operator grants because the agent runs as `claude` (no sudo) but the inventory
|
||||
manages `ubongo` as `sjat`: (1) `claude`'s SSH key added to `sjat`'s `authorized_keys`
|
||||
(`Permission denied (publickey)` otherwise), then (2) `NOPASSWD` sudo for `sjat`
|
||||
(`Missing sudo password` otherwise). So the "AI-worker control node" (ADR-015) can drive
|
||||
the whole fleet but not itself, unattended. This is the **pending `ansible`-user
|
||||
bootstrap** gap (STATUS) biting in practice. → the proper fix is ubongo's bootstrap to a
|
||||
key-trusted, NOPASSWD `ansible` (or `sjat`) management identity as part of `base`/its
|
||||
control-node recipe, so control-node self-management doesn't need ad-hoc operator grants.
|
||||
|
||||
- `[recurring]` **ADRs claim cross-doc reconciliation they didn't actually perform**
|
||||
(2026-06-14): ADR-024's Status + Consequences asserted "ADR-017 prose that mentioned
|
||||
Traefik is updated to read Caddy" — but ADR-008/017/019 + CAPABILITIES still said
|
||||
|
|
|
|||
|
|
@ -134,16 +134,20 @@ Dashboard live at `https://netbird.askari.wingu.me` (valid LE cert); `/api` auth
|
|||
- **Maps to:** ADR-016 (mesh), ADR-004 (one service = one role), ADR-021 (access),
|
||||
ADR-022 (backup), ADR-008/017 (VERIFY), accepted-risk R3 (askari public surface).
|
||||
|
||||
### M5 · Enroll peers → goal reached
|
||||
### M5 · Enroll peers → goal reached — ✅ infra done (2026-06-17); laptops = operator step
|
||||
|
||||
NetBird agent on `ubongo` (the `wt0` path appears), then NetBird **clients on `mamba` +
|
||||
the work laptop** → `ubongo` is reachable from anywhere. **← the mobile-access goal lands
|
||||
here.**
|
||||
The `base` `mesh` concern enrolled **`ubongo` (`100.99.146.14`) + `askari`
|
||||
(`100.99.226.39`)** as NetBird peers — both Management+Signal Connected, the ubongo↔askari
|
||||
mesh link ping-verified. NetBird ships a default **Allow-All** peer policy, so any enrolled
|
||||
peer can already reach `ubongo` over `wt0`. **Remaining (operator):** install the NetBird
|
||||
client on `mamba` + the work laptop and log in → `ubongo` reachable from anywhere. **← the
|
||||
mobile-access goal lands when the laptops join.**
|
||||
|
||||
- **Critical ordering:** NetBird-on-`ubongo` **before** applying `base` default-deny to
|
||||
`ubongo`. Hardening first would lock out SSH (no mesh path yet). Once the mesh `wt0`
|
||||
path exists, apply default-deny and set `base__firewall_control_addr` for the LAN
|
||||
fallback (ADR-021's `ssh-from-control`, already built/dormant).
|
||||
- **Deferred to a "mesh-hardening" follow-on** (was folded into M5; split out as the
|
||||
lockout-risky part): apply `base` nftables **default-deny** to `ubongo` + set
|
||||
`base__firewall_control_addr` (ADR-021 `ssh-from-control`, built/dormant); tighten the
|
||||
NetBird ACL off Allow-All to scoped policies; move `askari`'s SSH onto `wt0` (retiring
|
||||
the Hetzner-firewall WAN allow). Safe to do now that the `wt0` path exists.
|
||||
- **Maps to:** ADR-016, ADR-021 (SSH ladder: `wt0` + ssh-from-control), ADR-020.
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,70 +1,86 @@
|
|||
$ANSIBLE_VAULT;1.1;AES256
|
||||
30613536623331613935326162646664303565646530376564343633313431636165626431313264
|
||||
3034343032356461306137346162626637663139653033650a346164393839343264633062663030
|
||||
34623764363631356239363737393265613961323633316239653032633532623032636632316132
|
||||
6633306637653839660a656161643030626562653062303762616162393836383635323461303337
|
||||
64336339633161643664306666306530333363653362313731613231396133346433666437346231
|
||||
61306232646235396161383634363265623432373737353036656664326630313335313463323462
|
||||
65383832313066633539643632326563336438616261623630316230643239323435613337303361
|
||||
30383039653531396264613237396138363836616163626366363063383634323335383038386362
|
||||
34343064656365336530666435636465393966373434633230373534353261656566656138356636
|
||||
35303032396365346136383837633134343037343332393863363832616139633964396638643833
|
||||
30323834303737346266383237643530306366653262633131663332613937626632363732613932
|
||||
39313864613038356262323465393062636535663138633738376163363930313132323735383565
|
||||
66353964633230613266663433313234383961666464636561343364303536306334336536373836
|
||||
63363366333136623137346537623230393935656334396565303231663833386338666636663833
|
||||
65656633663335316162343438396264663738343861393237353537393432333035393331626566
|
||||
31383534623339346338646434613230336566363063333137343636666238303637626637363263
|
||||
30663131636634623861623232303031633862343538386232653637613866376231336465393535
|
||||
33343164346661626361623136383230393365396636356266656637366537613331343330643532
|
||||
30653333346235303338396336303965656232323165643465653235616666636631336633613132
|
||||
30316161626236663365613133336430643030323164366563613633666362666239333164306662
|
||||
62623163343162373261653332636333373462323635633364356531396538316134356234663861
|
||||
33363766343666303135356165626136626164666630386161393062636662383835653731373830
|
||||
65653335373664316638376239633137393537343362346535343138656265323836653332616630
|
||||
33623938626139343662626639386536626134396663653930373532343865386565356336303334
|
||||
35343134323765653764613132656430333362373535613662336234366164313965666362613733
|
||||
66626663353030626332326433623734643961646336613937346637333439333731633438336339
|
||||
64653537326131623061316239323132663231653863393230653439646266633764633934366563
|
||||
63656136376531393761306331383866656338306432333966636166643831323065353866313336
|
||||
39636232306362386439663866653238626532316339346432373933316565386265303739663764
|
||||
61626337313963363365666438363837353732353938613962303832343639306135363864333536
|
||||
64306634303235396163663837323931383031616335396438383636336264346361316439326133
|
||||
64363231636434396166343530643037373232386336623433393436356236643938386331376237
|
||||
30613164616532356163303430333861613863643132303565346461613433343634353036666638
|
||||
33333533646263636362393865633166353962653137353831346366336235326465333436333230
|
||||
62633339313364663765613361316264346161356334313866656436643666393631376433313333
|
||||
62373361313633663037643038333233346461383732613939343935353635373738326566333838
|
||||
37313338336532383938303762303062373138353436626462323439356663626431366563633863
|
||||
38636234383164626636633566643963366466666334323131336166623837313933343262323834
|
||||
32643134336137616462353862336533653062313664346138383762356663343861386134393361
|
||||
63303763346161656465626465666463356631336539333234623931373764323638623331396234
|
||||
65333036653131353737376663633134633238666535636661383530333032333466643438333163
|
||||
33333231393134393165363036353262323836363965323037396531373865656363366534636263
|
||||
34633131616637323432396162646466316166373639313731626364633234393339333333373663
|
||||
38363164353262376338333933383732393631626532313861633465646231666335396233376266
|
||||
66313165633165313566646266663265633730316330643261373838343665613035373662323365
|
||||
35333836336235396237333934653766333732383533373732353633383931323232663731393965
|
||||
39623161613131626562663632373031663234656438316363373462316137646236323438663031
|
||||
36613666383863623033383231333338613537333565653633616635366463313062613263343938
|
||||
31633839376164383261333465326538373439653265373665323063623366616366356138666265
|
||||
34666164393165386566346533396638623464383937623539346234303730626463636435333434
|
||||
36313466306166333264346533623132306262646538316335343936373862363931303366643765
|
||||
65396132306664393435643531646637633939616636663933393138383137633536656362386165
|
||||
35653337326537633539626332333565643831633339393866616164653862306333393531336130
|
||||
30383561366431303030376436643434643466323562323730633638643663613339386239646562
|
||||
31353266386164343832376464303962363665316261383031633534333333333766656530306664
|
||||
31633931653231653530343763383738336333323161663031646331333638356233343661656463
|
||||
63316234333430643730663661363662373030653730613762663464393937393962373064623631
|
||||
38343864313764633737303838616133383636666130396339316138346162386438306664306363
|
||||
32333438383033626235656133356335623834656637386633333839343134363137363266636536
|
||||
36303235393264653462353833323030333263666464663864623964363738393166613439313639
|
||||
62656538343662343665356339326364613032363334376232666434613836346638333464623266
|
||||
65346236393161663562323865613437633863396437383233363532396136336534376431613937
|
||||
35383231323430323462343861666564663734666564393131313932333831643035303036613430
|
||||
30313636613939616336323534636131393761356534306332343735616136333531366339343936
|
||||
65393536393636666639633236303234653766306263393237653437353632373430653438633736
|
||||
63633139323732653566663062373537376463383439643336383434646533353762623636323031
|
||||
65323233306666323630366164366331646632303263333665336432396262383138643432666365
|
||||
37633336663362323132646438363832346438653361346438303630636131646638323461376534
|
||||
36663333353962636266643336373963623564326366333736393936396333326262
|
||||
32313030663934353361336234373562303537356334346238663836373238366136356331363761
|
||||
6337323031666565663430303562646565303533653531640a636662373939363632383838613431
|
||||
38313365626365373539653266326661393765333737386161666165666534636562353165386537
|
||||
3934633033383966360a323965333139643764326236396635383863353437313966326665373537
|
||||
65396564393130303030643861663964383436396561643666623837306366346333306430306238
|
||||
66656136626566626262373037623531623633313664376166376161363336353930636538323339
|
||||
38386564333432353363353663643539343765373662643836646666626339353539323033386230
|
||||
31613165373035363533383862366638353035653836303737656534623361313064616365643131
|
||||
64386165653835366137353339396364313661656333333635616338346561363765353934343162
|
||||
64346462656566376539643030656461363161393936623332373632653731303031393437316636
|
||||
36626165306161336262356161666531323336343663643661626365396437383230613636356530
|
||||
62326363383138643162316464396666623332366434336462363531363836313833366237396464
|
||||
38323635353238653432626361383434646538326531356333393337643066373262663462656466
|
||||
65373036653265616137666533373930333239303732623832353337343434636434616562336135
|
||||
38666137353266353130303235616362323633353735373163336138633838633738393637633964
|
||||
66623866353265316336336566663034306664656365643832616232313732626464316563636335
|
||||
63653930626565636630326661626561366539303964373933653437356537343361626438313439
|
||||
35643165636662643463616337323063343633306536346538623331333365366533653634343538
|
||||
63623261636366303261373338633939363338316463303065613436396163616537666265623439
|
||||
31383361646531633863623230616635646138653630383537366335633030343530383735616435
|
||||
35656464393432313563303030626133383761303763653530653837313930303034353136353237
|
||||
37376366623836646236363062633938666135326631376235323061666465373865396235643937
|
||||
32633736656539356332336237646137303534343337353139383637623165353338623566666535
|
||||
30643134303235633362383064376234366235363262396362613731373364306362303634613138
|
||||
39366230366262363237656631646361356464393266656166386337303663313136666261633836
|
||||
32306132323239343539396232316564326361626462366561313561393635393233653633646431
|
||||
39313039313139616262396334613035333633326135346365333537373138396535633137353832
|
||||
63636335613237623234646234653435616635356637343964656463383864366534363438343938
|
||||
39626364653832373062323434316134653831336534383934346231656533643435306465393065
|
||||
31653731653438646361363732303664626438663533393837356562376633643933376132616236
|
||||
65393432633831313433323930383736316630626230373963653536396637363436643136363962
|
||||
37326534343237363961326438376137663034356532376433376461363337333562646136616462
|
||||
61636131376264393236376532356539376536643632623864656331656630353362623133303830
|
||||
34633461633539643262353263376363613566343261373930623139626364653232363538353330
|
||||
33633634363232653439656236303262373265613762373165646131383537623438383835383962
|
||||
33383931626136313036366562363732396561633631643561646536653665333733383261363833
|
||||
66356461663965373234393237323037356331333339643931313936313234323432613563306630
|
||||
33306638663839363565636661653830316265393639313065313062666534303039326465373636
|
||||
64363033323837313030353132383562343337326366626635663439396231393537313932643337
|
||||
30663031323231313938366436343735326165326433656633336465316630383961626664303536
|
||||
38633964326431643362626631656131303539613033323039393630353766386339346363663362
|
||||
33323034396136356362313163376438393739373738366363623636623634316537313461373066
|
||||
38613062656231363532663133333438663535666566356336316266383763623765346237663838
|
||||
64336435353437373264346561363265643339306532383539306363653564356362313430333066
|
||||
65633733633938343830303537383231303036326132376263363531626565633664343038356661
|
||||
31336139663061656437633138373438663966616338343565396562306638346437353730643664
|
||||
30373133373863626137313062643062393035653463653231653465333166633063353137633538
|
||||
62383331303164343236343539396461623738396234653333356632313664616263623061363563
|
||||
34323165306533323362376161346364316135333535626261353730666131643938306366326263
|
||||
31313934633137623638316534383234376333396131303034633636323037363732383263326335
|
||||
32393766343161386537333062643434333333363538323366363231336666383161373432383563
|
||||
65613537366139643032336230303133623431376231646662643666373532636565393639373930
|
||||
65336630616462353837666431616662636635333532393331326539306233363539396266653239
|
||||
31303031303330396632386131623134313536313433623064356636333230373962643339363736
|
||||
30396130353466373136643935646436613636376636323530643031653334303863376432646534
|
||||
39343165356232346539366233373135326338343663356164616265336235623332646365633466
|
||||
35393533373663393762376332396136336236616635616535313336613034346436363665356565
|
||||
32636536336634613531393434613435613962653862343737373237623261373836386663343831
|
||||
66656135323838636638353963646638326531343635653937306230323237343933626135356533
|
||||
66356263636438633164386535333762616438626439343462393833393731643037396662653737
|
||||
31666361656530383437396230393663616133383764316437623939663631396561343266383766
|
||||
62373636663631393637393763613337356337633264366434346561343263373931323335643135
|
||||
31366661623137353336666630633365663764646234343035313130663562636361623532643461
|
||||
63333961333338623966396662656262323830396439633337663431663235663962666238356630
|
||||
30353331313462653061373638666235653938623931366466666164343566623238333237353265
|
||||
30373064353132366634623966306632303832306630383637623465323134633133656333303964
|
||||
35646637316236303364393363323137616132326437623238336631313530663230333362623633
|
||||
34383032376538366464363032343262656164376166386237383563613630336666633965653730
|
||||
64373236396564363164643637623736626532396630313131356563333238643665356166323837
|
||||
31626338623665623165643763623661666439626435643237336433646132666366623661393832
|
||||
37306533613966663936373061613331633934623462343236626234306130383738343631303231
|
||||
32326339323738323537333363313538373266623363363636633462356234363466393263316235
|
||||
39663033303165656366396334306535643361646663373935303230376466366632373563303231
|
||||
64323264653036333039663965646630653934376239653236323063656137373830623563336463
|
||||
37343461373737313539316361623763373733653930626532393565333938333761323631303332
|
||||
39663530303439616561356561666532653762343339323435636164376664373731343132666539
|
||||
63626637346563393765303065646564643661636130396439323736343764333633373331653333
|
||||
66633465343433303038623638323965636533666639643266353163353436393036336639336133
|
||||
32646664363565326539643763653832313336663262313634343635616333613434373333323036
|
||||
61366435376265336638326132333439613431353633653762653836386235643965366436363866
|
||||
35626664393139386337353335343930306130356335623131646261656434303966656431623231
|
||||
66643730393430363838626434663933613536343533316262373564666665373663336363623166
|
||||
63363037373634383961373035633239646235316137363036333765313864643365396165643432
|
||||
36623465313036376261393566383539336638363836633232656136656533396663323366313062
|
||||
64616632373333313466356362336234346564373832316433373963623263316635
|
||||
|
|
|
|||
|
|
@ -11,3 +11,8 @@ dev_env__users:
|
|||
# assumes. Manage it as the operator account. Overrides the all-group default for this
|
||||
# group only.
|
||||
ansible_user: sjat
|
||||
|
||||
# ubongo is a NetBird mesh peer (ADR-016, M5) — enrol the agent via base's `mesh` concern.
|
||||
# Enrollment only; the host firewall default-deny stays deferred (the mesh-hardening
|
||||
# follow-on), so this brings up wt0 without changing SSH exposure.
|
||||
base__mesh_enabled: true
|
||||
|
|
|
|||
6
inventories/production/group_vars/offsite_hosts/vars.yml
Normal file
6
inventories/production/group_vars/offsite_hosts/vars.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
# Off-site hosts (askari). askari runs the NetBird coordinator AND is a mesh peer
|
||||
# (ADR-016, M5) — enrol the agent via base's `mesh` concern. Enrollment only; the
|
||||
# host firewall default-deny + moving askari's SSH onto wt0 stay deferred to the
|
||||
# mesh-hardening follow-on.
|
||||
base__mesh_enabled: true
|
||||
|
|
@ -27,3 +27,30 @@ render + validate without applying (used by Molecule).
|
|||
- `make test ROLE=base` — Molecule renders + `nft -c` syntax-checks (never applies; it
|
||||
shares the host kernel). Enforcement + the apply/rollback path are verified at ADR-008
|
||||
Level 2 on staging VMs.
|
||||
|
||||
## Mesh enrollment (NetBird agent)
|
||||
|
||||
Enrols the host as a NetBird *agent* on the self-hosted mesh (ADR-016): installs the
|
||||
pinned `netbird` daemon from the upstream APT repo (keyring in `/etc/apt/keyrings`,
|
||||
mirroring the `docker_host` repo idiom) and runs `netbird up` against the coordinator
|
||||
with a setup key. Tagged `mesh`.
|
||||
|
||||
**Additive only — this concern makes no firewall change.** SSH is already gated to the
|
||||
NetBird overlay interface by the `firewall` concern (`base__firewall_mgmt_interface`,
|
||||
default `wt0`); enrolling a host simply brings that interface up. No port is opened here.
|
||||
|
||||
Enrolment is **opt-in**: `base__mesh_enabled` defaults to `false`, so applying `base` to
|
||||
a host not on the mesh is a no-op for this concern. Re-enrolment is guarded on
|
||||
`netbird status` reporting `Management: Connected`, so re-runs are idempotent. The setup
|
||||
key is sourced from `vault.netbird.setup_key` and passed with `no_log` (it lands on the
|
||||
process argv).
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
|------------------------------|--------------------------------------|---------|
|
||||
| `base__mesh_enabled` | `false` | Opt-in switch — include the concern at all. Set per-host/group to enrol. |
|
||||
| `base__mesh_manage` | `true` | Test gate — when `false`, skips the live network/daemon tasks (apt install, status check, `netbird up`) so Molecule can exercise the wiring without a coordinator. |
|
||||
| `base__mesh_management_url` | `https://netbird.askari.wingu.me` | Coordinator (management) URL. |
|
||||
| `base__mesh_setup_key` | `{{ vault.netbird.setup_key }}` | Enrolment setup key, from vault. |
|
||||
| `base__mesh_version` | `"0.72.4"` | Pinned agent version (matches the coordinator). The exact apt version string is confirmed on-host at deploy. |
|
||||
|
|
|
|||
|
|
@ -20,3 +20,13 @@ base__fail2ban_bantime: 1h
|
|||
base__fail2ban_findtime: 10m
|
||||
# base__ssh_authorised_keys lives in group_vars/all/vars.yml (per-person control keys).
|
||||
base__ssh_authorised_keys: []
|
||||
|
||||
# NetBird mesh agent enrollment (ADR-016). Opt-in: default off so applying `base` to a
|
||||
# host not on the mesh is a no-op for this concern. The live actions (apt install over
|
||||
# the network, `netbird up` against the coordinator) are additionally gated by
|
||||
# base__mesh_manage so Molecule can exercise the wiring without a coordinator.
|
||||
base__mesh_enabled: false
|
||||
base__mesh_manage: true
|
||||
base__mesh_management_url: "https://netbird.askari.wingu.me"
|
||||
base__mesh_setup_key: "{{ vault.netbird.setup_key }}"
|
||||
base__mesh_version: "0.72.4" # match the coordinator; exact apt pin confirmed on-host at deploy
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@
|
|||
vars:
|
||||
base__firewall_apply: false
|
||||
base__firewall_control_addr: 10.10.0.99 # test control-node LAN address
|
||||
# Exercise the mesh concern's include path with the live actions gated off, so it
|
||||
# runs hermetically (no coordinator/key needed) and must be a clean no-op.
|
||||
base__mesh_enabled: true
|
||||
base__mesh_manage: false
|
||||
base__mesh_setup_key: "dummy-molecule-key"
|
||||
firewall_zones:
|
||||
lan: 10.30.0.0/24
|
||||
srv: 10.20.0.0/24
|
||||
|
|
|
|||
|
|
@ -57,3 +57,16 @@
|
|||
- name: Fail2ban sshd jail configured
|
||||
ansible.builtin.command: grep -q '^\[sshd\]' /etc/fail2ban/jail.d/sshd.local
|
||||
changed_when: false
|
||||
|
||||
# mesh concern: enabled but manage=false must be a clean no-op (no install/enrol)
|
||||
- name: Check whether netbird got installed
|
||||
ansible.builtin.command: which netbird
|
||||
register: _nb
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
- name: Assert mesh manage=false installed nothing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _nb.rc != 0
|
||||
fail_msg: "netbird must not be installed when base__mesh_manage is false"
|
||||
success_msg: "mesh concern is a clean no-op under manage=false"
|
||||
|
|
|
|||
|
|
@ -22,3 +22,11 @@
|
|||
apply:
|
||||
tags: [hardening]
|
||||
tags: [hardening]
|
||||
|
||||
- name: NetBird mesh enrollment
|
||||
ansible.builtin.include_tasks:
|
||||
file: mesh.yml
|
||||
apply:
|
||||
tags: [mesh]
|
||||
when: base__mesh_enabled | bool
|
||||
tags: [mesh]
|
||||
|
|
|
|||
66
roles/base/tasks/mesh.yml
Normal file
66
roles/base/tasks/mesh.yml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
# NetBird agent enrollment (ADR-016). Additive only — no firewall change here.
|
||||
- name: Install NetBird apt prerequisites
|
||||
ansible.builtin.apt:
|
||||
name: [ca-certificates, curl, gnupg]
|
||||
state: present
|
||||
update_cache: true
|
||||
when: base__mesh_manage | bool
|
||||
tags: [mesh]
|
||||
|
||||
- name: Ensure /etc/apt/keyrings exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: base__mesh_manage | bool
|
||||
tags: [mesh]
|
||||
|
||||
- name: Add the NetBird APT GPG key
|
||||
ansible.builtin.get_url:
|
||||
url: https://pkgs.netbird.io/debian/public.key
|
||||
dest: /etc/apt/keyrings/netbird.asc
|
||||
mode: "0644"
|
||||
when: base__mesh_manage | bool
|
||||
tags: [mesh]
|
||||
|
||||
- name: Add the NetBird APT repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >-
|
||||
deb [signed-by=/etc/apt/keyrings/netbird.asc]
|
||||
https://pkgs.netbird.io/debian stable main
|
||||
filename: netbird
|
||||
state: present
|
||||
when: base__mesh_manage | bool
|
||||
tags: [mesh]
|
||||
|
||||
# The apt pin string can't be confirmed from docs — it might be a bare "0.72.4" or
|
||||
# carry a packaging suffix. The live deploy task confirms the exact on-host string.
|
||||
- name: Install the NetBird agent (pinned)
|
||||
ansible.builtin.apt:
|
||||
name: "netbird={{ base__mesh_version }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
when: base__mesh_manage | bool
|
||||
tags: [mesh]
|
||||
|
||||
- name: Check current NetBird connection status
|
||||
ansible.builtin.command: netbird status
|
||||
register: _netbird_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: base__mesh_manage | bool
|
||||
tags: [mesh]
|
||||
|
||||
- name: Enrol this host in the mesh
|
||||
ansible.builtin.command: >-
|
||||
netbird up
|
||||
--management-url {{ base__mesh_management_url }}
|
||||
--setup-key {{ base__mesh_setup_key }}
|
||||
register: _netbird_up
|
||||
changed_when: _netbird_up.rc == 0
|
||||
when:
|
||||
- base__mesh_manage | bool
|
||||
- "'Management: Connected' not in (_netbird_status.stdout | default(''))"
|
||||
no_log: true # setup key is on the argv
|
||||
tags: [mesh]
|
||||
|
|
@ -20,6 +20,7 @@ concerns:
|
|||
- config # render templated config/compose files to disk — no restart
|
||||
- deploy # bring services up / restart (compose up -d)
|
||||
- proxy # reverse-proxy + TLS registration (Caddy routes, Authentik)
|
||||
- mesh # NetBird agent enrollment (ADR-016)
|
||||
|
||||
# Ansible built-in special tags. Narrow use only:
|
||||
# always — cheap preflight assertions (run regardless of --tags)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue