docs: Phase 1 complete — clients enrolled + NetBird client runbook

mamba + work laptop enrolled in the mesh → ubongo reachable from anywhere; the
mobile-access goal is met and Phase 1 (remote access) is complete. Adds
docs/runbooks/netbird-client.md (reusable client-enrollment runbook) + STATUS/
ROADMAP flips + CLAUDE.md reading-table entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sjat 2026-06-17 17:11:32 +02:00
parent 8d2a064542
commit 5d14efc864
4 changed files with 90 additions and 6 deletions

View file

@ -258,5 +258,6 @@ Single-contributor, trunk-based (no merge requests / approval gates):
| Reverse proxy (Caddy) | `docs/decisions/024-reverse-proxy.md` |
| Adding a new role | `docs/runbooks/new-role.md` |
| Adding a new host | `docs/runbooks/new-host.md` |
| Enrolling a NetBird client (laptop/phone) | `docs/runbooks/netbird-client.md` |
| Rotating vault secrets | `docs/runbooks/rotate-secrets.md` |
| Claude Code setup (per machine) | `docs/runbooks/claude-code-setup.md` |

View file

@ -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 | **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. |
| 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 (`mamba` + work laptop) enrolled (2026-06-17) → `ubongo` reachable from anywhere: the mobile-access goal is met and Phase 1 (remote access) is COMPLETE.** Client enrollment runbook: `docs/runbooks/netbird-client.md`. |
| 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). |

View file

@ -43,9 +43,10 @@ this collapses into interleaving with extra context-switching cost).
---
## Phase 1 — Off-site / Remote-access
## Phase 1 — Off-site / Remote-access — ✅ COMPLETE (2026-06-17)
Delivers mobile access to `ubongo`; proves the machinery. Ordered by *real* dependencies.
All milestones (M1M5) done; the mobile-access goal is met. Next: the Procurement gate.
### M1 · boma's DNS home — a new domain at Gandi, managed as code
@ -134,14 +135,14 @@ 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 — ✅ infra done (2026-06-17); laptops = operator step
### M5 · Enroll peers → goal reached — ✅ DONE (2026-06-17)
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.**
peer reaches `ubongo` over `wt0`. The road-warrior clients (**`mamba` + the work laptop**)
are enrolled (operator, via `docs/runbooks/netbird-client.md`) → **`ubongo` is reachable
from anywhere. ← the mobile-access goal is met; Phase 1 is complete.**
- **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

View file

@ -0,0 +1,82 @@
# Runbook — Enrolling a NetBird client (road-warrior device)
Joins a **client/road-warrior device** (laptop, desktop, phone) to the boma NetBird mesh
so it can reach `ubongo` and other peers from anywhere. The self-hosted coordinator is on
`askari` (ADR-016, M4b); enrollment lands a device on the `100.64.0.0/10` overlay.
> **Hosts vs clients.** Managed **Linux hosts** join via the `base` role's `mesh` concern
> (`base__mesh_enabled: true` + the reusable key in `vault.netbird.setup_key`) — see
> ADR-016 / the `base` README, *not* this runbook. This runbook is for **user devices**
> NetBird doesn't manage with Ansible.
verified: NetBird client install + self-hosted `--management-url` flow · docs.netbird.io
(`/get-started/install/windows`, `/get-started/cli`) · 2026-06-17
## Prerequisites
- The coordinator's first-boot `/setup` admin exists and you can log in at
`https://netbird.askari.wingu.me`.
- **Auth, pick one:**
- **SSO** (recommended for a personal device) — your dashboard account; no secret to copy.
- **Setup key** — dashboard → **Settings → Setup Keys** → a reusable key (mint a
client-specific one for clean ACL grouping, or reuse the existing reusable key).
- Local **admin rights** on the device (the client installs a service).
- **Coordinator facts:** management URL `https://netbird.askari.wingu.me`; `ubongo`
= `100.99.146.14` (`ubongo.netbird.selfhosted`); `askari` = `100.99.226.39`.
---
## Part A — Windows 11
1. **Install:** download + run the MSI **https://pkgs.netbird.io/windows/msi/x64**
(official x64 client; installs the tray app + the `netbird` service).
2. **Connect** from an **elevated** Windows Terminal / PowerShell ("Run as administrator"):
```powershell
netbird up --management-url https://netbird.askari.wingu.me
```
A browser opens — sign in with your dashboard account. (SSO won't open a browser?
use a key: `netbird up --setup-key <KEY> --management-url https://netbird.askari.wingu.me`.)
3. Proceed to **Part C** (verify).
---
## Part B — Other platforms (same management URL)
- **macOS / Linux desktop:** install the client (macOS: NetBird app / Homebrew; Linux:
`pkgs.netbird.io` per the distro — same apt/rpm flow as `base`'s `mesh` concern), then
`netbird up --management-url https://netbird.askari.wingu.me` (Linux: prefix `sudo`).
- **Android / iOS:** install the **NetBird** app, then in **Settings → Advanced /
Server** set the management server to `https://netbird.askari.wingu.me` **before**
logging in; connect and complete the SSO login. (Setup keys are supported in-app too.)
---
## Part C — Verify + use
```sh
netbird status # expect: Management: Connected, Signal: Connected, a 100.x NetBird IP
netbird status -d # peer detail — ubongo (100.99.146.14) + askari (100.99.226.39) listed
```
Reach `ubongo` over the mesh:
```sh
ssh sjat@100.99.146.14 # or: ssh sjat@ubongo.netbird.selfhosted
```
**SSH auth is separate from the mesh:** `ubongo` is key-only (passwords disabled), so the
device needs an SSH key authorised for `sjat@ubongo`. The mesh provides the network path;
the SSH key provides auth.
---
## Notes
- **Split-tunnel:** NetBird routes only the `100.x` overlay by default — normal/work
networking is unaffected.
- **Persistence:** the service auto-starts on boot and reconnects; the tray app has
Connect/Disconnect; CLI `netbird down` / `netbird up` (no flags after first setup).
- **Troubleshooting***"failed while getting Management Service public key"* / won't
register: confirm `https://netbird.askari.wingu.me` loads in a browser from the device
(DNS + TLS + the gRPC routing through Caddy are reachable), the URL is exact, and the
terminal is elevated. If a peer shows Disconnected, NAT traversal is falling back to the
relay (over 443) — usually transient.
- **Removing a device:** `netbird down` then uninstall; revoke its peer in the dashboard
(and the setup key if one-off).