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.ProxmoxTemplateId reste 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.Audit est nécessaire à GET .../agent/network-get-interfaces. Sans lui, Proxmox renvoie un 403, VmService ne récupère jamais l’adresse IP de la VM et celle-ci reste vide.
  • VM.GuestAgent.Unrestricted est nécessaire à POST .../agent/set-user-password, utilisé par l’endpoint de réinitialisation des identifiants. Sans lui, la réinitialisation renvoie un 500 (consécutif à un 403 Proxmox).

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’un Development provenant du manifeste d’un autre environnement.
  • Les conteneurs dev / staging peuvent positionner Development ou Staging selon 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 cloudinit d’un template existant.
  • Révoquer le token API edukit-api-dev@pve!vm-service ou 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) ou VM.GuestAgent.Unrestricted (plus de réinitialisation de mot de passe).
  • Changer le port SSH, le nom d’utilisateur ou les authorized_keys de edukit-deploy.
  • Déplacer /var/lib/vz/snippets/ vers un autre chemin ou retirer le droit d’écriture à edukit-deploy.

Sources


Retour en haut