Host-level Gatus rollout to kai-tower-3026 (Windows-native + WSL, no-page) #398

Closed
opened 2026-06-24 06:44:14 +00:00 by coilyco-ops · 2 comments
Member

Goal

Host-level Gatus rollout onto kai-tower-3026 so the tower joins the reachability mesh with its own outbound rows. Per Kai's "both" decision, two instances - they probe independently because WSL2 NATs through Windows and the paths fail separately (the recurring WSL-networking class: #175, #609):

  1. Windows-native (the Windows 11 host, user firem): gatus.exe as a Windows service, using the host's real network + Tailscale.
  2. WSL (kai-tower-3026-wsl, already an ansible inventory host): Linux Gatus (container or binary) over the existing ssh hop.

This is the host-level rollout the fleet-reachability work explicitly deferred - see the EXTENSION POINT comment in ansible/inventory/fleet.yml ("Windows/WSL towers + Mac get a host-level container rollout in a SEPARATE later issue"). Design parent: #255. Bundle/configs: coilyco-bridge/deploy services/fleet-reachability/config/.

Already done (configs landed, deploy#... 3c8d08c)

Both configs are authored + on canonical main, ready to consume:

  • config/gatus-kai-tower-3026.yaml (Windows-native)
  • config/gatus-kai-tower-3026-wsl.yaml (WSL)

Each probes ser8 + kai-server (tcp 6443/22 + icmp), web.port: 8089, metrics: true, and NO alerts: [telegram] (the tower is a no-page informational node - pair-only rule; do not change this).

Scope

Part A - WSL (headless-doable, has precedent)

Extend the fleet-reachability role (or a sibling) to deploy a Linux Gatus into kai-tower-3026-wsl over the existing ssh hop, consuming gatus-kai-tower-3026-wsl.yaml. Mirror the existing role's config-as-ConfigMap-or-file + idempotency patterns, adapted to a plain docker/binary host (no k3s here). Add kai-tower-3026-wsl to a NEW inventory group (e.g. fleet_reachability_towers), NOT fleet_reachability (keep it out of the pair's group + out of sync.yml, so the fleet-converge timer never fires it).

Part B - Windows-native (HARD; likely needs the Windows-automation foundation first)

Author the role to install gatus.exe as a Windows service (winsw / NSSM / scheduled task) via ansible WinRM, consuming gatus-kai-tower-3026.yaml. Caveat the agent must respect: the fleet has NO Windows-native ansible precedent yet (Windows agent-stack convergence is #356, still open). If the WinRM connection / Windows-service foundation isn't in place, do not invent a fragile one-off - author the role + inventory wiring as far as is sound, then stop and comment describing exactly what Windows foundation is missing (WinRM listener, auth, service-wrapper choice) and link #356. Part A should not block on Part B.

Out of scope / guardrails

  • No live apply. Live rollout (esp. the Windows service) needs a human on/at the tower or a working WinRM path - flag it, don't fake it.
  • Do NOT add telegram alerts to the tower (no-page node).
  • Do NOT add the tower hosts to the fleet_reachability group or to sync.yml.
  • Public-safe: short names (kai-tower-3026, ser8, kai-server) only; any opaque FQDN/IP via SSM.

Acceptance

  • WSL role: ansible-lint + --syntax-check pass; --check dry-run is clean; idempotent; documented apply command in the role README.
  • Windows role: authored as far as the existing foundation allows, with a clear comment on what's blocked and why (link #356) if it can't be completed.
  • pre-commit passes. Runbook (docs/fleet-reachability.md) updated with the tower apply steps + the confirm-before-apply expectation.

Refs: #255 (design), #356 (Windows agent-stack convergence - likely prerequisite for Part B), fleet.yml extension point, coilyco-bridge/deploy services/fleet-reachability.

## Goal Host-level Gatus rollout onto **kai-tower-3026** so the tower joins the reachability mesh with its own outbound rows. Per Kai's "both" decision, **two** instances - they probe independently because WSL2 NATs through Windows and the paths fail separately (the recurring WSL-networking class: #175, #609): 1. **Windows-native** (the Windows 11 host, user `firem`): `gatus.exe` as a Windows service, using the host's real network + Tailscale. 2. **WSL** (`kai-tower-3026-wsl`, already an ansible inventory host): Linux Gatus (container or binary) over the existing ssh hop. This is the host-level rollout the fleet-reachability work **explicitly deferred** - see the EXTENSION POINT comment in `ansible/inventory/fleet.yml` ("Windows/WSL towers + Mac get a host-level container rollout in a SEPARATE later issue"). Design parent: **#255**. Bundle/configs: coilyco-bridge/deploy `services/fleet-reachability/config/`. ## Already done (configs landed, deploy#... 3c8d08c) Both configs are authored + on canonical main, ready to consume: - `config/gatus-kai-tower-3026.yaml` (Windows-native) - `config/gatus-kai-tower-3026-wsl.yaml` (WSL) Each probes ser8 + kai-server (tcp 6443/22 + icmp), `web.port: 8089`, `metrics: true`, and **NO `alerts: [telegram]`** (the tower is a no-page informational node - pair-only rule; do not change this). ## Scope ### Part A - WSL (headless-doable, has precedent) Extend the `fleet-reachability` role (or a sibling) to deploy a Linux Gatus into `kai-tower-3026-wsl` over the existing ssh hop, consuming `gatus-kai-tower-3026-wsl.yaml`. Mirror the existing role's config-as-ConfigMap-or-file + idempotency patterns, adapted to a plain docker/binary host (no k3s here). Add `kai-tower-3026-wsl` to a NEW inventory group (e.g. `fleet_reachability_towers`), **NOT** `fleet_reachability` (keep it out of the pair's group + out of `sync.yml`, so the fleet-converge timer never fires it). ### Part B - Windows-native (HARD; likely needs the Windows-automation foundation first) Author the role to install `gatus.exe` as a Windows service (winsw / NSSM / scheduled task) via ansible **WinRM**, consuming `gatus-kai-tower-3026.yaml`. **Caveat the agent must respect:** the fleet has NO Windows-native ansible precedent yet (Windows agent-stack convergence is #356, still open). If the WinRM connection / Windows-service foundation isn't in place, do **not** invent a fragile one-off - author the role + inventory wiring as far as is sound, then **stop and comment** describing exactly what Windows foundation is missing (WinRM listener, auth, service-wrapper choice) and link #356. Part A should not block on Part B. ## Out of scope / guardrails - No live apply. Live rollout (esp. the Windows service) needs a human on/at the tower or a working WinRM path - flag it, don't fake it. - Do NOT add telegram alerts to the tower (no-page node). - Do NOT add the tower hosts to the `fleet_reachability` group or to `sync.yml`. - Public-safe: short names (`kai-tower-3026`, `ser8`, `kai-server`) only; any opaque FQDN/IP via SSM. ## Acceptance - WSL role: `ansible-lint` + `--syntax-check` pass; `--check` dry-run is clean; idempotent; documented apply command in the role README. - Windows role: authored as far as the existing foundation allows, with a clear comment on what's blocked and why (link #356) if it can't be completed. - `pre-commit` passes. Runbook (`docs/fleet-reachability.md`) updated with the tower apply steps + the confirm-before-apply expectation. Refs: #255 (design), #356 (Windows agent-stack convergence - likely prerequisite for Part B), fleet.yml extension point, coilyco-bridge/deploy services/fleet-reachability.
Author
Member

🔒 Reserved by ward agent --driver claude — container ward-infrastructure-issue-398-claude-d72653a6 on host kais-macbook-pro-2.local is carrying this issue (reserved 2026-06-24T06:45:47Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `ward-infrastructure-issue-398-claude-d72653a6` on host `kais-macbook-pro-2.local` is carrying this issue (reserved 2026-06-24T06:45:47Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Owner

Landed on main as merge fa29e97 (feature c8b1996); CI lint + secret-scan green.

Part A (WSL, kai-tower-3026-wsl) - DONE. New sibling role fleet-reachability-tower + playbooks/fleet-reachability-tower.yml roll a host-level Linux Gatus container (ghcr.io/twin/gatus:latest, network_mode: host + NET_RAW mirroring the k3s pod's hostNetwork + NET_RAW) onto the WSL host over the existing ssh hop, consuming config/gatus-kai-tower-3026-wsl.yaml copied verbatim from the bundle checkout. No-page node (no telegram). Added the NEW fleet_reachability_towers inventory group (NOT fleet_reachability, NOT in sync.yml, never fired by the converge timer). Validated: --syntax-check + a local --check dry-run pass (4 ok, 11 host-touching tasks skipped, 0 failed), idempotent. Apply command + confirm-before-apply in docs/fleet-reachability-towers.md and the role README.

Part B (Windows-native, kai-tower-3026) - AUTHORED-BUT-BLOCKED on #356. Role fleet-reachability-tower-win is authored as far as is sound: it would install gatus.exe as a Windows service (NSSM wrapper) via ansible WinRM, consuming config/gatus-kai-tower-3026.yaml. It is an unverified draft, NOT live-applied - wired to no playbook, host absent from inventory. The fleet has no Windows-native ansible foundation yet, so before this can run, #356 (Windows agent-stack convergence) must land:

  1. a WinRM listener on kai-tower-3026 (HTTPS, a cert, the firewall rule);
  2. auth + connection vars for user firem (credentials via SSM, never tracked);
  3. a settled service-wrapper choice (NSSM vs winsw vs scheduled task).

Part A does not block on Part B. Picked the Windows draft back up once #356 lands the listener/auth/wrapper. Detail: docs/fleet-reachability-towers.md Part B.

Landed on `main` as merge `fa29e97` (feature `c8b1996`); CI lint + secret-scan green. **Part A (WSL, `kai-tower-3026-wsl`) - DONE.** New sibling role `fleet-reachability-tower` + `playbooks/fleet-reachability-tower.yml` roll a host-level Linux Gatus container (`ghcr.io/twin/gatus:latest`, `network_mode: host` + `NET_RAW` mirroring the k3s pod's hostNetwork + NET_RAW) onto the WSL host over the existing ssh hop, consuming `config/gatus-kai-tower-3026-wsl.yaml` copied verbatim from the bundle checkout. No-page node (no telegram). Added the NEW `fleet_reachability_towers` inventory group (NOT `fleet_reachability`, NOT in `sync.yml`, never fired by the converge timer). Validated: `--syntax-check` + a local `--check` dry-run pass (4 ok, 11 host-touching tasks skipped, 0 failed), idempotent. Apply command + confirm-before-apply in `docs/fleet-reachability-towers.md` and the role README. **Part B (Windows-native, `kai-tower-3026`) - AUTHORED-BUT-BLOCKED on #356.** Role `fleet-reachability-tower-win` is authored as far as is sound: it would install `gatus.exe` as a Windows service (NSSM wrapper) via ansible WinRM, consuming `config/gatus-kai-tower-3026.yaml`. It is an **unverified draft, NOT live-applied** - wired to no playbook, host absent from inventory. The fleet has no Windows-native ansible foundation yet, so before this can run, #356 (Windows agent-stack convergence) must land: 1. a **WinRM listener** on kai-tower-3026 (HTTPS, a cert, the firewall rule); 2. **auth + connection vars** for user `firem` (credentials via SSM, never tracked); 3. a settled **service-wrapper** choice (NSSM vs winsw vs scheduled task). Part A does not block on Part B. Picked the Windows draft back up once #356 lands the listener/auth/wrapper. Detail: `docs/fleet-reachability-towers.md` Part B.
Sign in to join this conversation.
No description provided.