docs: migrate workflow to DooPlex-local execution

This commit is contained in:
2026-07-19 12:16:52 +02:00
parent 13af252907
commit ee48a48288
7 changed files with 250 additions and 67 deletions
+1 -2
View File
@@ -36,9 +36,8 @@ The core rule. A guessed `wget` probe ENOENTs at runtime and the container flaps
inspection). On the demo guest:
```bash
SSH=/c/Windows/System32/OpenSSH/ssh.exe; export MSYS_NO_PATHCONV=1
for t in wget curl node python3; do
echo "$t: $($SSH felhom-pve "pct exec 9201 -- docker run --rm --entrypoint sh <image>:<tag> -c 'command -v $t'" 2>/dev/null | tr -d '\r')"
echo "$t: $(ssh felhom-pve "pct exec 9201 -- docker run --rm --entrypoint sh <image>:<tag> -c 'command -v $t'" 2>/dev/null | tr -d '\r')"
done
```
+37 -29
View File
@@ -5,24 +5,32 @@ description: Build, deploy, publish, or verify ANY Felhom artifact — felhom-co
# Felhom build & deploy runbooks
All repos live in `E:\git\` (Git Bash: `/e/git/`). Trunk-based: commit+push to `main` first, always.
**Claude Code runs on DooPlex (192.168.0.180, Debian 13, `kisfenyo`) — builds are LOCAL commands.**
All repos live under `$FELHOM_ROOT/git/`. Trunk-based: commit+push to `main` first, always.
Update the repo's `CHANGELOG.md` (+ `REUSE.md` if a shared helper changed) in the same commit.
## Session invariants (set once, every session)
```bash
SSH=/c/Windows/System32/OpenSSH/ssh.exe # Git Bash's /usr/bin/ssh can't reach the Windows agent — fails silently
export MSYS_NO_PATHCONV=1 # before any ssh felhom-pve command with absolute paths (pct etc.)
FELHOM_ROOT=/mnt/5_hdd/felhom.eu # build-server working root — ALL felhom repos/build/drill/iso live HERE
# (moved off the SSD 2026-07-18; expands locally into the "…" SSH strings below)
FELHOM_ROOT=/mnt/5_hdd/felhom.eu # working root — ALL felhom repos/build/drill/iso live HERE
# repos $FELHOM_ROOT/git/felhom-*, build dirs $FELHOM_ROOT/build/felhom-*
```
> **Clean-tree gate before any build:** `git status --porcelain` must be empty and
> `git rev-parse HEAD` must equal `git rev-parse origin/main` in the repo being built. An unpushed
> change does not exist — never build a dirty or unpushed tree. The `git pull` in the build step
> stays (it is a no-op when you work in this tree, and load-bearing if anything was pushed from
> elsewhere).
| Host | Access | Role |
|---|---|---|
| Build server (k3s) | `$SSH kisfenyo@192.168.0.180` | build+push images/binaries (`$FELHOM_ROOT/build/felhom-{controller,hub,agent}`, repos under `$FELHOM_ROOT/git/`), `sudo kubectl` |
| Demo Proxmox host | `$SSH felhom-pve` (root@192.168.0.162) | agent deploy, `pct` into guests |
| Demo guest 9201 | via `pct exec 9201 -- bash -c '...'` on felhom-pve | the live controller |
| felhotest (legacy) | `$SSH -p 33022 kisfenyo@router.abonet.hu` | OLD /opt/docker compose mechanism — not the 9201 flow |
| **DooPlex (this host, k3s)** | local | build+push images/binaries (`$FELHOM_ROOT/build/felhom-{controller,hub,agent}`, repos under `$FELHOM_ROOT/git/`), `sudo kubectl` |
| Demo Proxmox host | `ssh felhom-pve` (root@192.168.0.162) | agent deploy, `pct` into guests |
| Demo guest 9201 | via `ssh felhom-pve "pct exec 9201 -- bash -c '...'"` | the live controller |
| felhotest (legacy) | `ssh -p 33022 kisfenyo@router.abonet.hu` | OLD /opt/docker compose mechanism — not the 9201 flow |
**No browser here:** `claude-in-chrome` is not available on DooPlex. Validate at the endpoint level
(invoke the exact endpoint the UI invokes) and say which method was used.
Version bumps are ldflags-only (`-X main.version` / `-X main.Version`) — build scripts inject them; no source edit.
@@ -32,13 +40,13 @@ Version bumps are ldflags-only (`-X main.version` / `-X main.Version`) — build
the tag written in `/etc/felhom-controller-image` (anonymous Gitea pull). Data volume + encryption key persist.
```bash
# 1. commit+push the repo
# 2. build+push image (build.sh does NOT git-pull — the explicit pull is load-bearing)
$SSH kisfenyo@192.168.0.180 "cd $FELHOM_ROOT/build/felhom-controller && git -C $FELHOM_ROOT/git/felhom-controller pull && ./build.sh <VER> --push"
# 1. commit+push the repo (clean-tree gate above)
# 2. build+push image, LOCAL (build.sh does NOT git-pull — the explicit pull is load-bearing)
cd $FELHOM_ROOT/build/felhom-controller && git -C $FELHOM_ROOT/git/felhom-controller pull && ./build.sh <VER> --push
# 3. deploy in the guest
$SSH felhom-pve "pct exec 9201 -- bash -c 'docker pull gitea.dooplex.hu/admin/felhom-controller:<VER> && echo gitea.dooplex.hu/admin/felhom-controller:<VER> > /etc/felhom-controller-image && systemctl restart felhom-controller-bootstrap.service'"
ssh felhom-pve "pct exec 9201 -- bash -c 'docker pull gitea.dooplex.hu/admin/felhom-controller:<VER> && echo gitea.dooplex.hu/admin/felhom-controller:<VER> > /etc/felhom-controller-image && systemctl restart felhom-controller-bootstrap.service'"
# 4. verify
$SSH felhom-pve "pct exec 9201 -- docker ps --filter name=felhom-controller --format '{{.Image}} {{.Status}}'"
ssh felhom-pve "pct exec 9201 -- docker ps --filter name=felhom-controller --format '{{.Image}} {{.Status}}'"
```
Check current live version first: same `docker ps` command, or `cat /etc/felhom-controller-image`.
@@ -49,19 +57,19 @@ Runs as the NON-ROOT `felhom-agent` user: `/usr/local/bin/felhom-agent --config
(systemd `felhom-agent.service`). Sudoers allowlist at `/etc/sudoers.d/felhom-agent`.
```bash
# build on 180 (pull first!)
$SSH kisfenyo@192.168.0.180 "cd $FELHOM_ROOT/git/felhom-agent && git pull && go build -ldflags '-X main.version=<VER>' -o /tmp/felhom-agent-<VER> ./cmd/felhom-agent"
# fetch to local, then push to the PVE host (Windows scp needs cygpath -w for the LOCAL path)
scp kisfenyo@192.168.0.180:/tmp/felhom-agent-<VER> "$(cygpath -w /tmp/felhom-agent-<VER>)"
scp "$(cygpath -w /tmp/felhom-agent-<VER>)" felhom-pve:/tmp/
# build LOCALLY (pull first!)
cd $FELHOM_ROOT/git/felhom-agent && git pull && go build -ldflags '-X main.version=<VER>' -o /tmp/felhom-agent-<VER> ./cmd/felhom-agent
# copy to the PVE host — ONE hop, no intermediate workstation
scp /tmp/felhom-agent-<VER> felhom-pve:/tmp/
# install with backup + restart
$SSH felhom-pve "cp /usr/local/bin/felhom-agent /usr/local/bin/felhom-agent.bak-\$(/usr/local/bin/felhom-agent --version | awk '{print \$2}') && install -m0755 /tmp/felhom-agent-<VER> /usr/local/bin/felhom-agent && systemctl restart felhom-agent && sleep 3 && /usr/local/bin/felhom-agent --version && journalctl -u felhom-agent -n 20 --no-pager"
ssh felhom-pve "cp /usr/local/bin/felhom-agent /usr/local/bin/felhom-agent.bak-\$(/usr/local/bin/felhom-agent --version | awk '{print \$2}') && install -m0755 /tmp/felhom-agent-<VER> /usr/local/bin/felhom-agent && systemctl restart felhom-agent && sleep 3 && /usr/local/bin/felhom-agent --version && journalctl -u felhom-agent -n 20 --no-pager"
```
**Ship the sudoers + guarded-mkfs wrapper WITH the binary whenever `configs/` changed** — several Go
guards exist only if the deployed sudoers/wrapper match the binary (globs must match `stageTemp`
patterns). Beware CRLF when scp-ing config files through Windows. After restart, check the journal
for a clean `ReassertGuestBinds` and no capability-probe degradations.
patterns). After restart, check the journal for a clean `ReassertGuestBinds` and no capability-probe
degradations. (Legacy Windows workstation: the copy was two hops via the Windows box, needing
`cygpath -w` for the local scp path — and config files scp'd through Windows risked CRLF.)
Publish to Gitea (so Day-0 self-install can fetch it): `scripts/publish-agent.sh <ver> <binary>` with
`REGISTRY_*` creds. The hub's Day-0 artifact manifest must then vouch the new version — that UI is
@@ -74,21 +82,21 @@ operator-password-gated (CC cannot); flag it as an operator follow-up.
(reverted on next sync), never `:latest`. The live image can lag the CHANGELOG — reconcile via the manifest.
```bash
# 1. commit+push code 2. build+push image
$SSH kisfenyo@192.168.0.180 "cd $FELHOM_ROOT/build/felhom-hub && ./build.sh <VER> --push"
# 1. commit+push code 2. build+push image (LOCAL)
cd $FELHOM_ROOT/build/felhom-hub && ./build.sh <VER> --push
# 3. bump manifests/hub.yaml image tag → <VER>, commit, push
# 4. hard-refresh + sync (argocd CLI on 180 is not logged in — drive the Application CR)
$SSH kisfenyo@192.168.0.180 "sudo kubectl -n argocd annotate application felhom argocd.argoproj.io/refresh=hard --overwrite; sleep 8; sudo kubectl -n argocd get application felhom -o jsonpath='{.status.sync.status} {.status.sync.revision}{\"\n\"}'"
$SSH kisfenyo@192.168.0.180 "sudo kubectl -n argocd patch application felhom --type merge -p '{\"operation\":{\"initiatedBy\":{\"username\":\"cc\"},\"sync\":{\"syncStrategy\":{\"apply\":{}}}}}'"
# 4. hard-refresh + sync (argocd CLI is not logged in — drive the Application CR)
sudo kubectl -n argocd annotate application felhom argocd.argoproj.io/refresh=hard --overwrite; sleep 8; sudo kubectl -n argocd get application felhom -o jsonpath='{.status.sync.status} {.status.sync.revision}{"\n"}'
sudo kubectl -n argocd patch application felhom --type merge -p '{"operation":{"initiatedBy":{"username":"cc"},"sync":{"syncStrategy":{"apply":{}}}}}'
# 5. verify: Synced/Healthy + rollout + image tag + startup log
$SSH kisfenyo@192.168.0.180 "sudo kubectl -n argocd get application felhom -o jsonpath='sync={.status.sync.status} health={.status.health.status}{\"\n\"}'; sudo kubectl -n felhom-system rollout status deploy/hub --timeout=90s; sudo kubectl -n felhom-system get deploy hub -o jsonpath='{.spec.template.spec.containers[0].image}'; echo; sudo kubectl -n felhom-system logs -l app=hub --tail 10"
sudo kubectl -n argocd get application felhom -o jsonpath='sync={.status.sync.status} health={.status.health.status}{"\n"}'; sudo kubectl -n felhom-system rollout status deploy/hub --timeout=90s; sudo kubectl -n felhom-system get deploy hub -o jsonpath='{.spec.template.spec.containers[0].image}'; echo; sudo kubectl -n felhom-system logs -l app=hub --tail 10
```
Green gate before any hub commit: `go build ./... && go vet ./... && go test ./...` in `hub/`.
## Website (felhom.eu/website)
Push to `main` = deployed (git-sync sidecar, live in ~12 min). **Run `python scripts/site_gates.py`
Push to `main` = deployed (git-sync sidecar, live in ~12 min). **Run `python3 scripts/site_gates.py`
first, after ANY website change** (BOM, emoji, nav parity, cache-bust `?v=N` — bump it when css/svg
change). New pages must be added to the script's `PAGES` list. Emergency edits: https://files.felhom.eu.
+2 -2
View File
@@ -34,8 +34,8 @@ Files: `website/assets/site.css`, `hub/internal/web/templates/style.css`,
website sections are boxless (rules + spacing, not cards).
- **Two-tone H1:** last word wrapped in `<span>` (renders `--blue-bright`). H1 only — never H2+.
- **Icons:** monochrome sprite (`icons.svg`, `<use href="...#name">`) / Lucide-style. **No emoji
anywhere** — enforced by gates; never hunt emoji with grep (Windows grep false-negatives multibyte;
Python gates only).
anywhere** — enforced by gates; never hunt emoji with grep (proven to false-negative multibyte on
the Windows workstation, and grep was never the sanctioned check regardless — Python gates only).
- **Fonts:** vendored woff2 (latin-ext for Hungarian) — **no CDN fonts** (gate-enforced on the website).
- **Language:** Hungarian for everything customer-facing (controller UI, customer emails); English for
operator surfaces (hub UI, operator alerts). Hungarian text lives in maps like `severityLabels` /