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 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 19:57:15 +00:00
co-authored by Claude Sonnet 5
parent e9e2312163
commit 87873300e1
4 changed files with 104 additions and 35 deletions
+65 -24
View File
@@ -31,32 +31,73 @@ machines when deployed.
the auto-installer (see `docs/auto-installer.md`). Never commit its the auto-installer (see `docs/auto-installer.md`). Never commit its
contents; if `git status` ever shows it as trackable, something is wrong. 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 There are two SSH-reachable Proxmox nodes on the LAN, both defined in
node hosting production VMs/containers — not a sandbox. `scripts/env.sh` (`PVE1_HOST` / `PVE_TEST_HOST`), individually targetable
via `scripts/proxmox/create-proxmox-resource.sh --node <host>` 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 #### `pve1.sweet.home` (production — off-limits to Claude)
list`, `pct list`, `qm config`, `pct config`, the Proxmox API, etc.) to
inspect the node's config, storage, and any existing VM/container — A real, live Proxmox node hosting production VMs/containers not a
including ones this repo didn't create. Never modify, stop, restart, sandbox, and not Claude's to touch by default.
delete, or reconfigure anything that already exists there (`qm set`,
`pct set`, `qm destroy`, `pct destroy`, `qm stop`, `pct stop`, snapshot - **Off-limits at all times unless the operator has given explicit,
operations, storage changes, etc.) without the operator's explicit same-session instructions to act on this specific host.** That
go-ahead. authorization is scoped to the task it was given for — don't carry it
- **Test VMs/containers are allowed, but must be torn down.** You may create forward to unrelated later work in the same conversation, and never
a scratch VM or container on the node (e.g. via assume it from a previous session.
`scripts/proxmox/create-proxmox-resource.sh` or raw `qm`/`pct create`) to - **Read-only for existing state is always fine, authorization or not.**
validate something. Anything you create this way must be destroyed again You may SSH in (or use `pvesm`, `qm list`, `pct list`, `qm config`, `pct
in the same session, before ending the task — never leave a test config`, the Proxmox API, etc.) to inspect the node's config, storage,
resource running on the node. Use a VMID/name that's obviously scratch and any existing VM/container — including ones this repo didn't create.
(and doesn't collide with a real flake target) so it's unambiguous what's - **Never** modify, stop, restart, delete, reconfigure, or create anything
safe to remove. on this node (`qm set`, `pct set`, `qm destroy`, `pct destroy`, `qm
- **No changes to production, ever, from an agent session** — this covers stop`, `pct stop`, `qm create`, `pct create`, snapshot operations,
both the node itself (Proxmox host config, storage pools, networking) and storage changes, etc.) — including scratch/test resources — without
any pre-existing guest. Anything beyond inspecting and tearing down your that explicit go-ahead. Use `pve-test.sweet.home` for anything
own scratch resources is the operator's call to make manually, same as exploratory instead; it exists precisely so `pve1` never has to be the
the deploy commands above. 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 ## Commands
+5
View File
@@ -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. 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 `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. 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/<name>/host.nix` carries the per-machine identity Each buildtype's `hosts/<name>/host.nix` carries the per-machine identity
(hostname, hostId, per-machine secrets, `system.stateVersion`) that must stay (hostname, hostId, per-machine secrets, `system.stateVersion`) that must stay
+20 -10
View File
@@ -6,12 +6,22 @@
# environment (e.g. PROXMOX_STORAGE=tank-nvme ./scripts/proxmox/create-proxmox-resource.sh ...) # environment (e.g. PROXMOX_STORAGE=tank-nvme ./scripts/proxmox/create-proxmox-resource.sh ...)
# since each one only sets a default if unset. # since each one only sets a default if unset.
# SSH-reachable Proxmox node that scripts/proxmox/create-proxmox-resource.sh runs # Two SSH-reachable Proxmox nodes exist on the LAN:
# pct/qm on. Matches the Proxmox web UI hostname already used in # - pve1.sweet.home -- production. Real, live VMs/containers.
# hosts/nixos/home.nix's desktop shortcuts (pve.<homeDomain> from # - pve-test.sweet.home -- sandbox/test node, for scratch VMs/containers
# variables.nix) -- change this if that's not actually reachable over SSH, # that don't belong on production.
# or if you're targeting a different node in a multi-node cluster. #
: "${PROXMOX_HOST:=pve.sweet.home}" # PROXMOX_HOST is what scripts/proxmox/create-proxmox-resource.sh actually
# targets by default -- overridable per-invocation with --node <hostname>,
# 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}" : "${PROXMOX_SSH_USER:=root}"
# Where this flake repo lives on the Proxmox node itself. # Where this flake repo lives on the Proxmox node itself.
@@ -63,10 +73,10 @@
# nothing here forces a mount to happen. # nothing here forces a mount to happen.
: "${PROXMOX_DEFAULT_LXC_FEATURES:=nesting=1,keyctl=1,mount=nfs;nfs4}" : "${PROXMOX_DEFAULT_LXC_FEATURES:=nesting=1,keyctl=1,mount=nfs;nfs4}"
export PROXMOX_HOST PROXMOX_SSH_USER PROXMOX_STORAGE PROXMOX_ISO_STORAGE \ export PVE1_HOST PVE_TEST_HOST PROXMOX_HOST PROXMOX_SSH_USER PROXMOX_STORAGE \
PROXMOX_BRIDGE PROXMOX_DEFAULT_CORES PROXMOX_DEFAULT_MEMORY_MB \ PROXMOX_ISO_STORAGE PROXMOX_BRIDGE PROXMOX_DEFAULT_CORES \
PROXMOX_DEFAULT_LXC_DISK_GB PROXMOX_DEFAULT_LXC_FEATURES \ PROXMOX_DEFAULT_MEMORY_MB PROXMOX_DEFAULT_LXC_DISK_GB \
PROXMOX_REMOTE_REPO_DIR PROXMOX_DEFAULT_LXC_FEATURES PROXMOX_REMOTE_REPO_DIR
# Matches variables.nix's nixCacheHost -- update both if it ever changes. # Matches variables.nix's nixCacheHost -- update both if it ever changes.
: "${NIX_CACHE_HOST:=nix-cache}" : "${NIX_CACHE_HOST:=nix-cache}"
+14 -1
View File
@@ -12,6 +12,17 @@
# copies over the locally-managed host-keys/ (gitignored, so a git pull # copies over the locally-managed host-keys/ (gitignored, so a git pull
# alone wouldn't carry it) before building. # 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: # Usage:
# scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --host <name> [options] # scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --host <name> [options]
# scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --list # scripts/proxmox/create-proxmox-resource.sh --type lxc|vm --list
@@ -120,7 +131,9 @@ Shared:
--iso-storage <pool> (default: \$PROXMOX_ISO_STORAGE, ${PROXMOX_ISO_STORAGE}) --iso-storage <pool> (default: \$PROXMOX_ISO_STORAGE, ${PROXMOX_ISO_STORAGE})
--bridge <bridge> (default: \$PROXMOX_BRIDGE, ${PROXMOX_BRIDGE}) --bridge <bridge> (default: \$PROXMOX_BRIDGE, ${PROXMOX_BRIDGE})
--node <host> Proxmox node to SSH into (default: --node <host> 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 --dry-run Print the full plan; touch nothing
local or remote, no prompts. local or remote, no prompts.
-h, --help -h, --help