From f7a8b668d3480a1ea8e2d3698f8451d44df1e7c8 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Fri, 24 Apr 2026 16:31:41 -0700 Subject: [PATCH] paperwork: refresh STATUS.md + CLAUDE.md; finalize 4b MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STATUS.md: - Mark 4b done (both Postgres migration + NFS decoupling) - Add arch decisions for gitea remote + prefer-elway policy - Add tooling entries for elway + tea CLI - Document 2026-04-24 session milestones (irv-ml1 AI stacks, elway, task-board, 4b finish) - Expand memory-pointer list with the files added this session CLAUDE.md: - Tell new sessions to use elway for SSH-driven work, point at the smoke playbook template - Document the task-board plugin + MCP-tool contract so assistant sessions with the plugin enabled know the assistant should call task_start / task_update / task_wait / task_complete at meaningful checkpoints .claude/settings.json: - Project-level env: TASK_BOARD_SESSION=Infra so every Claude Code session opened here labels its task-board cards "Infra" playbooks/decouple-pfi-postgres-from-ana-nas.yaml: - Finishes the DB-off-NFS migration on pfi-postgres. Already ran against prod today; fstab clean, unmounted, no systemd mnt-db unit. Verify 3 was mis-expressed on first run (`grep -q active` matched "inactive") — fixed to invert systemctl exit code directly. --- .claude/settings.json | 5 + CLAUDE.md | 29 ++- STATUS.md | 245 ++++++++++++------ .../decouple-pfi-postgres-from-ana-nas.yaml | 95 +++++++ 4 files changed, 297 insertions(+), 77 deletions(-) create mode 100644 .claude/settings.json create mode 100644 playbooks/decouple-pfi-postgres-from-ana-nas.yaml diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..a61efac --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "env": { + "TASK_BOARD_SESSION": "Infra" + } +} diff --git a/CLAUDE.md b/CLAUDE.md index ab6777b..ca7d6af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,24 @@ This workspace is for managing PFI infrastructure — servers, Docker stacks, and related configs. Spawn a dedicated Claude Code session here when working on infra so it doesn't clutter AIPA-MCP development context. +**New session starting here?** Read [`docs/orientation.md`](docs/orientation.md) first — fleet topology, backup architecture, governing principles, and all the NFS/DSM/naming gotchas that have cost past sessions time. + +**For SSH-driven work: use `scripts/elway`.** Write a playbook under +`playbooks/.yaml` and run +`scripts/elway --playbook ...` instead of chaining +`ssh -t host 'sudo …'` commands — handles sudo once lazily, +structured pass/change/fail reporting, idempotency via +`creates:` / `when:` / `changed_when:`. Template: +[`playbooks/elway-smoke.yaml`](playbooks/elway-smoke.yaml). + +**Task visibility via task-board.** If the Claude Code session has +the `task-board` plugin enabled (installed from +`git@gitea.phasefinal.com:vh/task-board.git`), a card at +`http://10.250.50.70:7878/` tracks work in progress. Hooks flip the +card on turn boundaries automatically; call `task_start` / +`task_update` / `task_wait` / `task_complete` MCP tools to set the +activity subheader and post meaningful log entries. + ## Purpose - Inventory of servers and their state @@ -53,7 +71,8 @@ Observed and standardized across servers: | Name | IP | Site | Role | Details | |------|-----|------|------|---------| -| ana-ml2 | 10.250.50.54 | Anaheim (`10.250.0.0/16`) | GPU / AI inference (bare metal) | `servers/ana-ml2/README.md` | +| ana-ml2 | 10.250.50.54 | Anaheim (`10.250.0.0/16`) | GPU / AI inference (bare metal, dual RTX 6000 Ada) | `servers/ana-ml2/README.md` | +| irv-ml1 | 10.100.79.3 (WG) | Irvine — reachable only via WireGuard tunnel from NH3 | GPU / AI inference (bare metal, RTX 3090 + RTX A6000, native stacks) | `servers/irv-ml1/README.md` | | ana-docker | 10.250.50.70 | Anaheim | General-purpose Docker host (non-GPU VM on pfi-pve) | `servers/ana-docker/README.md` | | pfi-ana-webhost | 10.250.50.52 | Anaheim | VM on pfi-pve (VMID 110) — web workload | `servers/pfi-ana-webhost/README.md` | | ana-filebot | 10.250.50.53 | Anaheim | LXC on pfi-pve (CT 112) — file-task automation | `servers/ana-filebot/README.md` | @@ -62,18 +81,24 @@ Observed and standardized across servers: | pfi-postgres | 10.250.50.80 | Anaheim | VM on pfi-pve (VMID 105) — shared Postgres (vaultwarden/gitea/paperless) | `servers/pfi-postgres/README.md` | | ana-wg | 10.250.50.252 | Anaheim | LXC on pfi-pve (CT 113) — WireGuard | `servers/ana-wg/README.md` | | pfi-pve | 10.250.250.31 | Anaheim | Proxmox VE hypervisor | `servers/pfi-pve/README.md` | +| pbs-ana | 10.250.50.90 | Anaheim | Proxmox Backup Server — fleet primary (VM on pfi-pve, NFS datastore on ana-nas) | `servers/pbs-ana/README.md` | | sfsrv-ana | 10.250.250.115 | Anaheim | **SureFire client (PFI-managed)** — Proxmox VE hypervisor | `servers/sfsrv-ana/README.md` | | sf-ana-container | 10.250.150.100 | Anaheim | **SureFire client (PFI-managed)** — container workload on sfsrv-ana | `servers/sf-ana-container/README.md` | | sf-r630 | iDRAC 10.250.250.110 | Anaheim | **SureFire client (PFI-managed)** — physical Dell R630, iDRAC-managed from PFI side | `servers/sf-r630/README.md` | | nh3-docker | 10.100.50.40 | NH3 (`10.100.0.0/16`) | General-purpose Docker host (non-GPU VM on nh3-pve) | `servers/nh3-docker/README.md` | | nh3-pve | 10.100.250.60 | NH3 | Proxmox VE hypervisor | `servers/nh3-pve/README.md` | +| nh3-nas | 10.100.50.50 | NH3 | Synology RS2418+ — NFS exports, rest-server-nh3, PBS-NH3 datastore backend | `servers/nh3-nas/README.md` | +| pbs-nh3 | 10.100.50.90 | NH3 | Proxmox Backup Server — DR mirror (VM on nh3-pve, NFS datastore on nh3-nas); syncs from pbs-ana | `servers/pbs-nh3/README.md` | | esh-docker-vm | 10.0.50.45 | ESH home lab (`esteban.net`, `10.0.50.0/24`) | Home-lab Docker host (VM on esh-pve) | `servers/esh-docker-vm/README.md` | | vm-esh-nas | 10.0.50.154 | ESH home lab | NAS-adjacent Docker host (VM on esh-pve-nas) | `servers/vm-esh-nas/README.md` | | esh-pve | 10.0.250.35 | ESH home lab | Proxmox VE hypervisor | `servers/esh-pve/README.md` | | esh-pve-nas | 10.0.50.55 | ESH home lab | Proxmox VE hypervisor (storage / media) | `servers/esh-pve-nas/README.md` | +| esh-vm-db | 10.0.50.60 | ESH home lab | DB VM — PostgreSQL (paperless-ng) + MongoDB; bare-metal VM, no Docker | `servers/esh-vm-db/README.md` | **Placement rules:** -- GPU-required stacks → `ana-ml2`. +- GPU-required stacks → `ana-ml2` (primary, Anaheim) or `irv-ml1` + (secondary, Irvine — bigger VRAM ceiling at 72 GB total). Access + to `irv-ml1` requires WireGuard. - Anaheim non-GPU services → `ana-docker`. - NH-site non-GPU services → `nh3-docker`. - ESH home-lab workloads (`esteban.net`) → `esh-docker-vm` (general) or `vm-esh-nas` (needs direct NFS mounts from 10.0.50.50). Not part of the PFI colo topology, but shares monitoring/backup tooling. diff --git a/STATUS.md b/STATUS.md index fe7414c..e412fe1 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,16 +1,23 @@ # Status + Open Issues -Last updated: 2026-04-21 +Last updated: 2026-04-24 Snapshot of fleet state and open work. Refresh this file when a pass of significant work lands — don't let it drift quietly. +**New session? Read [`docs/orientation.md`](docs/orientation.md) first.** + ## What's in place -### Backup coverage +### Backup coverage (2-layer, fully operational) -- **VM-level vzdump:** 24/24 guests across pfi-pve, nh3-pve, esh-pve, esh-pve-nas. -- **File-level restic:** 6/6 hosts configured with systemd timers: +- **PBS fleet-wide.** All 5 hypervisors (pfi-pve, nh3-pve, esh-pve, + esh-pve-nas, sfsrv-ana) → `pbs-ana` (primary, VM on pfi-pve with + NFSv3 datastore on ana-nas). Per-hypervisor namespaces to avoid + VMID collisions. DR mirror at `pbs-nh3` (VM on nh3-pve with NFSv3 + datastore on nh3-nas Synology) pulls daily at 06:00. Verify jobs + armed on both sides. +- **restic 8/8 hosts** with resticprofile + systemd timers at 01:00: | Host | Target rest-server | DB hooks | |---|---|---| | ana-docker | rest-server-ana (local) | synapse, seafile, vaultwarden-pg, gitea (native dump), openwebui | @@ -19,17 +26,48 @@ significant work lands — don't let it drift quietly. | esh-docker-vm | rest-server-ana (cross-site) | paperless-pg, HA SQLite, CWA SQLite, pgadmin SQLite, uptime-kuma SQLite | | vm-esh-nas | rest-server-ana (cross-site) | — | | nh3-dev (workstation) | rest-server-nh3 (local) | — | + | irv-ml1 | rest-server-nh3 (via WG) | — | + | esh-vm-db | rest-server-ana (cross-site) | pg_dumpall, mongodump | +- **Cross-site restic rsync.** `ana-nas → nh3-nas` at 04:00 daily + (mirrors rest-server-ana data). `nh3-nas → ana-nas` at 05:00 daily + (mirrors rest-server-nh3 data, runs as root since DSM writes files + as admin mode 400). Tracked at `configs/rsync/{ana-nas-to-nh3,nh3-nas-to-ana}/`. ### Inventory -- **18 tracked hosts** under `servers/` (5 Docker + 4 Proxmox + 1 workstation + - 6 PFI VMs + 3 SureFire tenant + 1 NH3-dev workstation... audit the actual count - vs this when updating). -- **Homepage** at shows function-first layout with - Main / Infrastructure / Toolchain tabs. Per-group icons, row-count - layout, useEqualHeights. -- **FortiGate + UniFi discovery** scripts produce TSVs; gap analysis - against `servers/*` for unmanaged IPs. +- **~22 tracked hosts** under `servers/` across ANA / NH3 / ESH / IRV sites. + SSH config aliases in `~/.ssh/config` for every host — `ssh ` just works. +- **Homepage** at — function-first layout + (Main / Infrastructure / Toolchain tabs), per-group icons, four + Infra sub-groups (ANA / NH3 / IRV / ESH). Docker auto-discovery + active for 5 hosts (ana-docker, ana-ml2, nh3-docker, esh-docker-vm, + irv-ml1). +- **FortiGate + UniFi discovery scripts** produce TSVs; gap analysis + against `servers/*/` for unmanaged IPs. + +### Architecture decisions (durable) + +- **DB data on local disk, not NFS.** pfi-postgres migrated 2026-04-23; + fstab + NFS mount removed 2026-04-24 (pfi-postgres now fully + decoupled from ana-nas). Mongo on esh-vm-db confirmed already local. + Removes the biggest ana-nas blast-radius risk. Memory: + `project_db_migrate_off_nfs.md`. +- **Backups must not risk production.** Rule adopted after + 2026-04-23 ana-nas self-backup crash. Memory: + `feedback_backups_must_not_risk_production.md`. +- **offen sidecars retired fleet-wide 2026-04-23.** restic covers + equivalent scope; reclaimed 16 GB of redundant tarballs on + `/mnt/backup/docker/esh-vm-docker/`. +- **Gitea remote for this repo (2026-04-23).** `origin` is + `vh/esh-pfi-infrastructure` on `gitea.phasefinal.com`. Also: + `vh/task-board` (new 2026-04-24) hosts a Claude Code plugin + + marketplace serving the assistant task-state dashboard. +- **Prefer elway for multi-step SSH work (2026-04-24).** The new + `scripts/elway` mini-playbook runner replaces chained `ssh -t sudo …` + commands — handles sudo once up front, structured reporting, + idempotency (creates/when/changed_when). Memory: + `feedback_use_elway.md`; template playbook: + `playbooks/elway-smoke.yaml`. ### Tooling @@ -40,29 +78,39 @@ significant work lands — don't let it drift quietly. `scripts/discover-gaps.sh` for network-level inventory discovery. - `scripts/deploy-stack.sh` + `scripts/sync-stacks.sh` for compose push/pull. - `scripts/add-host.sh` for new-host registration. +- **`scripts/elway`** (2026-04-24) — mini-ansible playbook runner over + SSH. Playbooks live under `playbooks/`. Tier 1 (creates/when) + tier + 2 (changed_when) idempotency; handlers + register + multi-host + fan-out deferred as gitea issues #3–#5. +- **`tea` CLI** at `/usr/local/bin/tea` — gitea CLI, already logged in + as `vh`. Use for issue / PR work instead of inventing URLs. ## Open issues ### 🟥 Quick wins (do next) -1. **Fix Backrest's `esh-docker-vm` URI** — Backrest is pointed at - `10.100.50.50` (NH3 Synology) for that repo, while the actual backup - writes go to `10.250.50.70` (rest-server-ana). Edit `config.json` in - the backrest container, swap the host portion. ~5 min. +1. ~~**Fix Backrest's `esh-docker-vm` URI**~~ — done. -2. **Verify SSH on the 9 newly-registered hosts** and pull first snapshots: - ``` - scripts/refresh-server-info.sh --validate-only all - scripts/refresh-server-info.sh pfi-ana-webhost ana-filebot pfi-pteradactyl \ - pfi-tacticalrmm pfi-postgres ana-wg - ``` - ssh-target files were guessed (`lkraven@` for VMs, `root@` for LXCs) — - first run surfaces mismatches. +2. ~~**Push SSH keys + pull snapshots for 6 unrefreshed hosts**~~ — + **done 2026-04-23**. 4 VMs (pfi-ana-webhost, pfi-pteradactyl, + pfi-tacticalrmm, pfi-postgres) took the workstation key via + `ssh-copy-id` with `lkraven@`. 2 LXCs (ana-filebot, ana-wg) + needed key installed via `pct push` from pfi-pve because + `PermitRootLogin prohibit-password` blocked `ssh-copy-id`. + Minor: pfi-pteradactyl's `server_inspect` Docker section is blank + because lkraven is not in the `docker` group there — `sudo usermod + -aG docker lkraven` + re-login to fix. -3. **Patch out `forget` schedules from all 6 restic profiles.** They fail - nightly against `--append-only` rest-servers. One-liner per host: - comment out `schedule:` under the `forget` block in profiles.yaml; - redeploy; run `resticprofile unschedule forget` on each host. ~15 min. +3. ~~**Patch out `forget` schedules from all 6 restic profiles**~~ — done. + +3b. ~~**Discover sf-r630 OS-side IP**~~ — **resolved 2026-04-23**: + the R630 with iDRAC `10.250.250.110` is the same physical box + that runs `sfsrv-ana` (Proxmox VE at `10.250.250.115`). No + separate OS IP to find. `servers/sf-r630/` now clarifies it as + the hardware/BMC-only inventory entry; `servers/sfsrv-ana/` is + the OS view. `servers/ana-ml2/README.md` updated with its own + distinct BMC IP (`10.250.250.50`, Supermicro) to prevent future + confusion between the two physical chassis.