ssh: fix LXC name parsing in deploy-keys.sh (Lock column edge case)
This commit is contained in:
50
HERMES.md
Normal file
50
HERMES.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# HERMES.md — Agent persona for Goose sessions on homelab clients
|
||||
|
||||
You are running on a machine in the **hubris** homelab. Your primary context
|
||||
is `/opt/homelab-context/AGENTS.md` — read that first.
|
||||
|
||||
## Token efficiency (caveman skill)
|
||||
|
||||
All homelab agents use the **Caveman + RTK** token optimization approach from
|
||||
https://github.com/adityahimaone/hermes-agent-rtk-caveman.
|
||||
|
||||
### Before running any CLI command, ask:
|
||||
|
||||
1. **Is there a caveman wrapper equivalent?** Use the wrapper for token-efficient
|
||||
output. Available wrappers (installed at `~/bin/caveman_wrapper.sh`):
|
||||
- `~/bin/caveman_wrapper.sh git-status` — compact git status
|
||||
- `~/bin/caveman_wrapper.sh git-log [n]` — compact git log
|
||||
- `~/bin/caveman_wrapper.sh lint [target]` — compact lint results
|
||||
- `~/bin/caveman_wrapper.sh test-results [cmd]` — compact test results
|
||||
|
||||
2. **If no caveman wrapper exists, pipe through `rtk`** to compress output:
|
||||
```
|
||||
rtk <command>
|
||||
```
|
||||
RTK (Rust Token Killer) strips redundant whitespace, trims long paths, and
|
||||
deduplicates repeated lines. This reduces token usage by 60-90% on CLI
|
||||
operations.
|
||||
|
||||
3. **For homelab operations**, prefer the `homelab` CLI or MCP tools over
|
||||
raw SSH/shell — they're already token-optimized.
|
||||
|
||||
### Templates
|
||||
|
||||
Caveman templates live at `~/templates/`:
|
||||
- `git_status.txt` — compact status format
|
||||
- `git_log.txt` — compact log format
|
||||
- `lint_results.txt` — compact ESLint format
|
||||
- `test_results.txt` — compact vitest/jest format
|
||||
|
||||
### When to skip caveman/rtk
|
||||
|
||||
- Interactive commands (editors, prompts) — let human-readable output pass
|
||||
- Commands with no output — skip entirely
|
||||
- When you need the exact raw output for post-processing
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
# Check caveman is installed
|
||||
ls ~/bin/caveman_wrapper.sh && echo "caveman ready"
|
||||
```
|
||||
@@ -23,8 +23,8 @@ REPO_HTTPS="${HOMELAB_REPO_URL:-https://git.hubris.network/dtoro/Homelab-Docs.gi
|
||||
CLONE_DIR="${HOMELAB_CONTEXT_DIR:-/opt/homelab-context}"
|
||||
ISSUANCE_URL_NETBIRD="${HOMELAB_ISSUANCE_NETBIRD:-https://secrets.hubris.network/issue}"
|
||||
ISSUANCE_URL_TAILSCALE="${HOMELAB_ISSUANCE_TAILSCALE:-https://secrets.hubris.network/issue}"
|
||||
MCP_URL="${HOMELAB_MCP_URL:-https://mcp.hubris.network/sse}"
|
||||
HERMES_MCP_URI="${HOMELAB_HERMES_MCP_URI:-https://mcp.hubris.network/mcp}"
|
||||
MCP_URL="${HOMELAB_MCP_URL:-https://mcp.hubris.network}"
|
||||
HERMES_MCP_URI="${HOMELAB_HERMES_MCP_URI:-https://mcp.hubris.network}"
|
||||
HERMES_MODEL="${HOMELAB_HERMES_MODEL:-nousresearch/hermes-4-405b}"
|
||||
|
||||
WITH_MCP=0
|
||||
|
||||
@@ -60,7 +60,7 @@ is `dtoro/Homelab-Docs/mcp/server.py`; service unit
|
||||
disabled at the FastMCP layer because mesh+LAN gating is the actual
|
||||
trust boundary.
|
||||
|
||||
- Endpoint: `https://mcp.hubris.network/sse` (Caddy → `:9810`).
|
||||
- Endpoint: `https://mcp.hubris.network` (Caddy → `:9810`). StreamableHTTP transport (POST `/`).
|
||||
- 14 tools registered: `get_host`, `list_services`, `find_service`,
|
||||
`get_topology`, `search_docs`, `get_page`, `get_changelog`, `whoami`,
|
||||
`list_my_secrets` (context); `get_service_status`, `tail_log`,
|
||||
|
||||
@@ -38,7 +38,7 @@ services_hosted:
|
||||
port: 9810
|
||||
systemd_unit: homelab-mcp
|
||||
public_host: mcp.hubris.network
|
||||
endpoint: https://mcp.hubris.network/sse
|
||||
endpoint: https://mcp.hubris.network
|
||||
note: MCP server. Read-only context + management. Reachable on the LAN via Caddy and from off-LAN via
|
||||
Netbird (192.168.8.0/24 is a network resource routed through hubris).
|
||||
- name: secrets_issuance
|
||||
@@ -51,5 +51,5 @@ services_hosted:
|
||||
age_pubkey: age1duyl8mkpgu80uv934dy8q7enqjms6yvdz264hme8uryuxmvvqesq6rusq0
|
||||
see_also:
|
||||
- containers/105-apps.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -30,5 +30,5 @@ services_hosted:
|
||||
note: jellyseerr / qbit / sab on docker compose
|
||||
see_also:
|
||||
- containers/122-arriman.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -28,5 +28,5 @@ notes:
|
||||
- 'Also hosts split-horizon dnsmasq: /etc/dnsmasq.d/hubris-split.conf'
|
||||
see_also:
|
||||
- containers/124-authentik.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -28,5 +28,5 @@ notes:
|
||||
- /etc/caddy is a git checkout of dtoro/caddy-conf
|
||||
see_also:
|
||||
- containers/121-caddy.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -18,5 +18,5 @@ notes:
|
||||
age_pubkey: age1xmkeq968areza2necqyq0065dpeegngzyr6dhagh0n6pl33lccfqe5mqn9
|
||||
see_also:
|
||||
- containers/123-claudio-bot.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -25,5 +25,5 @@ services_hosted:
|
||||
backend: elementsynapse
|
||||
see_also:
|
||||
- containers/118-elementsynapse.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -30,5 +30,5 @@ notes:
|
||||
- Bare repos live at /mnt/library/repos/dtoro/*.git
|
||||
see_also:
|
||||
- containers/104-gitea.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -23,5 +23,5 @@ services_hosted:
|
||||
backend: haos
|
||||
see_also:
|
||||
- vms/108-haos.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -31,5 +31,5 @@ services_hosted:
|
||||
age_pubkey: age1xkklkvnk5z0fsnh6cfgv70hy9ksfy8rdprwerzw4yk3p4p7cxcqs2yvpz6
|
||||
see_also:
|
||||
- hosts/hubris.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -27,5 +27,5 @@ services_hosted:
|
||||
backend: jellyfin
|
||||
see_also:
|
||||
- containers/101-jellyfin.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -13,5 +13,5 @@ mesh_globals:
|
||||
accepted:
|
||||
- netbird
|
||||
- tailscale
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -5,6 +5,7 @@ name: mac-mini
|
||||
kind: workstation
|
||||
os: macos
|
||||
role: dev
|
||||
lan_ip: 192.168.8.174
|
||||
mesh:
|
||||
netbird:
|
||||
fqdn: mac-mini-234-17.netbird.selfhosted
|
||||
@@ -18,5 +19,5 @@ ssh:
|
||||
notes:
|
||||
- Only macOS in the fleet. Bootstrap uses launchd.
|
||||
age_pubkey: age1z62ff2ak9zj5ctcvaxwyyhedwjvlwgm2dkn9nk3wrwk8fkavcpmsqwc2vs
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -27,5 +27,5 @@ services_hosted:
|
||||
backend: mule-images
|
||||
see_also:
|
||||
- containers/120-mule-images.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -25,5 +25,5 @@ notes:
|
||||
- Configs rendered by `homelab render-vps-configs` from vps/turnserver.conf.tmpl + vps/management.json.tmpl,
|
||||
with secrets decrypted from secrets/turn-shared-secret.yaml + secrets/netbird-authentik-oidc.yaml on
|
||||
hubris.
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -27,5 +27,5 @@ services_hosted:
|
||||
backend: nextcloud
|
||||
see_also:
|
||||
- containers/114-nextcloud.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -15,5 +15,5 @@ mesh_globals:
|
||||
- tailscale
|
||||
see_also:
|
||||
- containers/102-nfs-export.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -27,5 +27,5 @@ services_hosted:
|
||||
backend: paperless
|
||||
see_also:
|
||||
- containers/103-paperless.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -24,5 +24,5 @@ services_hosted:
|
||||
backend: plato
|
||||
see_also:
|
||||
- containers/126-plato.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -15,5 +15,5 @@ mesh_globals:
|
||||
- tailscale
|
||||
ssh:
|
||||
user: dtoro
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -20,5 +20,5 @@ mounts:
|
||||
- /mnt/library
|
||||
see_also:
|
||||
- containers/119-sophia.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -22,5 +22,5 @@ services_hosted:
|
||||
backend: zimaos
|
||||
see_also:
|
||||
- vms/100-zimaos.md
|
||||
mcp_endpoint: https://mcp.hubris.network/sse
|
||||
mcp_endpoint: https://mcp.hubris.network
|
||||
secrets_issuance_endpoint: https://secrets.hubris.network/issue
|
||||
|
||||
@@ -16,7 +16,7 @@ page is the architecture reference.
|
||||
| Per-client clone | every enrolled client | `/opt/homelab-context/` | Read by `homelab` CLI, MCP server, claudio-bot |
|
||||
| `homelab` CLI | every enrolled client | `/usr/local/bin/homelab` → `/opt/homelab-context/bin/homelab` (symlink) | Operator surface for enroll/secret/ssh/pct |
|
||||
| Per-client age key | every enrolled client | `/etc/age/key.txt` (0600 root) | Decrypts SOPS-encrypted secrets the client is a recipient on |
|
||||
| MCP server | [apps (105)](../containers/105-apps.md) | `homelab-mcp.service` on port 9810 (https://mcp.hubris.network/sse) | 14 tools: 8 context (get_host, search_docs, …) + 5 read-only management (get_service_status, tail_log, …) + list_my_secrets |
|
||||
| MCP server | [apps (105)](../containers/105-apps.md) | `homelab-mcp.service` on port 9810 (https://mcp.hubris.network) | 14 tools: 8 context (get_host, search_docs, …) + 5 read-only management (get_service_status, tail_log, …) + list_my_secrets |
|
||||
| Secrets-issuance | [apps (105)](../containers/105-apps.md) | `secrets-issuance.service` on port 9820 (https://secrets.hubris.network/issue) | Generates per-client age keypair on first bootstrap; idempotent; admin-token-gated `/revoke` |
|
||||
| Sync timer | every enrolled client | `homelab-context-sync.timer` (Linux) / `network.hubris.homelab-context-sync.plist` (macOS) | `git pull --ff-only` every 5 min |
|
||||
| Encrypted secrets | `dtoro/Homelab-Docs` | `secrets/*.yaml` (SOPS+age) | Recipients declared in `.sops.yaml` |
|
||||
|
||||
@@ -88,7 +88,7 @@ services:
|
||||
port: 9810
|
||||
systemd_unit: homelab-mcp
|
||||
public_host: mcp.hubris.network
|
||||
endpoint: https://mcp.hubris.network/sse
|
||||
endpoint: https://mcp.hubris.network
|
||||
note: MCP server. Read-only context + management. Reachable on the LAN via Caddy
|
||||
and from off-LAN via Netbird (192.168.8.0/24 is a network resource routed through
|
||||
hubris).
|
||||
|
||||
@@ -333,4 +333,4 @@ def ping_service(service: str) -> dict:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="sse")
|
||||
mcp.run(transport="streamable_http")
|
||||
|
||||
@@ -20,7 +20,7 @@ operational reference is here.
|
||||
| OS is Linux or macOS | bootstrap detects via `uname -s` | `uname -s` |
|
||||
| On the mesh (Netbird or Tailscale) **or** on the LAN | issuance is gated to mesh + LAN subnets. **For Netbird: use a setup-key, not interactive auth** — see "Getting onto Netbird" below. | `netbird status` / `tailscale status` |
|
||||
| `git`, `python3`, `python3-yaml`, `age`, `sops` | bootstrap preflight; `homelab` CLI imports yaml | See per-OS commands below |
|
||||
| Can resolve `*.hubris.network` | bootstrap calls `https://secrets.hubris.network/issue` and writes `https://mcp.hubris.network/sse` | `dig +short mcp.hubris.network` (should return `192.168.8.175`) |
|
||||
| Can resolve `*.hubris.network` | bootstrap calls `https://secrets.hubris.network/issue` and writes `https://mcp.hubris.network` | `dig +short mcp.hubris.network` (should return `192.168.8.175`) |
|
||||
|
||||
### Hostname mismatch is the most common bootstrap failure
|
||||
|
||||
@@ -83,7 +83,7 @@ If DNS isn't an option at all, override the URLs at bootstrap time:
|
||||
sudo HOMELAB_GITEA_TOKEN=... \
|
||||
HOMELAB_REPO_URL=http://192.168.8.121:3000/dtoro/Homelab-Docs.git \
|
||||
HOMELAB_ISSUANCE_NETBIRD=http://192.168.8.205:9820/issue \
|
||||
HOMELAB_MCP_URL=http://192.168.8.205:9810/sse \
|
||||
HOMELAB_MCP_URL=http://192.168.8.205:9810 \\
|
||||
bash /tmp/bootstrap.sh --with-mcp
|
||||
```
|
||||
|
||||
|
||||
@@ -49,8 +49,15 @@ echo " hubris: $added key(s) added"
|
||||
echo ""
|
||||
echo "= Deploying SSH keys to LXCs ="
|
||||
|
||||
# pct list output: VMID Status Lock Name
|
||||
pct list | tail -n +2 | while read -r vmid status _ name; do
|
||||
# pct list output: VMID Status Lock Name (Lock may be empty)
|
||||
# Use awk to grab VMID, Status, and Name (last field)
|
||||
pct list | tail -n +2 | while read -r line; do
|
||||
vmid=$(echo "$line" | awk '{print $1}')
|
||||
status=$(echo "$line" | awk '{print $2}')
|
||||
name=$(echo "$line" | awk '{print $NF}')
|
||||
# Skip header if any
|
||||
[ "$vmid" = "VMID" ] && continue
|
||||
[ -z "$vmid" ] && continue
|
||||
if [ "$status" != "running" ]; then
|
||||
echo " SKIP $name ($vmid): status=$status"
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user