From b65116b84718fb0cfd9599bf27da53a5ec4e1661 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 5 Jul 2026 20:02:20 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20pct-run.sh=20=E2=80=94=20run=20commands?= =?UTF-8?q?=20in=20CTs=20by=20ID,=20no=20IPs=20needed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds /scripts/pct-run.sh that maps CT IDs to PVE nodes and runs pct exec directly. No hardcoded IPs — Proxmox is the source of truth. Updates infrastructure-control with CT access table using pct-run. Usage examples: pct-run 112 cat /etc/hostname # Tanko pct-run 114 grep LITELLM /etc/environment # Mumuni key check pct-run 116 docker ps # LiteLLM containers --- infrastructure-control.prose.md | 30 +++++++++++ scripts/pct-run.sh | 96 +++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100755 scripts/pct-run.sh diff --git a/infrastructure-control.prose.md b/infrastructure-control.prose.md index 0aa8d09..87b555b 100644 --- a/infrastructure-control.prose.md +++ b/infrastructure-control.prose.md @@ -602,3 +602,33 @@ ssh root@192.168.68.110 "systemctl restart llama-server" | docker-vm (.7) | Audiobookshelf | `/opt/audiobookshelf/docker-compose.yml` | | CT 116 (.116) | Inference Harness | `/opt/inference-harness/docker-compose.yml` | | Netbird (.17) | Netbird | Docker run (not compose) | + +## CT Access (pct-run — no IPs needed) + +All CTs are accessible via `pct-run `. No IP addresses required. +Source of truth: `/root/scripts/pct-run.sh` or `prose-contracts/scripts/pct-run.sh`. + +| CT | Name | Node | pct-run | +|-----|------|------|---------| +| 100 | abiba | amdpve | `pct-run 100` | +| 105 | kagentz | amdpve | `pct-run 105` | +| 111 | tdunna | amdpve | `pct-run 111` | +| 112 | tanko | amdpve | `pct-run 112` | +| 113 | baggy/koonimo | amdpve | `pct-run 113` | +| 115 | scottdenya | amdpve | `pct-run 115` | +| 104 | authentik | minipve | `pct-run 104` | +| 110 | gitea | minipve | `pct-run 110` | +| 114 | mumuni | minipve | `pct-run 114` | +| 116 | syslog-api | minipve | `pct-run 116` | +| 106 | ra-h-os | storepve | `pct-run 106` | +| 107 | proxmox-backup | storepve | `pct-run 107` | +| 108 | media | storepve | `pct-run 108` | +| 117 | zulip | storepve | `pct-run 117` | +| 102 | adguard | acerpve | `pct-run 102` | + +GPU bare-metal hosts (.8 acerpve, .110 ocupve, .15 amdpve) are NOT CTs — use SSH directly: +```bash +ssh root@192.168.68.8 # RTX 3090 +ssh root@192.168.68.110 # RTX 5070 +ssh root@192.168.68.15 # Strix Halo +``` diff --git a/scripts/pct-run.sh b/scripts/pct-run.sh new file mode 100755 index 0000000..ad7612c --- /dev/null +++ b/scripts/pct-run.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# pct-run — Run commands inside Proxmox CTs by CT ID only. No IPs needed. +# Usage: pct-run [command...] +# If no command given, opens a shell. +# +# Source of truth: Proxmox pct config on each node. +# No hardcoded IPs. No prose contract drift. + +set -euo pipefail + +# ── CT ID → PVE Node mapping (maintained HERE, not in prose contracts) ── +declare -A CT_NODES=( + # amdpve (192.168.68.15) + [100]=amdpve # abiba + [105]=amdpve # kagentz + [111]=amdpve # tdunna + [112]=amdpve # tanko + [113]=amdpve # baggy/koonimo + [115]=amdpve # scottdenya + # minipve (192.168.68.12) + [104]=minipve # authentik + [110]=minipve # gitea + [114]=minipve # mumuni + [116]=minipve # syslog-api + # storepve (192.168.68.6) + [106]=storepve # ra-h-os + [107]=storepve # proxmox-backup + [108]=storepve # media + [117]=storepve # zulip + # acerpve (192.168.68.9) + [102]=acerpve # adguard + # ocupve (192.168.68.5) — no CTs (bare metal GPU .110) +) + +# Each node must be root-accessible via SSH hostname +# (Ensure ~/.ssh/config or /etc/hosts has these resolvable) + +# ── PVE node → IP (needed only because SSH needs an address) ── +declare -A NODE_IPS=( + [amdpve]=192.168.68.15 + [minipve]=192.168.68.12 + [storepve]=192.168.68.6 + [acerpve]=192.168.68.9 + [ocupve]=192.168.68.5 +) + +resolve_node() { + local ct_id="$1" + local node="${CT_NODES[$ct_id]:-}" + if [[ -z "$node" ]]; then + echo "ERROR: CT $ct_id not found in mapping" >&2 + exit 1 + fi + echo "$node" +} + +node_ip() { + local node="$1" + local ip="${NODE_IPS[$node]:-}" + if [[ -z "$ip" ]]; then + echo "ERROR: Node $node not found in IP mapping" >&2 + exit 1 + fi + echo "$ip" +} + +main() { + if [[ $# -lt 1 ]]; then + echo "Usage: pct-run [command...]" >&2 + echo " pct-run 112 cat /etc/hostname" >&2 + echo " pct-run 114 systemctl status hermes-gateway" >&2 + echo "" + echo "Known CTs:" >&2 + for ct in $(echo "${!CT_NODES[@]}" | tr ' ' '\n' | sort -n); do + echo " CT $ct → ${CT_NODES[$ct]}" >&2 + done + exit 1 + fi + + local ct_id="$1" + shift + local node + node=$(resolve_node "$ct_id") + local ip + ip=$(node_ip "$node") + + if [[ $# -eq 0 ]]; then + # Interactive shell + exec ssh -t "root@${ip}" "pct enter ${ct_id}" + else + # One-shot command + ssh "root@${ip}" "pct exec ${ct_id} -- $*" + fi +} + +main "$@"