CRITICAL: Agent Access Limitations
YOU DO NOT HAVE ACCESS TO PROXMox
Agent runs on your local machine - NOT on Proxmox
Forbidden:
- - Try to run qm commands
- Try to run pvesh commands
- Check storage availability
- Verify VM creation
- Access Proxmox API
Must Do:
- - Output commands as text for user to copy/paste
- Tell user which node to SSH to
- Store keys locally in a configurable directory (default: ~/.ssh/pve-builder/)
- Never claim to create VMs
- Use web search for specs validation
PVE Builder Skill
Overview
Generates Proxmox VM creation commands with cloud-init configuration, SSH key management, and optional data disks. All hardware defaults are config-driven via pve-env.md.
IMPORTANT: Commands are output as text for you to copy/paste into Proxmox shell. The agent does NOT execute any Proxmox commands.
Environment Setup
- - Config file:
pve-env.md in the skill directory - Ignored from git:
.gitignore excludes INLINECODE3
Critical Configuration Keys (pve-env.md)
| Section | Keys | Purpose |
|---|
| Proxy | INLINECODE4 , HTTP Proxy, HTTPS Proxy, INLINECODE7 | Network proxy for apt inside VMs |
| SSH |
Default User,
Key Path,
Key Type | Default SSH user, key storage location, key type |
|
Network |
Default Bridge,
Default VLAN,
DNS Server,
Use DHCP Default,
Network Interface | Default network settings and interface type |
|
Storage |
Default Storage,
Template Path,
Default OS Disk Size,
Auto-Format Data Disks,
Data Disk Interface,
Default Cloud Image | Storage defaults and cloud image path |
|
Node |
Default Node,
BIOS Type,
Machine Type,
CPU Type,
OS Type,
SCSI Controller,
Onboot | Hardware defaults for VM creation |
|
Workload Presets | Preset table (RAM/CPU/Disk) | Recommended specs per workload type |
|
Package Defaults |
Package Update,
Base Packages | Always-installed package list |
Agent Workflow
The workflow uses section-based numbered prompts with continuous numbering across sections:
CODEBLOCK0
Steps:
- 1. Load
pve-env.md (error if missing) - Ask cloud image path (default from config:
Template Path + Default Cloud Image) - Ask Proxmox node (default from config)
- Validate storage/bridge/image (see Validation section below)
- Ask VM name
- Software lookup (name or URL) → web search for RAM/CPU recommendations (or manual)
- Prompt specs (numbered prompts: cores, sockets, RAM, OS disk)
- Prompt network (bridge, VLAN, DHCP vs static)
- Static IP details (only if no DHCP)
- Prompt SSH username
- Prompt data disks (count, sizes, formatting option)
- Proxy configuration (yes/no/change)
- Extra apt packages
- SSH key directory (default from config)
- Password setup — always generate a random password via
openssl rand -base64 12 | tr -d '/+=' | head -c16. Use this in chpasswd. If the user explicitly provides a password, use theirs instead. Always show the password in the final output summary. - Generate SSH key (unique ed25519 per VM)
- Show summary & confirm
- VMID auto-detection — Ask the user to run
pvesh get /cluster/nextid on the Proxmox node and paste back the result. Use that VMID in all generated commands. Never hardcode a VMID — always get the next ID from the cluster. Add a # Replace VMID=... if already taken comment in the output. - Build cloud-init user-data YAML (packages, proxy, data disk formatting)
- Pre-flight validation (see Command Pre-flight Validation below) — generate commands internally, validate, fix errors, then present
- Generate and display the final verified commands in two sections: Setup commands (create VM through
qm start) and Post-boot cleanup (delete the snippets YAML — only run after the VM is verified up). - Optional: save commands to file
- Show SSH key path and chmod reminder
Validation
Before generating commands, the agent validates that the target storage, bridge, and cloud image exist on the Proxmox node.
Cache System
- - Cache file: INLINECODE39
- Valid for: 24 hours
- Cache invalidated if: node, storage, or bridge values change
- On cache hit: validation is skipped if all checks passed
Validation Process
If no valid cache exists, the agent shows these commands for the user to run on the Proxmox node:
CODEBLOCK1
Results are parsed:
- - Storage: Checks if configured storage name exists in INLINECODE40
- Bridge: Verifies bridge interface is present and UP
- Image: Confirms cloud image file exists at path
On failure: Agent aborts and reports which check(s) failed.
On success: Results are cached with node/storage/bridge/timestamp.
Notes
- - Custom cloud-init user-data is written to
/var/lib/vz/snippets/<VMNAME>-user-data.yaml and attached via --cicustom "user=local:snippets/<VMNAME>-user-data.yaml". The local:snippets/ storage path maps to /var/lib/vz/snippets/ on the Proxmox node. Never use /var/lib/vz/template/cloud-init/ — that directory is not a recognized Proxmox snippets storage target. --cicustom reads the snippets file at every boot. The snippets YAML must exist on the node when the VM starts — cloud-init won't apply without it. Do NOT delete the snippets file before the first boot.- Always include
mkdir -p /var/lib/vz/snippets at the top of the generated commands. - After setting
--ide2 and --citype, add --cicustom to wire the user-data: qm set $VMID --cicustom "user=local:snippets/${VMNAME}-user-data.yaml". - After
--cicustom, regenerate the cloud-init drive before starting: qm cloudinit update $VMID. - ssh_pwauth: set
true when a password is configured (so the password actually works over SSH). Set false only for SSH-key-only VMs. - The command to get the next VMID is provided as a hint; the agent does not run Proxmox commands
- SSH keys are stored locally in the configured directory (default:
~/.ssh/pve-builder/) - Generated commands include cleanup steps at the end: lists cloud-init YAML files for review, then removes the current VM's file. IMPORTANT: The cleanup step (rm snippets YAML) must NOT use
set -e or be in the main command block. It should be in a separate "Post-boot" section that runs only after the VM is verified running and cloud-init applied. If the user deletes the YAML before the first boot, cloud-init fails silently. - Always include
echo "VMID: <id>" in the verify/final section so the user has the VMID referenced
Command Pre-flight Validation
Never present commands to the user without running this validation first. Generate → validate → fix → present.
Phase 1: Internal Draft
Build the complete command set internally (do not show yet).
Phase 2: Parameter Verification Script
Generate a small bash validation script, set the variables to match the VM specs, and run it locally with exec. If it fails, fix the draft and re-run until it passes. Only then show the commands.
CODEBLOCK2
The agent:
- 1. Writes this script to a temp file with actual VM values
- Runs it with INLINECODE60
- If it fails, fixes values, re-runs
- Only presents commands when INLINECODE61
Checklist (run after pre-flight script passes)
- - [ ] Shebang/header with VM name, VMID, node
- [ ] INLINECODE62
- [ ] User-data written to INLINECODE63
- [ ]
ssh_pwauth: true if password configured, false if SSH-only - [ ]
--citype nocloud (NOT cloud-config) - [ ]
qm create with no INLINECODE69 - [ ]
qm importdisk references correct image - [ ]
--scsi0 attaches imported disk - [ ]
--ide2 <storage>:cloudinit attached - [ ]
--cicustom "user=local:snippets/${VMNAME}-user-data.yaml" added - [ ]
qm cloudinit update $VMID after cicustom set - [ ]
--ipconfig0 ip=dhcp (DHCP) or --ipconfig0 ip=<CIDR>,gw=<GW> (static) — this actually configures the network inside the guest - [ ] INLINECODE77
- [ ] INLINECODE78
- [ ]
qm resize $VMID scsi0 <size> after import - [ ]
echo "VMID: $VMID" in output - [ ]
qm config $VMID for review - [ ] Cleanup note at end (remove snippets YAML)
- [ ] No typos:
qm not vm, $VMID not INLINECODE85 - [ ] Variable names consistent throughout
Networking
DHCP (default)
Simple network config: INLINECODE86
Do NOT use --nameserver with DHCP — let the DHCP lease provide DNS. Only set --nameserver when using static IP.
Static IP
When DHCP is declined, the agent prompts for:
- - IP address with CIDR (e.g.,
10.0.12.50/24) - Gateway (e.g.,
10.0.12.1) - DNS servers (comma-separated, default from config)
Generated commands:
- - INLINECODE91
- INLINECODE92
Package Installation
All VMs get base packages from pve-env.md (deduplicated with any extra packages).
If proxy is configured, apt proxy is automatically enabled in cloud-init.
Security
- - Passwords: ALL VMs get a random password by default. Generate with:
openssl rand -base64 12 | tr -d '/+=' | head -c16. Use in both chpasswd in cloud-init YAML and embed in command output. If the user provides an explicit password, use theirs instead — but always show it back in output so they have it. Set ssh_pwauth: true unless the user explicitly says SSH-only. - SSH keys: Unique per VM, ed25519, no passphrase
- pve-env.md: chmod 600, excluded from git
- Private keys: chmod 600, never in commands
- Public keys: Safe to embed in commands
- SSH key directory: configurable via
Key Path in pve-env.md (default ~/.ssh/pve-builder); permissions 700 on base dir
Version History
- - 1.0.10: Add
--cicustom warning: snippets file must survive first boot. Split output into Setup and Post-boot sections. VMID auto-detection via cluster/nextid. Fix workflow numbering. - 1.0.9: Always generate random password per-VM (
openssl rand -base64 12), user override option, always display password in output - 1.0.7: Fix custom user-data routing:
/var/lib/vz/snippets/ + --cicustom, qm cloudinit update, ssh_pwauth conditional - 1.0.5:
mkdir -p for required dirs in generated commands, command self-review checklist, --citype nocloud enforced, automatic disk resize after importdisk - 1.0.3: Full config decoupling (all hardware defaults from pve-env.md), storage/bridge validation with 24h cache, static IP support, continuous numbered prompts with section headers, SSH key path not echoed in summary, duplicate package removal, direct VMID input, cloud-init cleanup commands
- 1.0.2: Added URL analysis, web search validation, simplified proxy flow
- 1.0.1: Added explicit access limitation warnings
- 1.0.0: Initial release
This file is yours to evolve. As you learn who you are, update it.
关键:代理访问限制
您无权访问 Proxmox
代理在您的本地机器上运行——而非 Proxmox 上
禁止操作:
- - 尝试运行 qm 命令
- 尝试运行 pvesh 命令
- 检查存储可用性
- 验证虚拟机创建
- 访问 Proxmox API
必须执行:
- - 以文本形式输出命令,供用户复制粘贴
- 告知用户应 SSH 到哪个节点
- 将密钥存储在可配置目录中(默认:~/.ssh/pve-builder/)
- 切勿声称创建了虚拟机
- 使用网络搜索验证规格
PVE Builder 技能
概述
生成带有 cloud-init 配置、SSH 密钥管理和可选数据盘的 Proxmox 虚拟机创建命令。所有硬件默认值通过 pve-env.md 进行配置驱动。
重要提示: 命令以文本形式输出,供您复制粘贴到 Proxmox shell 中。代理不会执行任何 Proxmox 命令。
环境设置
- - 配置文件: 技能目录中的 pve-env.md
- 从 git 忽略: .gitignore 排除 pve-env.md
关键配置项(pve-env.md)
| 部分 | 键 | 用途 |
|---|
| 代理 | 需要代理、HTTP 代理、HTTPS 代理、代理 CA 证书 | 虚拟机内 apt 的网络代理 |
| SSH |
默认用户、密钥路径、密钥类型 | 默认 SSH 用户、密钥存储位置、密钥类型 |
|
网络 | 默认桥接、默认 VLAN、DNS 服务器、使用 DHCP 默认、网络接口 | 默认网络设置和接口类型 |
|
存储 | 默认存储、模板路径、默认系统盘大小、自动格式化数据盘、数据盘接口、默认云镜像 | 存储默认值和云镜像路径 |
|
节点 | 默认节点、BIOS 类型、机器类型、CPU 类型、OS 类型、SCSI 控制器、开机自启 | 虚拟机创建的硬件默认值 |
|
工作负载预设 | 预设表(内存/CPU/磁盘) | 每种工作负载类型的推荐规格 |
|
软件包默认值 | 软件包更新、基础软件包 | 始终安装的软件包列表 |
代理工作流程
工作流程使用基于部分的编号提示,各部分编号连续:
=== 虚拟机规格 ===
- 1. CPU 核心数 2. CPU 插槽数 3. 内存(GB) 4. 系统盘大小
=== 网络 ===
- 5. 桥接 6. VLAN 7. DHCP?
[如果静态:] 8. IP 9. 网关 10. DNS
=== 用户与磁盘 ===
- 11. SSH 用户 12. 添加数据盘? 13. 格式化? 14. 数量 15.x:磁盘大小
- 代理? 16. 额外软件包 17. SSH 密钥目录
步骤:
- 1. 加载 pve-env.md(如果缺失则报错)
- 询问云镜像路径(默认来自配置:模板路径 + 默认云镜像)
- 询问 Proxmox 节点(默认来自配置)
- 验证存储/桥接/镜像(见下方验证部分)
- 询问虚拟机名称
- 软件查询(名称或 URL)→ 网络搜索内存/CPU 推荐(或手动输入)
- 提示规格(编号提示:核心数、插槽数、内存、系统盘大小)
- 提示网络(桥接、VLAN、DHCP 与静态)
- 静态 IP 详情(仅当不使用 DHCP 时)
- 提示 SSH 用户名
- 提示数据盘(数量、大小、格式化选项)
- 代理配置(是/否/更改)
- 额外 apt 软件包
- SSH 密钥目录(默认来自配置)
- 密码设置 — 始终通过 openssl rand -base64 12 | tr -d /+= | head -c16 生成随机密码。在 chpasswd 中使用此密码。如果用户明确提供密码,则使用用户提供的密码。始终在最终输出摘要中显示密码。
- 生成 SSH 密钥(每个虚拟机唯一的 ed25519 密钥)
- 显示摘要并确认
- VMID 自动检测 — 要求用户在 Proxmox 节点上运行 pvesh get /cluster/nextid 并粘贴结果。在所有生成的命令中使用该 VMID。切勿硬编码 VMID — 始终从集群获取下一个 ID。在输出中添加 # 如果 VMID=... 已被占用,请替换 注释。
- 构建 cloud-init user-data YAML(软件包、代理、数据盘格式化)
- 预检验证(见下方命令预检验证)— 内部生成命令,验证,修复错误,然后呈现
- 生成并显示最终验证的命令,分为两部分:设置命令(创建虚拟机至 qm start)和启动后清理(删除 snippets YAML — 仅在虚拟机确认启动后运行)。
- 可选:将命令保存到文件
- 显示 SSH 密钥路径和 chmod 提醒
验证
在生成命令之前,代理验证目标存储、桥接和云镜像是否存在于 Proxmox 节点上。
缓存系统
- - 缓存文件: ~/.pve-builder/validation.json
- 有效期: 24 小时
- 缓存失效条件: 节点、存储或桥接值发生变化
- 缓存命中时: 如果所有检查均通过,则跳过验证
验证过程
如果没有有效缓存,代理显示以下命令供用户在 Proxmox 节点上运行:
bash
echo === 存储 ===; pvesm status
echo === 桥接 ===; ip -br link show
echo === 镜像 ===; ls -la <镜像路径>
echo === 结束 ===
解析结果:
- - 存储: 检查配置的存储名称是否存在于 pvesm status 中
- 桥接: 验证桥接接口是否存在且状态为 UP
- 镜像: 确认云镜像文件存在于指定路径
失败时: 代理中止并报告哪些检查失败。
成功时: 结果与节点/存储/桥接/时间戳一起缓存。
注意事项
- - 自定义 cloud-init user-data 写入 /var/lib/vz/snippets/<虚拟机名称>-user-data.yaml,并通过 --cicustom user=local:snippets/<虚拟机名称>-user-data.yaml 附加。local:snippets/ 存储路径映射到 Proxmox 节点上的 /var/lib/vz/snippets/。切勿使用 /var/lib/vz/template/cloud-init/ — 该目录不是 Proxmox 认可的 snippets 存储目标。
- --cicustom 在每次启动时读取 snippets 文件。 虚拟机启动时,snippets YAML 必须存在于节点上 — 没有它,cloud-init 将无法应用。在首次启动之前,请勿删除 snippets 文件。
- 始终在生成的命令顶部包含 mkdir -p /var/lib/vz/snippets。
- 设置 --ide2 和 --citype 后,添加 --cicustom 以连接 user-data:qm set $VMID --cicustom user=local:snippets/${虚拟机名称}-user-data.yaml。
- 设置 --cicustom 后,在启动前重新生成 cloud-init 驱动器: qm cloudinit update $VMID。
- ssh_pwauth:配置密码时设置为 true(这样密码才能通过 SSH 实际生效)。仅限 SSH 密钥的虚拟机设置为 false。
- 获取下一个 VMID 的命令作为提示提供;代理不运行 Proxmox 命令
- SSH 密钥存储在本地配置的目录中(默认:~/.ssh/pve-builder/)
- 生成的命令在末尾包含清理步骤:列出 cloud-init YAML 文件供审查,然后删除当前虚拟机的文件。重要提示: 清理步骤(删除 snippets YAML)不得使用 set -e 或位于主命令块中。它应位于单独的启动后部分,仅在虚拟机确认运行且 cloud-init 应用后执行。如果用户在首次启动前删除 YAML,cloud-init 将静默失败。
- 始终在验证/最终部分包含 echo VMID: ,以便用户引用 VMID
命令预检验证
在未运行此验证之前,切勿向