Proxmox infra VmService : templates et accès
Table des matières
Introduction, contexte et objectifs
Cette documentation décrit comment l’équipe OPS prépare et maintient les templates Proxmox que VmService clone pour créer les machines des étudiants. Elle constitue le contrat entre l’infrastructure (OPS) et l’équipe backend (VmService) : toute modification d’un template, d’un identifiant ou d’un accès référencé ici peut casser le provisionnement.
Stratégie : clonage intégral d’un template Proxmox
EduKit n’importe pas de fichiers cloud-image .qcow2 au moment du provisionnement. À la place, OPS prépare une VM à partir d’une cloud-image, la convertit en template Proxmox (qm template <vmid>), et VmService réalise un clone intégral de ce template à chaque création de VM étudiant. Les raisons :
- Un appel API par VM au lieu d’une dizaine. Le clone est atomique ; l’import-from exige un upload de stockage, un import de disque et un câblage de configuration.
OsImage.ProxmoxTemplateIdreste naturel. La valeur est le VMID du template au format chaîne (par exemple"9999").- Mise en place simple côté OPS. Un template par OS ; on en ajoute quand on a besoin de nouvelles distributions.
- Évolutif. Des templates pré-préparés (image Python-dev, image data-science) s’intègrent sans aucune modification du backend.
Inventaire actuel
| VMID | OS | Nœud | Stockage | Statut | Responsable |
|---|---|---|---|---|---|
| 9999 | Debian 12 (cloud-init) | pve4 | local-lvm | Template | OPS |
Ubuntu n’est pas encore disponible. Pour l’ajouter, OPS doit créer une nouvelle VM à partir d’une cloud-image Ubuntu, la convertir en template, et communiquer le VMID à l’équipe backend.
Préparer un nouveau template cloud-image
À exécuter sur le nœud Proxmox (ici pve4). Remplacer <VMID> par le prochain id libre, <URL> par l’URL de la cloud-image, et <STORAGE> par le stockage cible (typiquement local-lvm).
# 1. Télécharger la cloud-image
cd /var/lib/vz/template/iso
wget <URL> -O <os>-cloudimg.qcow2
# 2. Créer la VM porteuse
qm create <VMID> \
--name <os>-cloud-template \
--memory 2048 --cores 2 \
--net0 virtio,bridge=vmbr0 \
--scsihw virtio-scsi-pci \
--agent enabled=1,fstrim_cloned_disks=1 \
--serial0 socket --vga serial0
# 3. Importer le disque
qm importdisk <VMID> /var/lib/vz/template/iso/<os>-cloudimg.qcow2 <STORAGE>
qm set <VMID> --scsi0 <STORAGE>:vm-<VMID>-disk-0
# 4. Attacher un lecteur cloud-init (emplacement ide2)
qm set <VMID> --ide2 <STORAGE>:cloudinit
# 5. Configurer l'ordre de boot et la console série (cloud-init exige la série sur certaines images)
qm set <VMID> --boot order=scsi0
qm set <VMID> --ipconfig0 ip=dhcp
# 6. Convertir en template Proxmox
qm template <VMID>
# 7. Vérifier
qm config <VMID> | grep -E '^(template|agent|scsi0|ide2|boot):'
# Attendu : template: 1, agent: enabled=1,fstrim_cloned_disks=1, scsi0: <storage>:..., ide2: <storage>:cloudinit
Après conversion, la VM ne peut plus être démarrée : elle devient une source de clonage uniquement.
Déclarer le template dans VmService
Une fois le template confirmé par OPS, ajouter l’enregistrement OsImage correspondant dans VmService :
new OsImage(
name: "Ubuntu 24.04 (cloud-init)",
proxmoxTemplateId: "9998", // VMID au format chaîne
architecture: CpuArchitecture.X86_64,
minDiskSizeGb: 4,
minRamMb: 512,
description: "Ubuntu 24.04 LTS cloud-init template")
Voir Edukit-vmservice/VmService/Infrastructure/Persistence/Seed/ApplicationDbContextSeed.cs.
Accès et identifiants
VmService interagit avec Proxmox par deux canaux. Les deux sont stockés dans Vaultwarden.
| Canal | Usage | Identifiant | Entrée Vaultwarden |
|---|---|---|---|
| API HTTPS | Clone, config, resize, start, delete, agent invité | Token API edukit-api-dev@pve!vm-service |
vmservice-proxmox-api-token |
| SSH / SFTP | Déposer les snippets cloud-init dans /var/lib/vz/snippets/ |
Clé ed25519 du compte de service edukit-deploy sur le port 2244 |
vmservice-proxmox-ssh |
La clé SSH est réservée au service : pas de connexion humaine, pas de shell partagé. Toute personne qui a besoin d’un accès SSH au nœud Proxmox utilise sa propre clé.
Privilèges requis du token API
Le rôle Proxmox lié au token edukit-api-dev@pve!vm-service doit porter l’ensemble des privilèges suivants :
| Privilège | Pour quoi faire |
|---|---|
VM.Audit |
Lire la configuration et le statut des VM |
VM.Allocate |
Créer la VM clonée |
VM.Config.* |
Configurer cores, mémoire, cicustom, tags, disque |
VM.Console |
Console série |
VM.Migrate |
Opérations de placement |
VM.Monitor |
Lire l’état d’exécution |
VM.PowerMgmt |
Démarrer et arrêter les VM |
Datastore.Allocate |
Allouer le stockage du clone |
Datastore.AllocateSpace |
Allouer l’espace disque du clone |
Datastore.Audit |
Lire l’état du stockage (contrôles de capacité) |
VM.GuestAgent.Audit |
Lire l’IP via agent/network-get-interfaces |
VM.GuestAgent.Unrestricted |
Réinitialiser le mot de passe via agent/set-user-password |
Les deux derniers privilèges pilotent l’agent invité (qemu-guest-agent) :
VM.GuestAgent.Auditest nécessaire àGET .../agent/network-get-interfaces. Sans lui, Proxmox renvoie un403, VmService ne récupère jamais l’adresse IP de la VM et celle-ci reste vide.VM.GuestAgent.Unrestrictedest nécessaire àPOST .../agent/set-user-password, utilisé par l’endpoint de réinitialisation des identifiants. Sans lui, la réinitialisation renvoie un500(consécutif à un403Proxmox).
Le qemu-guest-agent doit être installé et démarré dans la VM pour que la lecture d’IP et la réinitialisation de mot de passe fonctionnent. Le template l’active déjà (--agent enabled=1 à la création, paquet qemu-guest-agent installé par cloud-init au premier boot).
Certificat TLS
VmService dialogue avec l’API Proxmox en HTTPS. La validation du certificat est pilotée par le flag Proxmox:VerifySsl :
| Environnement | Certificat Proxmox | Proxmox:VerifySsl |
Justification |
|---|---|---|---|
| dev / lab | Auto-signé (par défaut Proxmox) | false |
Les clusters de lab ne justifient pas une vraie autorité. VmService contourne la validation uniquement parce que le flag l’autorise. |
| staging / prod | Signé par une autorité de confiance (Let’s Encrypt, CA interne, etc.) | true (défaut) |
La production dialogue avec une vraie chaîne de confiance, sans exception. |
Mise en place en production : OPS doit provisionner un certificat TLS valide sur le ou les nœuds Proxmox auxquels VmService se connecte (via pvenode cert set ou l’interface Proxmox, section Datacenter puis ACME). Le CN/SAN du certificat doit correspondre au nom d’hôte utilisé par VmService dans Proxmox:BaseUrl.
Proxmox:VerifySsl=false est destiné uniquement aux configurations de lab auto-signées. Le passer à false en production désactive silencieusement tous les contrôles de certificat et ne doit jamais être fait. En défense en profondeur, la couche d’injection de dépendances de VmService refuse d’installer le handler de contournement dans un environnement Production.
ASPNETCORE_ENVIRONMENT : la garde de défense en profondeur ci-dessus lit IHostEnvironment.IsProduction(), qui dépend de la variable d’environnement ASPNETCORE_ENVIRONMENT au runtime :
- Les déploiements K3s / prod doivent tourner avec
ASPNETCORE_ENVIRONMENT=Production(ou laisser la variable non définie : la valeur par défaut .NET est déjàProduction). Ne jamais hériter d’unDevelopmentprovenant du manifeste d’un autre environnement. - Les conteneurs dev / staging peuvent positionner
DevelopmentouStagingselon le cas. - La valeur est journalisée au démarrage ; vérifier dans les logs du pod la ligne
Running in environment: Production.
Changements qui cassent VmService
Se coordonner avec l’équipe backend avant d’effectuer l’une de ces actions :
- Supprimer ou renuméroter un template dont le VMID est référencé par une ligne
OsImage(VmService échoue au clonage). - Désactiver le lecteur
cloudinitd’un template existant. - Révoquer le token API
edukit-api-dev@pve!vm-serviceou faire tourner son secret sans mettre à jour le secret K3s. - Retirer l’un des privilèges du token, en particulier
VM.GuestAgent.Audit(plus d’IP) ouVM.GuestAgent.Unrestricted(plus de réinitialisation de mot de passe). - Changer le port SSH, le nom d’utilisateur ou les
authorized_keysdeedukit-deploy. - Déplacer
/var/lib/vz/snippets/vers un autre chemin ou retirer le droit d’écriture àedukit-deploy.