Proxmox VM Self Service (PVMSS)

PVMSS est une application web qui simplifie la création de machine virtuelle pour les utilisateurs sans passer par l’interface web ou la ligne de commande de Proxmox VE.

En laissant le choix des paramètres tels que la quantité de processeurs virtuels et de mémoire vive, la taille du stockage virtuel, l’image ISO de démarrage, l’utilisateur sera autonome et en mesure de créer autant de machine virtuelle qui lui est autorisé par les administrateurs. PVMSS est compatible avec Proxmox VE 9.0 et supérieur. Il n’est pas compatible avec les versions 8 et inférieur à cause des rôles qui ont changés dans PVE.

Contexte#

Mon constat en juin 2025, après plus de 10 ans à observer et à répondre aux besoins dans différentes situations où j’ai utilisé Proxmox, est qu’il manque une interface de création de machine virtuelle à la demande.

Plus récemment, des collègues m’ont demandé des machines pour effectuer des tests et être autonomes, ce que je ne pouvais leur fournir à la demande, à la minute.

C’est ainsi que j’ai eu l’idée de “Proxmox VM Self-Service” (abrégé PVMSS). PVMSS ne prend pas en charge les conteneurs LXC de PVE.

Pourquoi ne pas utiliser directement la console web de Proxmox ?#

La création de machine virtuelle dans PVE s’effectue via l’interface web après s’être authentifié, ou par ligne de commande.

En tant qu’utilisateur, vous pouvez créer des machines virtuelles via l’interface web, encore faut-il que les administrateurs aient prévu les accès et les droits.

Toutefois, pour les non-initiés, l’interface web de création de machine virtuelle de Proxmox peut être déroutante, voire inexploitable. Il y a de nombreux paramètres à choisir sans que vous puissiez savoir rapidement à quoi ça sert. L’interface web de Proxmox est réservée aux initiés (même si leur documentation est bien fournie).

Fonctionnalités pour les utilisateurs#

  • Créer une VM : Créer une nouvelle machine virtuelle avec des ressources personnalisables (CPU, RAM, stockage, description, nom de la machine, système d’exploitation).
  • Accès à la console de la VM: client web intégré (console noVNC).
  • Gestion des VM : Démarrer, arrêter, redémarrer et supprimer des machines virtuelles, redimensionner les quantités de CPU, RAM et de carte réseau, choisir les ponts réseaux.
  • Recherche de VM : Trouver des machines virtuelles par son VMID, son tag ou son nom, ou les trois.
  • Détails des VM : Afficher les informations complètes des VM incluant le statut, la description, les étiquettes, l’uptime, CPU, mémoire, utilisation disque et configuration réseau.
  • Gestion du profil : Consulter la liste de ses VM, réinitialiser son mot de passe.
  • Multi-langue : L’interface est disponible en français et en anglais.- Documentation : Un document d’aide à l’utilisation est disponible dans les deux langues, pour aider l’utilisateur à exploiter PVMSS.

Fonctionnalités pour les administrateurs#

  • Informations de l’application PVMSS : Diverses informations quant à l’état de PVMSS en tant qu’administrateur.
  • Gestion des nœuds: Afficher le cluster et les nœuds Proxmox disponibles pour le déploiement de VM.
  • Gestion du pool d’utilisateurs : Ajouter ou supprimer des utilisateurs accédant à PVMSS.
  • Gestion des tags : Créer et gérer des tags pour l’organisation des VM.
  • Gestion des ISO : Configurer les images ISO disponibles pour l’installation de VM (ne permet pas d’ajouter des modèles ou des ISO depuis PVMSS).
  • Configuration réseau: Gérer les ponts réseau accessibles (VMBRs) pour le réseau des VM, et la quantité de carte réseau qu’une VM peut avoir.
  • Gestion du stockage : Configurer les emplacements de stockage pour les disques des VM, et avoir la quantité de disque dur virtuel qu’une VM peut avoir.
  • Limites de ressources : Définir les limites de CPU, RAM et disque pour la création de VM, la quantité de disque et de carte réseau qu’une VM peut avoir (avoir des limites imposées) et les limites qu’un nœud Proxmox peut supporter pour PVMSS.

L’interface utilisateur#

GALERIE D’IMAGES A AJOUTER

L’interface administrateur#

Une interface d’administration de l’application permet aux administrateurs de limiter les ressources, organiser et distribuer tout le nécessaire pour les utilisateurs.

Ainsi, le choix des images ISO, des tags, des ponts réseaux, et des ressources limitées par les VM sont à la main des administrateurs.

GALERIE D’IMAGES A AJOUTER

Workflow d’utilisation#

Vous devez créer deux secrets, l’un pour la sécurité locale de l’application PVMSS et l’autre pour le mot de passe du compte administrateur local de PVMSS.

Pour le premier, vous pouvez librement saisir ce que vous souhaitez ou utiliser par exemple le résultat de la commande openssl rand -hex 32. Pour le mot de passe du compte administrateur, vous devrez saisir le résultat d’un hash bcrypt. Vous pourrez facilement créer ce hash avec l’utilitaire htpasswd sous Linux : htpasswd -bnBC 12 "" my_secret_password | cut -d : -f 2 (source ).

Avant le déploiement de PVMSS, l’administrateur doit préparer le serveur Proxmox. Il faut créer un jeton API (token api), puis lui ajouter les droits nécessaires pour le bon fonctionnement de l’application PVMSS.

Création du jeton API en ligne de commande et attribution des droits :TODO

Via l’interface web de Proxmox :

  • dirigez-vous dans Datacenter > Permissions > Users
  • cliquez sur le bouton Add, renseignez le username, sélectionnez le royaume (realm) sur “Proxmox VE Authentication” et saisissez un mot de passe fort (vous n’aurez pas besoin du mot de passe, mais il est crucial d’en mettre un pour éviter les abus de connexion avec ce compte privilégié). Pour l’exemple, j’ai créé un utilisateur “jhdocker”.
  • ensuite, dirigez-vous dans Datacenter > Permissions > API Tokens
  • cliquez sur le bouton Add, sélectionnez l’utilisateur que vous venez de créer (jhdocker@pve) et saisissez un nom pour le jeton API.
  • en cliquant sur le bouton ‘Add’ du formulaire, le secret du jeton API sera affiché une seule fois. Copiez le secret dans un endroit sécurisé, vous en aurez besoin pour le bon fonctionnement de l’app. Pour l’exemple, mon jeton s’intitule “test”
  • enfin, dirigez-vous dans Datacenter > Permissions, cliquez sur le bouton “Add” puis sur API Token Permissions, sélectionnez le chemin “/” et votre jeton API que vous venez de créer (dans mon cas, “jhdocker@pve!test”), sélectionnez le rôle “PVEAdmin”, et cochez la case “propagate”.

Une fois l’application démarrée, accédez à l’interface d’administration, en vous connectant en tant qu’administrateur et le mot de passe que vous avez généré. Naviguez ensuite dans les différents onglets à gauche de l’application pour appliquer, activer et créer votre configuration selon votre environnement.Enfin, créez des utilisateurs depuis PVMSS. La création de ces utilisateurs via PVMSS utilisera le jeton API pour créer des comptes locaux dans le serveur Proxmox, créer un pool spécifique à l’utilisateur et lui attribuer les droits nécessaires.Ainsi, chaque utilisateur disposera de son espace personnel pour ses machines virtuelles, qui ne seront pas visibles par les autres utilisateurs.

Configurer les variables d’environnement#

Vous pouvez utiliser le fichier d’exemple fourni env.example pour créer votre propre fichier .env. Ou vous pouvez modifier le fichier d’exemple directement.

  • ADMIN_PASSWORD_HASH : Un hash bcrypt du mot de passe pour le panneau d’administration. Vous pouvez en générer un à l’aide d’un outil en ligne ou d’un script simple
  • LOG_LEVEL : Définir le niveau de log de l’application : INFO ou DEBUG (par défaut : INFO).
  • PROXMOX_API_TOKEN_NAME : Le nom de votre token API Proxmox pour les opérations backend (ex : user@pve!token).
  • PROXMOX_API_TOKEN_VALUE : La valeur secrète de votre token API.
  • PROXMOX_URL : L’URL complète vers votre endpoint API Proxmox (ex : https://proxmox.example.com:8006/api2/json).
  • PROXMOX_VERIFY_SSL : Définir à false si vous utilisez un certificat autosigné sur Proxmox (par défaut : false).
  • PVMSS_ENV : “prod” ou “dev”, cet argument sera utilisé pour débloquer ou figer certaines fonctionnalités
  • PVMSS_OFFLINE : Quand votre nœud Proxmox n’est pas joignable, mais que vous souhaitez accéder à l’application sans faire d’appel API, passez l’option à “true”. Ainsi, vous pourrez configurer quelques options de PVMSS
  • PVMSS_SETTINGS_PATH : Le chemin par défaut dans l’app pour stocker sa configuration peut être modifié, ce n’est pas utile pour le moment, mais l’option existe.
  • SESSION_SECRET : Clé secrète pour le chiffrement des sessions (changez pour une chaîne aléatoire unique, par exemple $ openssl rand -hex 32
    environment:
      # Proxmox VE settings
      PROXMOX_API_TOKEN_NAME: "nom_user_pvmss@pve!nom_jeton_api"
      PROXMOX_API_TOKEN_VALUE: "aaaaaaaa-0000-44aa-1111-aaaaaaaaaaa"
      PROXMOX_URL: "https://ip-or-name:8006/api2/json"
      PROXMOX_VERIFY_SSL: false
      # PVMSS settings
      ADMIN_PASSWORD_HASH: "$2y$10$Ppg7Wl3sNYrmxZmWgcq4reOyznt7AeqMrQucaH4HY.dBrzavhPP1e"
      LOG_LEVEL: "INFO"
      SESSION_SECRET: "changeMeWithSomethingElseUnique"
      PVMSS_ENV: "prod" # Environment: production/prod or development/dev/developpement
      PVMSS_OFFLINE: "false"
      PVMSS_SETTINGS_PATH: "/app/settings.json"
      TZ: "Europe/Paris"

Lancer le conteneur#

Créez le fichier settings.json qui sera utilisé par PVMSS pour y stocker ses configurations :

{
  "tags": ["pvmss"],
  "isos": [],
  "vmbrs": [],
  "max_network_cards": 1,
  "max_disk_per_vm": 1,
  "enabled_storages": [],
  "limits": {
    "nodes": {},
    "vm": {
      "cores": {
        "max": 2,
        "min": 1
      },
      "disk": {
        "max": 12,
        "min": 6
      },
      "ram": {
        "max": 4,
        "min": 1
      },
      "sockets": {
        "max": 1,
        "min": 1
      }
    }
  }
}

Créez le fichier docker-compose.yml et saisissez ce contenu :

---
services:
  pvmss:
    image: jhmmt/pvmss:0.4.0
    container_name: pvmss
    restart: unless-stopped
    ports:
      - "50000:50000/tcp"
    # Use either the .env file for environment variables
    # or the environment variables in the docker-compose.yml file.
    # env_file:
    #  - .env
    environment:
      # Proxmox VE settings
      PROXMOX_API_TOKEN_NAME: "tokenName@changeMe!value"
      PROXMOX_API_TOKEN_VALUE: "aaaaaaaa-0000-44aa-1111-aaaaaaaaaaa"
      PROXMOX_URL: "https://ip-or-name:8006/api2/json"
      PROXMOX_VERIFY_SSL: "false"
      # PVMSS settings
      ADMIN_PASSWORD_HASH: "$2y$10$Ppg7Wl3sNYrmxZmWgcq4reOyznt7AeqMrQucaH4HY.dBrzavhPP1e"
      LOG_LEVEL: "INFO"
      SESSION_SECRET: "changeMeWithSomethingElseUnique"
      PVMSS_ENV: "prod" # Environment: production/prod or development/dev/developpement
      PVMSS_OFFLINE: "false"
      PVMSS_SETTINGS_PATH: "/app/settings.json"
      TZ: "Europe/Paris"
    volumes:
      - ./settings.json:/app/settings.json
    deploy:
      resources:
        limits:
          cpus: "1"
          memory: 64M

Avec Docker en cours d’exécution, exécutez la commande suivante depuis la racine du projet docker compose up -d, ou lancez le conteneur avec docker run :

docker run -d \
  --name pvmss \
  --restart unless-stopped \
  -p 50000:50000 \
  -v $(pwd)/settings.json:/app/settings.json \
  -e ADMIN_PASSWORD_HASH="$2y$10$Ppg7Wl3sNYrmxZmWgcq4reOyznt7AeqMrQucaH4HY.dBrzavhPP1e" \
  -e LOG_LEVEL=INFO \
  -e PROXMOX_API_TOKEN_NAME="tokenName@changeMe!value" \
  -e PROXMOX_API_TOKEN_VALUE="aaaaaaaa-0000-44aa-1111-aaaaaaaaaaa" \
  -e PROXMOX_URL=https://ip-or-name:8006/api2/json \
  -e PROXMOX_VERIFY_SSL=false \
  -e PVMSS_ENV="prod" \
  -e PVMSS_OFFLINE="false" \
  -e PVMSS_SETTINGS_PATH="/app/settings.json" \
  -e SESSION_SECRET="$(openssl rand -hex 32)" \
  -e TZ=Europe/Paris \
  jhmmt/pvmss:0.4.0

L’application sera disponible à l’adresse http://localhost:50000.

Consulter les logs#

Via la ligne de commande docker : docker logs -f pvmss.

Retrouvez les images sur le hub docker à cette adresse : https://hub.docker.com/r/jhmmt/pvmss/tags

Déploiement de l’application dans Kubernetes#

Un manifest comportant toutes les informations nécessaires est disponible à la racine de ce dépôt, nommé pvmss-deployment.yaml. Ce manifest contient :

  • Un namespace
  • Un service account
  • Un secret
  • Un configmap
  • Un persistent volume claim (pvc)
  • Un deployment
  • Un service
apiVersion: v1
kind: Namespace
metadata:
  name: pvmss
---
apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: true
metadata:
  name: pvmss-sa
  namespace: pvmss
---
apiVersion: v1
kind: Secret
metadata:
  name: pvmss-secrets
type: Opaque
data:
  admin-password: changemebase64hash
  pve-api-token: changemebase64hash
  session-secret: changemebase64hash
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: pvmss-config
data:
  settings.json: |
    {
        "tags": [
            "pvmss"
        ],
        "isos": [],
        "vmbrs": [],
        "max_network_cards": 1,
        "max_disk_per_vm": 1,
        "enabled_storages": [],
        "limits": {
            "nodes": {},
            "vm": {
                "cores": {
                    "min": 1,
                    "max": 4
                },
                "disk": {
                    "min": 6,
                    "max": 12
                },
                "ram": {
                    "min": 1,
                    "max": 4
                },
                "sockets": {
                    "min": 1,
                    "max": 1
                }
            }
        }
    }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvmss-settings-pvc
  namespace: pvmss
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: "" # Use default storage class
---
kind: Deployment
metadata:
  name: pvmss
  namespace: pvmss
labels:
  app.kubernetes.io/name: pvmss
  app.kubernetes.io/instance: pvmss
  app.kubernetes.io/version: 0.4.0
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app.kubernetes.io/name: pvmss
  template:
    metadata:
      labels:
        app.kubernetes.io/name: pvmss
    spec:
      automountServiceAccountToken: true
      serviceAccountName: pvmss-sa
      securityContext:
        runAsUser: 65532
        runAsGroup: 65532
        fsGroup: 65532
        fsGroupChangePolicy: OnRootMismatch
      terminationGracePeriodSeconds: 5
      restartPolicy: Always
      containers:
        - name: pvmss
          image: jhmmt/pvmss:0.4.0
          imagePullPolicy: IfNotPresent
          ports:
            - name: backend
              containerPort: 50000
              protocol: TCP
          env:
            - name: ADMIN_PASSWORD_HASH
              valueFrom:
                secretKeyRef:
                  name: pvmss-secrets
                  key: admin-password
            - name: LOG_LEVEL
              value: "INFO"
            - name: PROXMOX_API_TOKEN_NAME
              value: "changeme"
            - name: PROXMOX_API_TOKEN_VALUE
              valueFrom:
                secretKeyRef:
                  name: pvmss-secrets
                  key: pve-api-token
            - name: PROXMOX_VERIFY_SSL
              value: "false"
            - name: PROXMOX_URL
              value: "https://changeme:8006/api2/json"
            - name: SESSION_SECRET
              valueFrom:
                secretKeyRef:
                  name: pvmss-secrets
                  key: session-secret
            - name: PVMSS_ENV
              value: "production" # Can be 'dev', 'developpement', 'prod'
            - name: PVMSS_OFFLINE
              value: "false" # Set to true to disable Proxmox connection
            - name: PVMSS_SETTINGS_PATH
              value: "/data/settings.json"
            - name: TZ
              value: "Europe/Paris"
          volumeMounts:
            - name: pvmss-settings
              mountPath: /data
              readOnly: false
          resources:
            requests:
              memory: "64Mi"
              cpu: "25m"
            limits:
              memory: "128Mi"
              cpu: "50m"
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
            runAsNonRoot: true
            seccompProfile:
              type: RuntimeDefault
          volumes:
            - name: pvmss-settings
              persistentVolumeClaim:
                claimName: pvmss-settings-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: pvmss
  namespace: pvmss
spec:
  selector:
    app.kubernetes.io/name: pvmss
    app.kubernetes.io/instance: pvmss
    app.kubernetes.io/version: 0.4.0
  ports:
    - name: backend
      protocol: TCP
      port: 50000
      targetPort: 50000

Pour déployer l’application dans Kubernetes, exécutez la commande suivante : kubectl apply -f pvmss-deployment.yaml.

Limitations de PVMSS#

  • Il n’y a pas eu de tests rigoureux de sécurité, attention lors du déploiement.
  • Pas (encore) de support d’OpenID Connect.
  • Seulement un administrateur local à PVMSS peut administrer l’application, il n’y a pas encore la possibilité de créer des administrateurs supplémentaires.

La pile technique#

Reposant sur le langage Go pour la partie moteur (backend) et sur du HTML et CSS pour l’interface utilisateur (frontend), je souhaite garder l’outil le plus simple possible techniquement.Les sources sont disponibles sur GitHub à cette adresse .

Licence#

PVMSS est sous licence “Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International”. Pour plus d’informations, visitez https://creativecommons.org/licenses/by-nc-nd/4.0/ .

Divers#

Proxmox VE (PVE) est une suite d’outil sous Debian 13 vous permettant d’avoir une infrastructure virtualisée pour vos besoins. Fourni gratuitement et disposant d’un service de support payant, PVE est accessible et prend de plus en plus de place dans différents contextes.

Pour installer Proxmox dans Debian 13, vous pouvez retrouver un article que j’ai saisi ici même https://j.hommet.net/installer-proxmox-sur-debian/ .

#pvmss
11 minutes
2184 mots