eageric/cursor-cloud-eag

Crée, connecte et nettoie des machines virtuelles de test jetables sur le serveur EAG Proxmox VE via le tunnel SSH Cloudflare Access à eric-pve-ssh.eag.tools.

Qu'est-ce que cursor-cloud-eag ?

Cette compétence permet à un agent IA (tel que Claude Code, Cursor ou Codex) de gérer des machines virtuelles de test éphémères sur un serveur Proxmox VE distant, accessible uniquement via un tunnel SSH Cloudflare Access. Elle est conçue pour l'hôte 'eric-pve-ssh.eag.tools' qui héberge deux modèles : un Windows Server 2025 (VMID 101) et un Ubuntu 24.04 (VMID 100). L'agent peut cloner ces modèles, configurer les clones (mémoire, CPU, réseau), démarrer la VM, attendre la fin du premier démarrage, exécuter des tests via SSH (avec saut via l'hôte tunnel), puis demander à l'utilisateur s'il faut détruire la VM. La compétence gère également les snapshots, l'inventaire des VMs marquées 'ai-test', et les particularités de chaque système d'exploitation (connexion Windows via PowerShell Remoting, cloud-init pour Ubuntu). Les règles strictes empêchent de modifier les modèles ou de détruire des VMs sans confirmation explicite de l'utilisateur.

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

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

EAG Proxmox via le tunnel SSH Cloudflare

Le serveur Proxmox VE 9.2 héberge des machines virtuelles de test jetables. Depuis cet environnement, l'hôte est eric-pve-ssh.eag.tools. Les agents clonent un modèle, exécutent le test, puis demandent avant de supprimer quoi que ce soit.

Les modèles, les étapes de clonage et les connexions aux invités correspondent à l'environnement LAN. Ce qui change, c'est le chemin : l'agent cloud atteint l'hôte via Cloudflare Access, et atteint chaque invité en passant par cet hôte.

Accès

Le script de démarrage de l'environnement écrit la paire de clés à partir de PVE_SSH_PRIVATE_B64 et PVE_SSH_PUBLIC_KEY :

FichierModeUtilisation
~/.ssh/pve_ssh600Clé privée. Hôte Proxmox, Windows Administrator, Ubuntu erolleman.
~/.ssh/pve_ssh.pub644Clé publique correspondante.

/etc/ssh/ssh_config.d/eric-pve-ssh.conf définit déjà User root, IdentityFile ~/.ssh/pve_ssh, IdentitiesOnly yes, et ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h pour eric-pve-ssh.eag.tools. Utilisez cet alias d'hôte. Laissez le fichier système en place.

KEY="$HOME/.ssh/pve_ssh"
test -r "$KEY" || { echo "$KEY manquant ; le script de démarrage le crée à partir de PVE_SSH_PRIVATE_B64" >&2; exit 1; }
PVE="ssh -o StrictHostKeyChecking=accept-new eric-pve-ssh.eag.tools"
$PVE 'qm list'

SSH invité, pour 10.115.64.x (vmbr0) et 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"

Définissez USER sur Administrator ou erolleman et IP sur l'adresse de l'invité avant de développer VMSSH.

  • Connexion VM Windows : Administrator / Change_me, ou ~/.ssh/pve_ssh.
  • Connexion VM Ubuntu : erolleman avec ~/.ssh/pve_ssh. sudo est sans mot de passe. docker nécessite sudo.
  • L'interface Web Proxmox écoute sur le LAN à https://10.115.64.44:8006. Ce tunnel est réservé à SSH. Administrez l'hôte avec qm et pvesh via $PVE.
  • Gardez le matériel de clé dans les fichiers ci-dessus. Ne lisez ni ~/.ssh/pve_ssh ni PVE_SSH_PRIVATE_B64 dans une commande, un journal ou une réponse. Ne générez pas de clé de remplacement.

PowerShell à distance via SSH utilise le même saut. Ajoutez ceci à ~/.ssh/config (uniquement le bloc Host de l'invité ; le fichier système couvre déjà l'hôte du tunnel) :

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"

Règles strictes

  • Ne jamais démarrer, modifier, cloner par-dessus ou supprimer la VM 100 (ubuntu-2404) ou la VM 101 (ws2025-template). Ce sont des modèles.
  • Ne pas modifier la configuration de l'hôte (stockage, réseau, SDN, paquets) sauf demande explicite de l'utilisateur.
  • Ne pas réexécuter sysprep, windows-template/Copy-SysprepFiles.ps1 ou ubuntu-template/cloud-init-prepare.sh sur un clone. Ces scripts préparent les modèles et restent sur le poste de travail. Ils ne sont pas dans cet environnement.
  • Taguez chaque VM que vous créez avec ai-test.
  • Lorsque les tests sont terminés, demandez à l'utilisateur s'il faut détruire les VMs que vous avez créées. Ne détruisez jamais une VM sans la réponse de l'utilisateur.
  • N'ouvrez pas de session SSH directe vers 10.115.64.44, 10.115.64.x ou 10.20.0.x. Ces réseaux ne sont pas routés vers l'agent cloud. Les commandes hôte passent par eric-pve-ssh.eag.tools. Les commandes invité utilisent le saut ProxyCommand ci-dessus.

Informations sur l'hôte

L'hôte est une machine virtuelle Hyper-V. La virtualisation imbriquée VT-x est exposée. Sur le LAN, son adresse est 10.115.64.44.

ÉlémentValeur
MatérielIntel Xeon Gold 6234 (8 cœurs / 16 threads), 94 Go de RAM. Dimensionnez les VMs en conséquence.
vmbr0Pont LAN, DHCP. Adresse hôte 10.115.64.44/24, passerelle et DNS 10.115.64.1, domaine de recherche eag.lan. Les cartes réseau des deux modèles sont sur ce pont. Les adresses invitées sont 10.115.64.x. Depuis cet environnement, SSH vers elles passe par eric-pve-ssh.eag.tools.
nat0VNet SDN (zone simple nat), 10.20.0.0/24. Passerelle 10.20.0.1. DHCP 10.20.0.100–10.20.0.200 (12 h) depuis dnsmasq sur l'hôte, DNS 10.20.0.1. SNAT sortie vmbr0 en tant que 10.115.64.44. L'hôte Proxmox peut atteindre ce sous-réseau. Depuis cet environnement, SSH vers 10.20.0.x utilise le même saut.
local-dataLVM-thin sur VG vmdata, ~671 Go. Disques VM, EFI, TPM et disques cloud-init.
local-lvmLVM-thin sur le petit VG système PVE, ~23 Go, vide. Laissez-le inutilisé.
localRépertoire sur le système de fichiers racine. Sauvegardes, modèles de conteneurs, importations.
isosRépertoire /mnt/isos. ISO d'installation uniquement.

Quel modèle

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

Si l'utilisateur ne précise pas de système d'exploitation, demandez avant de cloner.

Les clones Windows activent RDP à l'intérieur de l'invité. Le tunnel Cloudflare transporte SSH. Utilisez SSH ou PowerShell à distance pour atteindre l'invité.

Modèle : ws2025-template (VMID 101)

Windows Server 2025 Datacenter Evaluation. 4 vCPU (host), 4 Go de RAM, UEFI + Secure Boot + TPM 2.0, disque SCSI VirtIO de 64 Go sur local-data, carte réseau VirtIO sur vmbr0 (4 files d'attente), pilotes VirtIO et agent invité QEMU installés.

Au premier démarrage, chaque clone automatiquement :

  • Obtient un nom d'ordinateur aléatoire, fuseau horaire Pacifique, locale en-US, et mot de passe Administrateur Change_me.
  • Se connecte automatiquement une fois et exécute Initialize-WindowsServer.ps1, qui installe la dernière version de PowerShell 7 depuis GitHub, active le serveur OpenSSH avec un sous-système powershell (PS à distance via SSH), ajoute la clé SSH à administrators_authorized_keys, active RDP, définit les réseaux Publics sur Privé, et supprime l'exigence Ctrl+Alt+Del.
  • Supprime le mot de passe de connexion automatique et le fichier de réponses, écrit C:\ProgramData\TemplateSetup\setup-complete, puis redémarre.

Le premier démarrage prend plusieurs minutes et nécessite internet (téléchargement de PowerShell 7). Journal : C:\ProgramData\TemplateSetup\Initialize-WindowsServer.log.

Modèle : ubuntu-2404 (VMID 100)

Ubuntu 24.04.5 LTS. 2 vCPU (x86-64-v2-AES), 4 Go de RAM, UEFI (clés Secure Boot non inscrites), pas de TPM, disque SCSI VirtIO de 32 Go sur local-data, carte réseau VirtIO sur vmbr0. Agent invité QEMU, OpenSSH, PowerShell 7 (pwsh), Nushell (nu sur /usr/local/bin) et Docker sont installés. Podman n'est pas installé. Le fuseau horaire est UTC.

Cloud-init a été nettoyé et limité aux sources de données NoCloud et ConfigDrive. Le disque n'a pas de netplan, donc un clone n'a pas de réseau tant que Proxmox cloud-init ne s'exécute pas. Le compte erolleman est déjà dans sudo et possède déjà la clé publique du projet. SSH est activé par socket. L'agent invité démarre depuis udev lorsque le port virtio apparaît.

Les user-data générées par Proxmox créent également un compte ubuntu verrouillé sans clé SSH. Connectez-vous en tant que erolleman.

Workflow : créer une VM de test

- [ ] 1. Confirmer que la VM source est un modèle
- [ ] 2. Cloner, configurer, taguer, démarrer
- [ ] 3. Obtenir l'IP depuis l'agent invité
- [ ] 4. Attendre la fin du premier démarrage
- [ ] 5. Exécuter le test
- [ ] 6. Demander à l'utilisateur s'il faut détruire la VM

1. Confirmer le modèle. Si cela n'affiche rien, arrêtez et informez l'utilisateur. Ne clonez pas une VM qui n'est pas un modèle.

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

2. Cloner, configurer, taguer, démarrer. Les clones liés sont par défaut. Ajoutez --full --storage local-data uniquement lorsque la VM doit survivre au modèle.

Les clones héritent de 4 vCPU / 4 Go (Windows) ou 2 vCPU / 4 Go (Ubuntu). Lorsque le test nécessite plus, utilisez qm set sur le clone avant de le démarrer. Laissez les modèles inchangés.

Windows :

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

Ubuntu : attachez le disque cloud-init avant le premier démarrage. ide2 sur le modèle est un CD vide ; remplacez-le. --ciupgrade 0 ignore la mise à jour complète des paquets par défaut. Sans --ipconfig0 ip=dhcp, le clone n'obtient jamais d'adresse.

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

Réseau isolé, pour les deux OS : avant le démarrage, placez la carte réseau sur nat0. Gardez cela uniquement lorsque l'utilisateur souhaite que la VM soit hors du LAN. L'adresse de l'invité sera 10.20.0.x. SSH depuis cet environnement utilise toujours le saut dans Accès ; l'hôte Proxmox est celui qui peut atteindre nat0.

$PVE "qm set $ID --net0 virtio,bridge=nat0"
# Ubuntu uniquement. Windows obtient un DHCP tout seul. Pointez le DNS Ubuntu vers dnsmasq sur la passerelle NAT.
$PVE "qm set $ID --ipconfig0 ip=dhcp --nameserver 10.20.0.1"

3. Obtenir l'IP. L'agent invité répond une fois que l'OS est opérationnel. Réessayez toutes les ~15 s. Utilisez l'adresse 10.115.64.x pour une carte réseau vmbr0, ou l'adresse 10.20.0.x pour 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. Attendre le premier démarrage. Les clones obtiennent de nouvelles clés d'hôte et les adresses sont réutilisées, donc SSH invité ignore la vérification des clés d'hôte. La clé de l'hôte de saut est stockée avec accept-new.

Windows : SSH se met en place pendant l'installation, et le script redémarre la VM à la fin. La VM est prête une fois que setup-complete existe et que Windows a redémarré depuis son écriture.

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) évite les guillemets imbriqués 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 signifie que l'installation est terminée et que la VM a redémarré. Si elle affiche READY failed, lisez le journal et signalez-le :

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

Ubuntu : attendez que cloud-init signale status: done. status: error signifie qu'il faut arrêter et lire /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. Exécuter le test.

Windows : le shell SSH par défaut est cmd.exe.

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

PowerShell à distance via SSH (depuis pwsh sur l'agent cloud) utilise le bloc invité ~/.ssh/config dans Accès :

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. Demander avant de nettoyer. Rapportez les résultats des tests, listez les VMs que vous avez créées (VMID, nom, IP), et demandez à l'utilisateur s'il faut les détruire. Utilisez l'outil AskQuestion lorsque disponible, avec les options "Détruire", "Garder en cours d'exécution" et "Éteindre mais garder" (plus des choix par VM si vous en avez créé plusieurs).

Si l'utilisateur choisit de détruire :

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

Si l'utilisateur choisit de garder mais d'éteindre :

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

Lorsque les VMs sont conservées, indiquez à l'utilisateur leurs VMIDs afin qu'elles puissent être retrouvées ultérieurement (elles conservent le tag ai-test).

Instantanés

Les disques des deux modèles sont sur LVM-thin, donc les clones prennent en charge les instantanés :

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

Nettoyage et inventaire

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

Proposez de détruire uniquement les VMs ai-test que vous avez créées dans cette session, sauf si l'utilisateur demande un nettoyage plus large. Obtenez toujours la confirmation de l'utilisateur au préalable.

Pièges

  • Windows est une édition d'évaluation avec une licence de 180 jours. Utilisez-la pour des VMs éphémères.
  • Un clone Ubuntu qui démarre une fois sans le disque cloud-init se retrouve sans réseau, et cloud-init ne réessaiera pas proprement. Détruisez-le et clonez à nouveau.
  • N'exécutez pas sysprep sur les clones Windows et ne convertissez pas les clones de l'un ou l'autre modèle en modèles.
  • L'adresse de l'hôte est un bail DHCP. Le SNAT de nat0 est épinglé à 10.115.64.44. Si cette adresse change, dites-le ; ne modifiez pas le SDN sauf demande de l'utilisateur.
  • cloudflared est invoqué en tant que /usr/local/bin/cloudflared par la configuration SSH système. Un fichier de clé manquant signifie que le script de démarrage ne s'est pas exécuté ; ne touchez pas aux secrets et signalez-le.
  • Les clés d'hôte des invités changent à chaque clone. UserKnownHostsFile=/dev/null s'applique à la session invitée. La clé d'hôte du tunnel reste dans ~/.ssh/known_hosts.

Skills associés