Skip to content

Housemate Lab Access

Procedure for onboarding a housemate user to a Proxmox sandbox: dedicated resource pool, ZFS-quota-bounded storage, scoped RBAC. Trusted-LAN scope — VMs land on vmbr0/VLAN 1 today; future L2 isolation captured in Phase 8. PBS UI access for the housemate is deliberately out of scope at this stage (operator handles restore); see step 6 for the future-enhancement path.

Prerequisites

  • Proxmox host healthy (pvecm status clean, sufficient ZFS free on stash)

Variables used in this runbook

Variable Value
Username (PVE) hazel@pve
Group housemate-lab-admins
Pool housemate-lab
ZFS dataset stash/housemate-vms (quota 500 GiB)
PVE storage housemate-zfs

Step 1 — Create the storage substrate

# Carve the ZFS dataset with a hard quota
zfs create -o quota=500G stash/housemate-vms

# Verify
zfs get quota stash/housemate-vms
# Add as PVE storage, ZFS plugin, content limited to VM disks + LXC roots
pvesm add zfspool housemate-zfs \
    --pool stash/housemate-vms \
    --content images,rootdir \
    --sparse 1

Why a ZFS quota and not a Proxmox storage limit

Proxmox storage doesn't enforce per-storage size caps. The ZFS dataset quota is the hard cap; PVE just sees "available" space and respects what the FS reports.

Step 2 — Create the pool

pveum pool add housemate-lab --comment "Housemate sandbox — see runbooks/housemate-access.md"

Step 3 — Create the user and group

# Group first
pveum group add housemate-lab-admins --comment "Housemate Proxmox sandbox"

# User in the PVE realm (not pam — no host shell account)
pveum user add hazel@pve --groups housemate-lab-admins --comment "Hazel — housemate lab"

# Set initial password (interactive prompt)
pveum passwd hazel@pve

Realm choice

Always @pve, never @pam. PAM users are real Linux accounts on the host with shell access; PVE-realm users exist only inside Proxmox auth.

Step 4 — TOTP enforcement

In the PVE UI, log in as Hazel for the first time and set up TOTP under Datacenter → Permissions → Two Factor. Easier to walk through together than via API.

Step 5 — Apply the ACL set

Three permissions, all on the group:

# VM lifecycle within the pool
pveum acl modify /pool/housemate-lab \
    --groups housemate-lab-admins --roles PVEVMAdmin

# Storage write — only this storage, not local-zfs or stash root
pveum acl modify /storage/housemate-zfs \
    --groups housemate-lab-admins --roles PVEDatastoreUser

# Network attach to vmbr0 — required for VM creation per
# /usr/share/perl5/PVE/API2/Qemu.pm:1138
pveum acl modify /sdn/zones/localnetwork/vmbr0 \
    --groups housemate-lab-admins --roles PVESDNUser
# Verify effective permissions for the user
pveum user permissions hazel@pve

PVESDNUser is required even with no SDN configured

PVE 9 routes all bridge-attach permission checks through the SDN tree, even for plain non-SDN bridges like vmbr0. The implicit ACL path is /sdn/zones/localnetwork/<bridge>. Without SDN.Use here, PVEVMAdmin on the pool is not enough to create a VM — the network step fails with a permission error.

Step 6 — PBS coverage

The existing pbs-daily job (02:00 daily, all VMs to nas-primary, root namespace) picks up Hazel's pool VMs automatically once they land — no PBS-side change needed. Hazel does not get a PBS user or UI access at this stage; restore is operator-mediated.

Future enhancement — self-service PBS UI for the housemate

If Hazel later needs to browse her own backups, you'd:

PVE side — edit pbs-daily (or add a new pool-scoped backup job) so VMs in pool housemate-lab write to --namespace housemate. The namespace auto-creates on first backup write; there is no explicit proxmox-backup-manager namespace create subcommand in PBS 4.x.

PBS side (on CT 105):

proxmox-backup-manager user create hazel@pbs --comment "Housemate lab"
proxmox-backup-manager acl update /datastore/nas-primary/housemate \
    DatastoreBackup --auth-id hazel@pbs
proxmox-backup-manager acl update /datastore/nas-primary/housemate \
    DatastoreAudit --auth-id hazel@pbs

Verified syntax for acl update is <path> <role> --auth-id <id> (path and role are positional; auth ID is a flag). The earlier draft of this runbook had the args inverted — corrected 2026-05-01.

PBS 4.x ACL footgun: attach ACLs to hazel@pbs (the user), never to hazel@pbs!some-token. Token ACLs silently resolve to zero perms; tokens inherit from their parent user.

Step 7 — Guidelines for Hazel

Provide a written copy:

  • Per-VM caps: 4 vCPU / 8 GiB RAM / 200 GiB disk. Pool quota is 500 GiB total across all VMs.
  • Snapshot before risky changes. qm snapshot <vmid> <name> or via UI.
  • Don't pass through host devices. You won't have permission anyway, but ping me first if you think you need it.
  • Backups are automatic. Daily 02:00 to PBS. You don't have direct access to PBS — if you ever need to restore a VM or pull files out of a backup, ping me.
  • Federation / public exposure is a separate conversation. Lab VMs are LAN-only by default — no port forwards, no DNS records, no reverse-proxy entries unless we explicitly set them up together.
  • Performance issues affecting the host (Plex stuttering, etc.) — ping me, we'll figure out which side it's coming from.

Verification — try it as Hazel

Log in as hazel@pve and verify:

  • Login works; TOTP prompt appears
  • Datacenter view shows only the housemate-lab pool (no other VMs/storages visible)
  • Create a tiny test VM (1 vCPU / 1 GiB / 16 GiB) on housemate-zfs, attached to vmbr0
  • Test VM boots, gets DHCP from UDM (192.168.1.x), reaches the internet
  • Snapshot the test VM, restore from snapshot
  • (Operator) Confirm test VM appears in PBS the morning after creation under root namespace
  • Destroy the test VM, verify ZFS dataset reclaim

Removal

To revoke access cleanly:

# Stop and delete all VMs in the pool first (Hazel can do this; or as root)
# Then:
pveum acl delete /pool/housemate-lab \
    --groups housemate-lab-admins --roles PVEVMAdmin
pveum acl delete /storage/housemate-zfs \
    --groups housemate-lab-admins --roles PVEDatastoreUser
pveum acl delete /sdn/zones/localnetwork/vmbr0 \
    --groups housemate-lab-admins --roles PVESDNUser
pveum user delete hazel@pve
pveum group delete housemate-lab-admins
pvesm remove housemate-zfs
zfs destroy -r stash/housemate-vms

PBS-side cleanup only applies if the future-enhancement block in step 6 was activated — otherwise nothing to remove.

Future migration to the Lab VLAN

When Phase 8 lands, step 8G replaces the /sdn/zones/localnetwork/vmbr0 ACL with one on the Lab VNet, and Hazel's VMs migrate from vmbr0 to the new VLAN-aware bridge.

Lessons from the 2026-05-01 run

Steps 1-5 landed on proxfold cleanly:

  • ZFS dataset + PVE storage created (housemate-zfs, 500 GiB quota)
  • Pool, group, user (no password yet) created
  • All three ACLs verified via pveum user permissions hazel@pve — pool/storage/SDN paths exactly as scoped, no spurious privileges

Step 6 was descoped mid-execution — Hazel doesn't need self-service PBS access at this stage. PBS-side artifacts I'd already created (hazel@pbs user + ACL on /datastore/nas-primary/housemate) were rolled back; backups continue to land in root namespace via the existing pbs-daily job.

Two CLI bugs in the original step 6 caught and corrected:

  • proxmox-backup-manager namespace create does not exist in PBS 4.x. The original draft assumed it did. Namespaces auto-create on first backup write, or via the web UI / REST API. Future-enhancement block in step 6 reflects this.
  • acl update arg order is <path> <role> --auth-id <id>, not <path> <auth-id> --role <role>. Path and role are both positional; auth ID is a flag.

Lesson for future runbook drafting: validate proxmox-backup-manager and pveum subcommands against --help before sketching command sequences. Cheap to do, would have caught both bugs pre-execution.