eageric/cursor-cloud-eag

Cria, conecta e limpa VMs de teste descartáveis no servidor EAG Proxmox VE através do túnel SSH Cloudflare Access em eric-pve-ssh.eag.tools.

O que é cursor-cloud-eag?

Esta skill capacita agentes de IA a gerenciar máquinas virtuais de teste em um servidor Proxmox VE remoto, acessível exclusivamente via túnel SSH Cloudflare Access. Ela suporta a clonagem de dois templates principais: Windows Server 2025 (VMID 101) e Ubuntu 24.04 LTS (VMID 100), com configuração automática de primeira inicialização, obtenção de endereço IP via agente convidado e execução de comandos através de um salto SSH. A skill impõe regras rígidas para proteger os templates, exigir confirmação do usuário antes de destruir VMs e evitar modificações na configuração do host. Ela também fornece fluxos de trabalho detalhados para criação, teste e limpeza de VMs, incluindo snapshots e inventário, sendo ideal para ambientes de desenvolvimento e teste que necessitam de VMs efêmeras e isoladas.

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

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

EAG Proxmox através do túnel SSH Cloudflare

O servidor Proxmox VE 9.2 hospeda VMs de teste descartáveis. Neste ambiente, o host é eric-pve-ssh.eag.tools. Os agentes clonam um template, executam o teste e, em seguida, perguntam antes de excluir qualquer coisa.

Os templates, as etapas de clonagem e os logins convidados correspondem ao ambiente de LAN. O que muda é o caminho: o agente na nuvem alcança o host através do Cloudflare Access e alcança cada convidado saltando por esse host.

Acesso

O script de inicialização do ambiente escreve o par de chaves de PVE_SSH_PRIVATE_B64 e PVE_SSH_PUBLIC_KEY:

ArquivoModoUso
~/.ssh/pve_ssh600Chave privada. Host Proxmox, Windows Administrator, Ubuntu erolleman.
~/.ssh/pve_ssh.pub644Chave pública correspondente.

/etc/ssh/ssh_config.d/eric-pve-ssh.conf já define User root, IdentityFile ~/.ssh/pve_ssh, IdentitiesOnly yes e ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h para eric-pve-ssh.eag.tools. Use esse alias de host. Deixe o arquivo de sistema no lugar.

KEY="$HOME/.ssh/pve_ssh"
test -r "$KEY" || { echo "$KEY ausente; o script de inicialização o cria a partir de PVE_SSH_PRIVATE_B64" >&2; exit 1; }
PVE="ssh -o StrictHostKeyChecking=accept-new eric-pve-ssh.eag.tools"
$PVE 'qm list'

SSH para convidados, tanto para 10.115.64.x (vmbr0) quanto para 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"

Defina USER como Administrator ou erolleman e IP como o endereço do convidado antes de expandir VMSSH.

  • Login VM Windows: Administrator / Change_me, ou ~/.ssh/pve_ssh.
  • Login VM Ubuntu: erolleman com ~/.ssh/pve_ssh. sudo não requer senha. docker precisa de sudo.
  • A interface web do Proxmox escuta na LAN em https://10.115.64.44:8006. Este túnel é apenas SSH. Administre o host com qm e pvesh através de $PVE.
  • Mantenha o material da chave nos arquivos acima. Não leia ~/.ssh/pve_ssh nem PVE_SSH_PRIVATE_B64 em um comando, log ou resposta. Não gere chave de substituição.

O PowerShell remoto sobre SSH usa o mesmo salto. Adicione isso a ~/.ssh/config (apenas o bloco Host do convidado; o arquivo de sistema já cobre o host do túnel):

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"

Regras rígidas

  • Nunca iniciar, modificar, clonar sobre ou excluir a VM 100 (ubuntu-2404) ou a VM 101 (ws2025-template). Ambas são templates.
  • Não alterar a configuração do host (armazenamento, rede, SDN, pacotes) a menos que o usuário peça explicitamente.
  • Não executar novamente sysprep, windows-template/Copy-SysprepFiles.ps1 ou ubuntu-template/cloud-init-prepare.sh em um clone. Esses scripts preparam os templates e permanecem na estação de trabalho. Eles não estão neste ambiente.
  • Marcar cada VM que você criar com ai-test.
  • Quando o teste terminar, perguntar ao usuário se deve destruir as VMs que você criou. Nunca destruir uma VM sem a resposta do usuário.
  • Não abrir sessão SSH direta para 10.115.64.44, 10.115.64.x ou 10.20.0.x. Essas redes não são roteadas para o agente na nuvem. Os comandos do host vão através de eric-pve-ssh.eag.tools. Os comandos do convidado usam o salto ProxyCommand acima.

Fatos do host

O host é uma máquina virtual Hyper-V. VT-x aninhado está exposto. Na LAN, seu endereço é 10.115.64.44.

ItemValor
HardwareIntel Xeon Gold 6234 (8 núcleos / 16 threads), 94 GB de RAM. Dimensione as VMs de acordo.
vmbr0Ponte LAN, DHCP. Endereço do host 10.115.64.44/24, gateway e DNS 10.115.64.1, domínio de pesquisa eag.lan. As NICs de ambos os templates estão nesta ponte. Os endereços dos convidados são 10.115.64.x. Deste ambiente, o SSH para eles salta através de eric-pve-ssh.eag.tools.
nat0SDN VNet (zona simples nat), 10.20.0.0/24. Gateway 10.20.0.1. DHCP 10.20.0.100–10.20.0.200 (12 h) a partir do dnsmasq no host, DNS 10.20.0.1. SNAT para fora em vmbr0 como 10.115.64.44. O host Proxmox pode alcançar esta sub-rede. Deste ambiente, o SSH para 10.20.0.x usa o mesmo salto.
local-dataLVM-thin no VG vmdata, ~671 GB. Discos de VM, EFI, TPM e drives cloud-init.
local-lvmLVM-thin no pequeno VG do sistema PVE, ~23 GB, vazio. Deixe-o sem uso.
localDiretório no sistema de arquivos raiz. Backups, templates de contêiner, importações.
isosDiretório /mnt/isos. Apenas ISOs de instalação.

Qual template

NecessidadeClonar
Windows, RDP ou Windows PowerShell101 ws2025-template
Linux, Docker, pwsh ou Nushell100 ubuntu-2404

Se o usuário não disser qual SO, pergunte antes de clonar.

Os clones do Windows habilitam o RDP dentro do convidado. O túnel Cloudflare transporta SSH. Use SSH ou PowerShell remoto para alcançar o convidado.

Template: ws2025-template (VMID 101)

Windows Server 2025 Datacenter Evaluation. 4 vCPU (host), 4 GB RAM, UEFI + Secure Boot + TPM 2.0, 64 GB disco VirtIO SCSI em local-data, NIC VirtIO em vmbr0 (4 filas), drivers VirtIO e agente convidado QEMU instalados.

Na primeira inicialização, cada clone automaticamente:

  • Obtém um nome de computador aleatório, fuso horário do Pacífico, localidade en-US e senha do Administrador Change_me.
  • Faz login automático uma vez e executa Initialize-WindowsServer.ps1, que instala o PowerShell 7 mais recente do GitHub, habilita o servidor OpenSSH com um subsistema powershell (PS remoto sobre SSH), adiciona a chave SSH a administrators_authorized_keys, habilita RDP, define redes Públicas como Privadas e remove o requisito Ctrl+Alt+Del.
  • Remove a senha de login automático e o arquivo de resposta, escreve C:\ProgramData\TemplateSetup\setup-complete e então reinicia.

A primeira inicialização leva vários minutos e precisa de internet (download do PowerShell 7). Log: C:\ProgramData\TemplateSetup\Initialize-WindowsServer.log.

Template: ubuntu-2404 (VMID 100)

Ubuntu 24.04.5 LTS. 2 vCPU (x86-64-v2-AES), 4 GB RAM, UEFI (chaves Secure Boot não cadastradas), sem TPM, 32 GB disco VirtIO SCSI em local-data, NIC VirtIO em vmbr0. Agente convidado QEMU, OpenSSH, PowerShell 7 (pwsh), Nushell (nu em /usr/local/bin) e Docker estão instalados. Podman não está instalado. O fuso horário é UTC.

O cloud-init foi limpo e limitado às fontes de dados NoCloud e ConfigDrive. O disco não tem netplan, então um clone não tem rede até que o cloud-init do Proxmox seja executado. A conta erolleman já está no sudo e já possui a chave pública do projeto. O SSH é ativado por socket. O agente convidado inicia a partir do udev quando a porta virtio aparece.

O user-data gerado pelo Proxmox também cria uma conta ubuntu bloqueada, sem chave SSH. Faça login como erolleman.

Fluxo de trabalho: criar uma VM de teste

- [ ] 1. Confirmar que a VM de origem é um template
- [ ] 2. Clonar, configurar, marcar, iniciar
- [ ] 3. Obter o IP do agente convidado
- [ ] 4. Aguardar até que a primeira inicialização termine
- [ ] 5. Executar o teste
- [ ] 6. Perguntar ao usuário se deve destruir a VM

1. Confirmar o template. Se isso não imprimir nada, pare e avise o usuário. Não clone uma VM que não seja um template.

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

2. Clonar, configurar, marcar, iniciar. Clones vinculados são o padrão. Adicione --full --storage local-data apenas quando a VM precisar sobreviver ao template.

Os clones herdam 4 vCPU / 4 GB (Windows) ou 2 vCPU / 4 GB (Ubuntu). Quando o teste precisar de mais, use qm set no clone antes de iniciá-lo. Deixe os templates inalterados.

Windows:

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

Ubuntu: anexe o drive cloud-init antes da primeira inicialização. ide2 no template é um CD vazio; substitua-o. --ciupgrade 0 pula a atualização completa padrão de pacotes. Sem --ipconfig0 ip=dhcp o clone nunca obtém um endereço.

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

Rede isolada, para qualquer SO: antes de iniciar, coloque a NIC em nat0. Mantenha isso apenas quando o usuário quiser a VM fora da LAN. O endereço do convidado será 10.20.0.x. O SSH deste ambiente ainda usa o salto em Acesso; o host Proxmox é quem pode alcançar nat0.

$PVE "qm set $ID --net0 virtio,bridge=nat0"
# Apenas Ubuntu. O Windows faz DHCP por conta própria. Aponte o DNS do Ubuntu para o dnsmasq no gateway NAT.
$PVE "qm set $ID --ipconfig0 ip=dhcp --nameserver 10.20.0.1"

3. Obter o IP. O agente convidado responde assim que o SO está ativo. Repita a cada ~15 s. Use o endereço 10.115.64.x para uma NIC vmbr0, ou o endereço 10.20.0.x para nat0.

$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. Aguardar a primeira inicialização. Os clones obtêm novas chaves de host e os endereços são reutilizados, portanto o SSH do convidado ignora a verificação de chave de host. A chave do host de salto é armazenada com accept-new.

Windows: o SSH surge durante a configuração e o script reinicia a VM quando termina. A VM está pronta assim que setup-complete existe e o Windows foi reiniciado desde que foi escrito.

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) evita aninhamento de aspas 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 significa que a configuração terminou e a VM foi reiniciada. Se imprimir READY failed, leia o log e relate:

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

Ubuntu: aguarde até que o cloud-init relate status: done. status: error significa parar e ler /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. Executar o teste.

Windows: o shell SSH padrão é cmd.exe.

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

PowerShell remoto sobre SSH (a partir de pwsh no agente na nuvem) usa o bloco Host do convidado em ~/.ssh/config em Acesso:

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. Perguntar antes de limpar. Relate os resultados do teste, liste as VMs que você criou (VMID, nome, IP) e pergunte ao usuário se deseja destruí-las. Use a ferramenta AskQuestion quando disponível, com as opções "Destroy", "Keep running" e "Shut down but keep" (mais escolhas por VM se você criou várias).

Se o usuário escolher destruir:

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

Se o usuário escolher manter mas desligar:

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

Quando as VMs forem mantidas, informe ao usuário seus VMIDs para que possam ser encontradas posteriormente (elas mantêm a tag ai-test).

Snapshots

Os discos de ambos os templates estão em LVM-thin, portanto os clones suportam snapshots:

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

Limpeza e inventário

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

Ofereça-se para destruir apenas VMs ai-test que você criou nesta sessão, a menos que o usuário peça uma limpeza mais ampla. Sempre obtenha a confirmação do usuário primeiro.

Armadilhas

  • Windows é uma edição de avaliação com licença de 180 dias. Use-a para VMs de curta duração.
  • Um clone Ubuntu que inicializa uma vez sem o drive cloud-init fica sem rede e o cloud-init não tentará novamente de forma limpa. Destrua-o e clone novamente.
  • Não execute sysprep em clones Windows e não converta clones de nenhum dos templates em templates.
  • O endereço do host é uma concessão DHCP. O SNAT do nat0 está vinculado a 10.115.64.44. Se esse endereço mudar, informe; não edite o SDN a menos que o usuário peça.
  • cloudflared é invocado como /usr/local/bin/cloudflared pela configuração SSH do sistema. Um arquivo de chave ausente significa que o script de inicialização não foi executado; deixe os segredos intocados e relate isso.
  • As chaves de host do convidado mudam a cada clone. UserKnownHostsFile=/dev/null se aplica à sessão do convidado. A chave do host do túnel permanece em ~/.ssh/known_hosts.

Habilidades Relacionadas