Community编程与开发github.com

eageric/cursor-cloud-eag

通过 Cloudflare Access SSH 隧道在 EAG Proxmox VE 服务器上创建、连接和清理一次性测试虚拟机。基于 Windows Server 2025 和 Ubuntu 24.04 模板进行克隆。

cursor-cloud-eag 是什么?

此技能为 AI 代理(如 Claude Code)提供在远程 Proxmox VE 服务器上管理测试虚拟机的完整能力。它通过 Cloudflare Access SSH 隧道(主机别名 eric-pve-ssh.eag.tools)连接到 EAG 基础设施,使用 SSH 私钥 `~/.ssh/pve_ssh` 进行身份验证。支持两种模板:Windows Server 2025 Datacenter Evaluation(VMID 101)和 Ubuntu 24.04 LTS(VMID 100)的完整克隆。该技能涵盖了从模板克隆、通过 QEMU Guest Agent 获取 IP 地址、等待首次启动(包括 Windows 的 Sysprep 后脚本),到通过隧道 Jump Host 进行 SSH 和 PowerShell Remoting 会话的完整工作流。还支持隔离网络(nat0 桥接)上的虚拟机、创建快照以及最终销毁或关闭虚拟机的操作。自动为创建的虚拟机添加 `ai-test` 标签,并在清理前强制要求用户确认。该技能集成在 Cloudflare 隧道环境中,严禁直接连接到 Proxmox 宿主机的 LAN 地址(10.115.64.44)。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/eageric/cursor-cloud-eag/tree/HEAD/.cursor/skills/pve-dev

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

通过 Cloudflare SSH 隧道的 EAG Proxmox

Proxmox VE 9.2 服务器托管一次性测试虚拟机。在此环境中,主机名为 eric-pve-ssh.eag.tools。代理程序克隆模板、运行测试,然后在删除任何内容前征询用户意见。

模板、克隆步骤和客户机登录方式与 LAN 环境一致。改变的是路径:云代理通过 Cloudflare Access 连接到主机,并通过该主机跳转访问所有客户机。

访问

环境启动脚本根据 PVE_SSH_PRIVATE_B64 和 PVE_SSH_PUBLIC_KEY 创建密钥对:

文件模式用途
~/.ssh/pve_ssh600私钥。用于 Proxmox 主机、Windows Administrator、Ubuntu erolleman。
~/.ssh/pve_ssh.pub644匹配的公钥。

/etc/ssh/ssh_config.d/eric-pve-ssh.conf 已为 eric-pve-ssh.eag.tools 设置 User root、IdentityFile ~/.ssh/pve_ssh、IdentitiesOnly yes 以及 ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h。使用该主机别名。保留系统文件不变。

KEY="$HOME/.ssh/pve_ssh"
test -r "$KEY" || { echo "缺少 $KEY; 启动脚本会根据 PVE_SSH_PRIVATE_B64 创建它" >&2; exit 1; }
PVE="ssh -o StrictHostKeyChecking=accept-new eric-pve-ssh.eag.tools"
$PVE 'qm list'

客户机 SSH,同时适用于 10.115.64.x(vmbr0)和 10.20.0.x(nat0):

JUMP='ssh -o StrictHostKeyChecking=accept-new -W %h:%p eric-pve-ssh.eag.tools'
VMSSH="ssh -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -o ProxyCommand=\"$JUMP\" USER@$IP"

在使用 VMSSH 之前,将 USER 设置为 Administrator 或 erolleman,将 IP 设置为客户机地址。

  • Windows 虚拟机登录:Administrator / Change_me,或使用 ~/.ssh/pve_ssh。
  • Ubuntu 虚拟机登录:erolleman,使用 ~/.ssh/pve_ssh。sudo 无需密码。docker 需要 sudo。
  • Proxmox Web UI 在 LAN 上监听于 https://10.115.64.44:8006。此隧道仅为 SSH。通过 $PVE 使用 qm 和 pvesh 管理主机。
  • 将密钥材料保存在上述文件中。不要将 ~/.ssh/pve_ssh 或 PVE_SSH_PRIVATE_B64 读入命令、日志或回复中。不要生成替代密钥。

通过 SSH 的 PowerShell 远程处理使用相同的跳转。将其添加到 ~/.ssh/config(仅限客户机 Host 块;系统文件已覆盖隧道主机):

Host 10.115.64.* 10.20.0.*
  IdentityFile ~/.ssh/pve_ssh
  IdentitiesOnly yes
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null
  ProxyCommand ssh -o StrictHostKeyChecking=accept-new -W %h:%p eric-pve-ssh.eag.tools
Enter-PSSession -HostName <ip> -UserName Administrator -KeyFilePath "$HOME/.ssh/pve_ssh"

硬性规则

  • 绝不要启动、修改、覆盖克隆或删除虚拟机 100(ubuntu-2404)或虚拟机 101(ws2025-template)。两者都是模板。
  • 除非用户明确要求,否则不要更改主机配置(存储、网络、SDN、软件包)。
  • 不要在克隆上重新运行 sysprep、windows-template/Copy-SysprepFiles.ps1 或 ubuntu-template/cloud-init-prepare.sh。这些脚本用于准备模板,且保留在工作站上。它们不在此环境中。
  • 为你创建的每个虚拟机打上 ai-test 标签。
  • 测试完成后,询问用户是否销毁你创建的虚拟机。未得到用户回答前,绝不要销毁任何虚拟机。
  • 不要打开直接 SSH 会话到 10.115.64.44、10.115.64.x 或 10.20.0.x。这些网络不会路由到云代理。主机命令通过 eric-pve-ssh.eag.tools 执行。客户机命令使用上述 ProxyCommand 跳转。

主机信息

该主机是一个 Hyper-V 虚拟机。嵌套 VT-x 已暴露。在 LAN 上,其地址为 10.115.64.44。

项目值
硬件Intel Xeon Gold 6234(8 核 / 16 线程),94 GB RAM。请据此预算虚拟机资源。
vmbr0LAN 桥接,DHCP。主机地址 10.115.64.44/24,网关和 DNS 10.115.64.1,搜索域 eag.lan。两个模板的 NIC 都在此桥接上。客户机地址为 10.115.64.x。从此环境通过 eric-pve-ssh.eag.tools 跳转 SSH 到它们。
nat0SDN VNet(简单区域 nat),10.20.0.0/24。网关 10.20.0.1。DHCP 10.20.0.100–10.20.0.200(12 小时),由主机上的 dnsmasq 提供,DNS 10.20.0.1。SNAT 通过 vmbr0 出站,地址为 10.115.64.44。Proxmox 主机可以访问此子网。从此环境,使用相同的跳转 SSH 到 10.20.0.x。
local-dataVG vmdata 上的 LVM-thin,约 671 GB。虚拟机磁盘、EFI、TPM 和 cloud-init 驱动器。
local-lvm小型 PVE 系统 VG 上的 LVM-thin,约 23 GB,空。保持未使用。
local根文件系统上的目录。备份、容器模板、导入。
isos目录 /mnt/isos。仅安装 ISO。

选择模板

需求克隆
Windows、RDP 或 Windows PowerShell101 ws2025-template
Linux、Docker、pwsh 或 Nushell100 ubuntu-2404

如果用户未指定操作系统,请先询问再克隆。

Windows 克隆会启用客户机内的 RDP。Cloudflare 隧道承载 SSH。使用 SSH 或 PowerShell 远程处理访问客户机。

模板:ws2025-template(VMID 101)

Windows Server 2025 Datacenter Evaluation。4 vCPU(host),4 GB RAM,UEFI + Secure Boot + TPM 2.0,local-data 上的 64 GB VirtIO SCSI 磁盘,vmbr0 上的 VirtIO NIC(4 队列),已安装 VirtIO 驱动程序和 QEMU Guest Agent。

首次启动时,每个克隆会自动:

  • 获取随机计算机名、太平洋时区、en-US 区域设置和 Administrator 密码 Change_me。
  • 自动登录一次并运行 Initialize-WindowsServer.ps1,该脚本从 GitHub 安装最新的 PowerShell 7,启用带有 powershell 子系统的 OpenSSH 服务器(通过 SSH 的 PS 远程处理),将 SSH 密钥添加到 administrators_authorized_keys,启用 RDP,将公共网络设置为私有,并移除 Ctrl+Alt+Del 要求。
  • 移除自动登录密码和应答文件,写入 C:\ProgramData\TemplateSetup\setup-complete,然后重启。

首次启动需要几分钟并需联网(下载 PowerShell 7)。日志:C:\ProgramData\TemplateSetup\Initialize-WindowsServer.log。

模板:ubuntu-2404(VMID 100)

Ubuntu 24.04.5 LTS。2 vCPU(x86-64-v2-AES),4 GB RAM,UEFI(Secure Boot 密钥未注册),无 TPM,local-data 上的 32 GB VirtIO SCSI 磁盘,vmbr0 上的 VirtIO NIC。已安装 QEMU Guest Agent、OpenSSH、PowerShell 7(pwsh)、Nushell(/usr/local/bin 上的 nu)和 Docker。未安装 Podman。时区为 UTC。

Cloud-init 已清理并仅限于 NoCloud 和 ConfigDrive 数据源。磁盘没有 netplan,因此在 Proxmox cloud-init 运行之前,克隆没有网络。erolleman 账户已在 sudo 组中,并已拥有项目公钥。SSH 是 socket 激活的。Guest Agent 在 virtio 端口出现时从 udev 启动。

Proxmox 生成的 user-data 还会创建一个锁定的 ubuntu 账户,没有 SSH 密钥。请以 erolleman 身份登录。

工作流程:创建测试虚拟机

- [ ] 1. 确认源虚拟机是模板
- [ ] 2. 克隆、配置、打标签、启动
- [ ] 3. 从 Guest Agent 获取 IP
- [ ] 4. 等待首次启动完成
- [ ] 5. 运行测试
- [ ] 6. 询问用户是否销毁虚拟机

1. 确认模板。 如果此命令无输出,则停止并告知用户。不要克隆非模板的虚拟机。

$PVE 'qm config 101 | grep ^template'   # Windows
$PVE 'qm config 100 | grep ^template'   # Ubuntu

2. 克隆、配置、打标签、启动。 链接克隆是默认选项。仅在虚拟机需要比模板存活更久时添加 --full --storage local-data。

克隆继承 4 vCPU / 4 GB(Windows)或 2 vCPU / 4 GB(Ubuntu)。当测试需要更多资源时,在启动前使用 qm set 修改克隆。保持模板不变。

Windows:

ID=$($PVE 'pvesh get /cluster/nextid')
$PVE "qm clone 101 $ID --name test-<用途> && qm set $ID --tags ai-test && qm start $ID"

Ubuntu:在首次启动前附加 cloud-init 驱动器。模板上的 ide2 是一个空 CD;替换它。--ciupgrade 0 跳过默认的完整软件包升级。没有 --ipconfig0 ip=dhcp,克隆将永远无法获取地址。

ID=$($PVE 'pvesh get /cluster/nextid')
$PVE "qm clone 100 $ID --name test-<用途> && qm set $ID --tags ai-test --ide2 local-data:cloudinit --citype nocloud --ipconfig0 ip=dhcp --ciupgrade 0 --boot order=scsi0 && qm start $ID"

隔离网络,不论操作系统:在启动前,将 NIC 放到 nat0 上。仅在用户希望将虚拟机脱离 LAN 时使用此选项。客户机地址将为 10.20.0.x。从此环境的 SSH 仍然使用访问部分中的跳转;Proxmox 主机才是能访问 nat0 的。

$PVE "qm set $ID --net0 virtio,bridge=nat0"
# 仅限 Ubuntu。Windows 自行 DHCP。将 Ubuntu DNS 指向 NAT 网关上的 dnsmasq。
$PVE "qm set $ID --ipconfig0 ip=dhcp --nameserver 10.20.0.1"

3. 获取 IP。 操作系统启动后,Guest Agent 会响应。每约 15 秒重试一次。对于 vmbr0 NIC 使用 10.115.64.x 地址,对于 nat0 使用 10.20.0.x 地址。

$PVE "qm guest cmd $ID network-get-interfaces" \
  | jq -r '.[]."ip-addresses"[]? | select(."ip-address-type"=="ipv4") | ."ip-address"' \
  | grep -vE '^(127\.|169\.254\.)'

4. 等待首次启动。 克隆会获得新的主机密钥,地址会被重用,因此客户机 SSH 会跳过主机密钥检查。跳转主机密钥已使用 accept-new 存储。

Windows:SSH 在安装过程中启动,脚本在其完成后重启虚拟机。当 setup-complete 存在且 Windows 自其写入后已再次启动时,虚拟机即准备就绪。

VMSSH="ssh -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -o ProxyCommand=\"$JUMP\" Administrator@$IP"
# -EncodedCommand (base64 UTF-16LE) 避免嵌套 bash/cmd/PowerShell 引号。
PS_CHECK=$(cat <<'EOF'
$m = Get-Item C:\ProgramData\TemplateSetup\setup-complete -ErrorAction SilentlyContinue
if ($m -and (Get-CimInstance Win32_OperatingSystem).LastBootUpTime -gt $m.LastWriteTime) { 'READY ' + (Get-Content $m.FullName) } else { 'WAITING' }
EOF
)
CHECK="powershell -NoProfile -EncodedCommand $(printf %s "$PS_CHECK" | iconv -t UTF-16LE | base64 -w0)"
until STATUS=$($VMSSH "$CHECK" 2>/dev/null | tr -d '\r'); [[ $STATUS == READY* ]]; do sleep 15; done
echo "$STATUS"

READY succeeded 表示安装完成且虚拟机已重启。如果显示 READY failed,请阅读日志并报告:

$VMSSH 'powershell -NoProfile -Command "Get-Content C:\ProgramData\TemplateSetup\Initialize-WindowsServer.log -Tail 30"'

Ubuntu:等待 cloud-init 报告 status: done。status: error 表示停止并阅读 /var/log/cloud-init-output.log。

VMSSH="ssh -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -o ProxyCommand=\"$JUMP\" erolleman@$IP"
until STATUS=$($VMSSH 'cloud-init status 2>/dev/null' | tr -d '\r'); [[ $STATUS == status:\ done || $STATUS == status:\ error ]]; do sleep 10; done
echo "$STATUS"

5. 运行测试。

Windows:默认 SSH shell 是 cmd.exe。

$VMSSH 'pwsh -NoProfile -Command "Get-ComputerInfo | Select-Object OsName, CsName"'

通过 SSH 的 PowerShell 远程处理(从云代理的 pwsh)使用访问部分中的 ~/.ssh/config 客户机块:

Enter-PSSession -HostName <ip> -UserName Administrator -KeyFilePath "$HOME/.ssh/pve_ssh"

Ubuntu:

$VMSSH 'pwsh -NoLogo -Command "$PSVersionTable.PSVersion.ToString()"'
$VMSSH 'sudo docker info --format "{{.ServerVersion}}"'

6. 清理前询问。 报告测试结果,列出你创建的虚拟机(VMID、名称、IP),并询问用户是否销毁它们。在可用时使用 AskQuestion 工具,提供选项“销毁”、“保持运行”和“关闭但不销毁”(如果你创建了多个虚拟机,还可提供每个虚拟机的选择)。

如果用户选择销毁:

$PVE "qm stop $ID && qm destroy $ID --purge"

如果用户选择保持但关闭:

$PVE "qm shutdown $ID --timeout 120 || qm stop $ID"

当虚拟机被保留时,告知用户它们的 VMID,以便以后可以找到(它们保留 ai-test 标签)。

快照

两个模板的磁盘都在 LVM-thin 上,因此克隆支持快照:

$PVE "qm snapshot $ID before-test"
$PVE "qm rollback $ID before-test"
$PVE "qm delsnapshot $ID before-test"

清理和盘点

$PVE 'pvesh get /cluster/resources --type vm --output-format json' \
  | jq -r '.[] | select((.tags // "") | split(";") | index("ai-test")) | "\(.vmid)\t\(.name)\t\(.status)"'

只提供销毁你在本次会话中创建的 ai-test 虚拟机,除非用户要求更广泛的清理。始终先获得用户的确认。

注意事项

  • Windows 是评估版,具有 180 天许可。仅用于短期虚拟机。
  • 如果 Ubuntu 克隆在未附加 cloud-init 驱动器的情况下启动一次,将无法获取网络,且 cloud-init 不会干净地重试。销毁它并重新克隆。
  • 不要在 Windows 克隆上运行 sysprep,也不要将任一模板的克隆转换为模板。
  • 主机地址是 DHCP 租约。nat0 SNAT 固定为 10.115.64.44。如果该地址更改,请说明;除非用户要求,否则不要编辑 SDN。
  • cloudflared 由系统 SSH 配置调用为 /usr/local/bin/cloudflared。缺少密钥文件意味着启动脚本未运行;保持密钥不变并报告该情况。
  • 客户机主机密钥随每次克隆更改。UserKnownHostsFile=/dev/null 适用于客户机会话。隧道主机密钥保留在 ~/.ssh/known_hosts 中。

相关技能