From 87873300e1c3e04025946ce5be875f8a3337aaad Mon Sep 17 00:00:00 2001 From: beatzaplenty Date: Tue, 21 Jul 2026 19:57:15 +0000 Subject: [PATCH] Add pve-test.sweet.home as a second Proxmox target pve1.sweet.home is production; scripts/env.sh now also defines PVE_TEST_HOST for a separate sandbox node, individually targetable via --node/PROXMOX_HOST. Tooling defaults are unchanged (still pve1) -- the new restriction (Claude defaults to pve-test unless explicitly told to use pve1) is documented as policy in CLAUDE.md, not enforced in the scripts. Co-Authored-By: Claude Sonnet 5 --- CLAUDE.md | 89 ++++++++++++++++------ README.md | 5 ++ scripts/env.sh | 30 +++++--- scripts/proxmox/create-proxmox-resource.sh | 15 +++- 4 files changed, 104 insertions(+), 35 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 68931a9..cdc1c79 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -31,32 +31,73 @@ machines when deployed. the auto-installer (see `docs/auto-installer.md`). Never commit its contents; if `git status` ever shows it as trackable, something is wrong. -### `pve.sweet.home` (the Proxmox node) +### Two Proxmox nodes: `pve1.sweet.home` (production) and `pve-test.sweet.home` (sandbox) -`pve.sweet.home` (`PROXMOX_HOST` in `scripts/env.sh`) is a real, live Proxmox -node hosting production VMs/containers — not a sandbox. +There are two SSH-reachable Proxmox nodes on the LAN, both defined in +`scripts/env.sh` (`PVE1_HOST` / `PVE_TEST_HOST`), individually targetable +via `scripts/proxmox/create-proxmox-resource.sh --node ` or by +overriding `PROXMOX_HOST`. `PROXMOX_HOST` itself still defaults to +`PVE1_HOST` (production) — that default, and every other script behavior, +is unchanged from before `pve-test` existed; the only thing new is that +`pve-test` can now be reached at all. They are **not interchangeable** — +one is real production infrastructure, the other exists specifically so +there's somewhere safe to test. The restriction below is a policy for +Claude specifically, not a change to the tooling's own default or +anything the operator needs to opt into. -- **Read-only for existing state.** You may SSH in (or use `pvesm`, `qm - list`, `pct list`, `qm config`, `pct config`, the Proxmox API, etc.) to - inspect the node's config, storage, and any existing VM/container — - including ones this repo didn't create. Never modify, stop, restart, - delete, or reconfigure anything that already exists there (`qm set`, - `pct set`, `qm destroy`, `pct destroy`, `qm stop`, `pct stop`, snapshot - operations, storage changes, etc.) without the operator's explicit - go-ahead. -- **Test VMs/containers are allowed, but must be torn down.** You may create - a scratch VM or container on the node (e.g. via - `scripts/proxmox/create-proxmox-resource.sh` or raw `qm`/`pct create`) to - validate something. Anything you create this way must be destroyed again - in the same session, before ending the task — never leave a test - resource running on the node. Use a VMID/name that's obviously scratch - (and doesn't collide with a real flake target) so it's unambiguous what's - safe to remove. -- **No changes to production, ever, from an agent session** — this covers - both the node itself (Proxmox host config, storage pools, networking) and - any pre-existing guest. Anything beyond inspecting and tearing down your - own scratch resources is the operator's call to make manually, same as - the deploy commands above. +#### `pve1.sweet.home` (production — off-limits to Claude) + +A real, live Proxmox node hosting production VMs/containers — not a +sandbox, and not Claude's to touch by default. + +- **Off-limits at all times unless the operator has given explicit, + same-session instructions to act on this specific host.** That + authorization is scoped to the task it was given for — don't carry it + forward to unrelated later work in the same conversation, and never + assume it from a previous session. +- **Read-only for existing state is always fine, authorization or not.** + You may SSH in (or use `pvesm`, `qm list`, `pct list`, `qm config`, `pct + config`, the Proxmox API, etc.) to inspect the node's config, storage, + and any existing VM/container — including ones this repo didn't create. +- **Never** modify, stop, restart, delete, reconfigure, or create anything + on this node (`qm set`, `pct set`, `qm destroy`, `pct destroy`, `qm + stop`, `pct stop`, `qm create`, `pct create`, snapshot operations, + storage changes, etc.) — including scratch/test resources — without + that explicit go-ahead. Use `pve-test.sweet.home` for anything + exploratory instead; it exists precisely so `pve1` never has to be the + answer to "where do I test this." +- **This is a Claude-specific policy, not something the scripts enforce.** + `scripts/env.sh`/`create-proxmox-resource.sh` default to `pve1` exactly + as they did before `pve-test` existed, with no extra flag or prompt + required — that's deliberate, so the operator's own existing workflows + don't change. Claude, however, must never rely on that default: every + Proxmox action Claude takes on its own initiative — not explicitly + pointed at `pve1` by the operator this session — targets `pve-test` + instead (e.g. `--node "$PVE_TEST_HOST"`, or `PROXMOX_HOST=$PVE_TEST_HOST`). + Claude's own default is `pve-test`, full stop, regardless of what the + tooling's own unqualified default happens to be. + +#### `pve-test.sweet.home` (sandbox — Claude's default target) + +A separate Proxmox node set aside for testing. The *tooling's* default is +still production (`PROXMOX_HOST` → `PVE1_HOST`, see above) — but +**Claude's own default is this node**: absent an explicit, same-session +instruction to use `pve1`, every Proxmox action Claude initiates targets +`pve-test`. Once targeted, it's safe to create, interrogate, and destroy +resources on without asking first. + +- **Test VMs/containers are allowed, but must be torn down.** Create a + scratch VM or container here (e.g. via + `scripts/proxmox/create-proxmox-resource.sh` or raw `qm`/`pct create`) + to validate something. Anything created this way must be destroyed + again in the same session, before ending the task — never leave a test + resource running. Use a VMID/name that's obviously scratch (and doesn't + collide with a real flake target) so it's unambiguous what's safe to + remove. +- **Node-level config is still not yours to change.** Creating/destroying + your own scratch guests is fine; Proxmox host config, storage pools, and + networking on `pve-test` itself are still the operator's call to make + manually, same as on `pve1`. ## Commands diff --git a/README.md b/README.md index 04d3d2b..8747b0e 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,11 @@ Check the Proxmox node itself, or `/etc/flake-target` on a running host (see below), if you need to know what's really out there right now. `scripts/proxmox/create-proxmox-resource.sh`'s duplicate-host guard works the same way: it checks the Proxmox node directly rather than any file here. +Real, production deployments live on `pve1.sweet.home`; there's a second +node, `pve-test.sweet.home`, set aside purely for scratch/test resources — +see `scripts/env.sh` (`PVE1_HOST` / `PVE_TEST_HOST`, and the +`--node`/`PROXMOX_HOST` targeting they feed into) and CLAUDE.md's Proxmox +section for which is which. Each buildtype's `hosts//host.nix` carries the per-machine identity (hostname, hostId, per-machine secrets, `system.stateVersion`) that must stay diff --git a/scripts/env.sh b/scripts/env.sh index dc864d6..76a7ec2 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -6,12 +6,22 @@ # environment (e.g. PROXMOX_STORAGE=tank-nvme ./scripts/proxmox/create-proxmox-resource.sh ...) # since each one only sets a default if unset. -# SSH-reachable Proxmox node that scripts/proxmox/create-proxmox-resource.sh runs -# pct/qm on. Matches the Proxmox web UI hostname already used in -# hosts/nixos/home.nix's desktop shortcuts (pve. from -# variables.nix) -- change this if that's not actually reachable over SSH, -# or if you're targeting a different node in a multi-node cluster. -: "${PROXMOX_HOST:=pve.sweet.home}" +# Two SSH-reachable Proxmox nodes exist on the LAN: +# - pve1.sweet.home -- production. Real, live VMs/containers. +# - pve-test.sweet.home -- sandbox/test node, for scratch VMs/containers +# that don't belong on production. +# +# PROXMOX_HOST is what scripts/proxmox/create-proxmox-resource.sh actually +# targets by default -- overridable per-invocation with --node , +# or per-variable as usual (e.g. PROXMOX_HOST=$PVE_TEST_HOST). It defaults +# to production, matching this repo's behavior before pve-test existed -- +# see CLAUDE.md's "Two Proxmox nodes" section for the policy on which +# situations should target which node (in particular: Claude defaults to +# pve-test, not this variable's own default, unless explicitly told +# otherwise). +: "${PVE1_HOST:=pve1.sweet.home}" +: "${PVE_TEST_HOST:=pve-test.sweet.home}" +: "${PROXMOX_HOST:=$PVE1_HOST}" : "${PROXMOX_SSH_USER:=root}" # Where this flake repo lives on the Proxmox node itself. @@ -63,10 +73,10 @@ # nothing here forces a mount to happen. : "${PROXMOX_DEFAULT_LXC_FEATURES:=nesting=1,keyctl=1,mount=nfs;nfs4}" -export PROXMOX_HOST PROXMOX_SSH_USER PROXMOX_STORAGE PROXMOX_ISO_STORAGE \ - PROXMOX_BRIDGE PROXMOX_DEFAULT_CORES PROXMOX_DEFAULT_MEMORY_MB \ - PROXMOX_DEFAULT_LXC_DISK_GB PROXMOX_DEFAULT_LXC_FEATURES \ - PROXMOX_REMOTE_REPO_DIR +export PVE1_HOST PVE_TEST_HOST PROXMOX_HOST PROXMOX_SSH_USER PROXMOX_STORAGE \ + PROXMOX_ISO_STORAGE PROXMOX_BRIDGE PROXMOX_DEFAULT_CORES \ + PROXMOX_DEFAULT_MEMORY_MB PROXMOX_DEFAULT_LXC_DISK_GB \ + PROXMOX_DEFAULT_LXC_FEATURES PROXMOX_REMOTE_REPO_DIR # Matches variables.nix's nixCacheHost -- update both if it ever changes. : "${NIX_CACHE_HOST:=nix-cache}" diff --git a/scripts/proxmox/create-proxmox-resource.sh b/scripts/proxmox/create-proxmox-resource.sh index 6de5c40..79a1455 100755 --- a/scripts/proxmox/create-proxmox-resource.sh +++ b/scripts/proxmox/create-proxmox-resource.sh @@ -12,6 +12,17 @@ # copies over the locally-managed host-keys/ (gitignored, so a git pull # alone wouldn't carry it) before building. # +# --node (default: $PROXMOX_HOST, see scripts/env.sh) picks which of the two +# LAN Proxmox nodes this runs against: production, pve1.sweet.home +# ($PVE1_HOST, PROXMOX_HOST's own default), or the sandbox node, +# pve-test.sweet.home ($PVE_TEST_HOST) -- pass --node "$PVE_TEST_HOST" (or +# set PROXMOX_HOST=$PVE_TEST_HOST) to target the sandbox instead. See +# CLAUDE.md's "Two Proxmox nodes" section: an agent session should default +# to pve-test and only touch pve1 when the operator has explicitly said so +# for the current task -- this script itself doesn't enforce that (its own +# default is production, matching this repo's behavior before pve-test +# existed), it's a policy for whoever/whatever is driving it. +# # Usage: # scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --host [options] # scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --list @@ -120,7 +131,9 @@ Shared: --iso-storage (default: \$PROXMOX_ISO_STORAGE, ${PROXMOX_ISO_STORAGE}) --bridge (default: \$PROXMOX_BRIDGE, ${PROXMOX_BRIDGE}) --node Proxmox node to SSH into (default: - \$PROXMOX_HOST, ${PROXMOX_HOST}) + \$PROXMOX_HOST, ${PROXMOX_HOST} -- + production; the sandbox node is + \$PVE_TEST_HOST, ${PVE_TEST_HOST}). --dry-run Print the full plan; touch nothing local or remote, no prompts. -h, --help