Pyinfra

Da GazziNet.
Vai alla navigazione Vai alla ricerca

Pyinfra

Pyinfra in GazziNet non e solo una pagina teorica: al 2026-03-29 e stato usato per pubblicare una web UI operativa che consente di creare VM Proxmox via browser, con autenticazione LDAP e job eseguiti on demand.

Questa pagina raccoglie il runbook sintetico della soluzione realmente messa in esercizio, con focus su deploy, configurazione, uso e verifiche. I dettagli sensibili restano fuori dalla wiki e vanno tenuti nei file runtime dedicati.

Cosa e stato realizzato

  • UI pubblica su https://bot.gazzi.net/pyinfra/
  • autenticazione LDAP prima dell'accesso alla form
  • runner pyinfra locale su bot.gazzi.local
  • provisioning VM su Proxmox via SSH e comandi qm
  • scelta di CPU, RAM, disco, bridge, VLAN, DHCP o IP statico
  • scelta di utente e password iniziali della VM
  • pulsante per trovare il primo VMID libero a partire da 100
  • lookup bridge e VLAN direttamente dal nodo Proxmox
  • validazione preventiva della coppia bridge + vlan
  • cleanup dello snippet cloud-init dopo il primo boot se la VM parte subito

Architettura logica

Flusso sintetico:

  1. utente apre bot.gazzi.net/pyinfra/
  2. Nginx su proxy01 inoltra verso il servizio su bot.gazzi.local
  3. l'app Flask autentica l'utente via LDAP
  4. la UI crea un job locale pyinfra
  5. il job usa SSH verso Proxmox ed esegue qm create / qm set
  6. se richiesto, la VM parte subito e viene atteso il completamento di cloud-init

Parametri gestiti dalla UI

  • VMID
  • nome VM
  • utente amministrativo iniziale
  • password iniziale
  • CPU
  • RAM
  • disco
  • rete: DHCP o IP statico
  • bridge Proxmox
  • VLAN Proxmox
  • gateway
  • CIDR
  • avvio automatico della VM a fine creazione

Nota pratica:

  • se e selezionato DHCP, i campi IP statici vengono disabilitati
  • se si usa rete statica, IP, gateway e CIDR diventano obbligatori

File principali

Sorgenti versionati:

  • scripts-repo/pyinfra-proxmox-webui/app.py
  • scripts-repo/pyinfra-proxmox-webui/lib/proxmox_ssh.py
  • scripts-repo/pyinfra-proxmox-webui/deploys/create_vm.py
  • scripts-repo/pyinfra-proxmox-webui/systemd/pyinfra-webui.service
  • scripts-repo/pyinfra-proxmox-webui/proxy01-bot-pyinfra-location.conf.example
  • scripts-repo/pyinfra-proxmox-webui/.env.example

Runtime:

  • working directory: /opt/pyinfra-webui
  • environment file: /etc/pyinfra-webui/pyinfra-webui.env
  • service systemd: /etc/systemd/system/pyinfra-webui.service
  • state dir: /var/lib/pyinfra-webui

Esempio environment file

Non inserire password o token nella wiki. Usare placeholder e valorizzare i segreti solo nel file runtime.

<syntaxhighlight lang="ini"> APP_HOST=0.0.0.0 APP_PORT=18180 APP_BASE_PATH=/pyinfra APP_TOKEN=CHANGEME APP_SECRET_KEY=CHANGEME APP_STATE_DIR=/var/lib/pyinfra-webui

PROXMOX_SSH_HOST=PROXMOX_HOST PROXMOX_SSH_PORT=22 PROXMOX_SSH_USER=root PROXMOX_SSH_PASS=CHANGEME

PROXMOX_IMAGE=/var/lib/vz/template/iso/noble-server-cloudimg-amd64.img PROXMOX_STORAGE=local PROXMOX_CLOUDINIT_STORAGE=local PROXMOX_BRIDGE=vmbr1 PROXMOX_GATEWAY=172.16.1.1 PROXMOX_CPU_TYPE=x86-64-v2-AES PROXMOX_CIUSER=ubuntu PROXMOX_CIPASSWORD=CHANGEME PROXMOX_CICUSTOM_USER=local:snippets/gazzi-ubuntu-user.yaml

LDAP_URI=ldap://LDAP_HOST:389 LDAP_USER_DN_TEMPLATE=uid={username},ou=People,dc=gazzi,dc=local </syntaxhighlight>

Service systemd

<syntaxhighlight lang="ini"> [Unit] Description=Pyinfra Proxmox Web UI After=network-online.target Wants=network-online.target

[Service] Type=simple User=pyinfraweb Group=pyinfraweb WorkingDirectory=/opt/pyinfra-webui EnvironmentFile=/etc/pyinfra-webui/pyinfra-webui.env ExecStart=/opt/pyinfra-webui/venv/bin/python /opt/pyinfra-webui/app.py Restart=on-failure RestartSec=3

[Install] WantedBy=multi-user.target </syntaxhighlight>

Reverse proxy

Snippet Nginx di riferimento:

<syntaxhighlight lang="nginx"> location = /pyinfra {

   return 301 /pyinfra/;

}

location /pyinfra/ {

   proxy_pass http://BOT_GAZZI_LOCAL:18180/;
   proxy_http_version 1.1;
   proxy_set_header Host $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-Forwarded-Host $host;
   proxy_set_header X-Forwarded-Port $server_port;
   proxy_set_header X-Forwarded-Prefix /pyinfra;
   proxy_redirect off;

} </syntaxhighlight>

Deploy o aggiornamento

Sequenza minima lato host applicativo:

<syntaxhighlight lang="bash"> sudo mkdir -p /opt/pyinfra-webui /etc/pyinfra-webui /var/lib/pyinfra-webui sudo chown -R pyinfraweb:pyinfraweb /opt/pyinfra-webui /var/lib/pyinfra-webui

cd /opt/pyinfra-webui python3 -m venv venv ./venv/bin/pip install -U pip ./venv/bin/pip install -r requirements.txt

sudo install -m 0644 systemd/pyinfra-webui.service /etc/systemd/system/pyinfra-webui.service sudo systemctl daemon-reload sudo systemctl enable --now pyinfra-webui.service </syntaxhighlight>

Poi:

  • copiare o aggiornare i file dell'app dentro /opt/pyinfra-webui
  • aggiornare /etc/pyinfra-webui/pyinfra-webui.env
  • riavviare il servizio

Comandi utili: <syntaxhighlight lang="bash"> sudo systemctl restart pyinfra-webui.service sudo systemctl status pyinfra-webui.service journalctl -u pyinfra-webui.service -n 100 --no-pager curl -sS http://127.0.0.1:18180/api/health </syntaxhighlight>

Comportamento del provisioning

La UI raccoglie i parametri e avvia un job che:

  • verifica che il VMID non esista gia
  • crea la VM cloud-init con qm create e qm set
  • configura net0 con bridge ed eventuale tag VLAN
  • imposta ipconfig0 in DHCP o statico
  • genera uno snippet cloud-init per creare l'utente richiesto con sudo
  • opzionalmente avvia la VM
  • se la VM viene avviata subito, aspetta guest agent e cloud-init status --wait
  • rimuove lo snippet cloud-init dopo il primo boot

Sicurezza

Regole da mantenere:

  • non scrivere in wiki password, token, cookie o dump di sessione
  • non copiare in Git segreti o backend interni inutili
  • tenere i segreti in /etc/pyinfra-webui/pyinfra-webui.env
  • usare HTTPS sul reverse proxy pubblico
  • mantenere il controllo umano: il job parte solo a richiesta dell'utente autenticato

Nota importante:

  • se start_after_create=false, lo snippet cloud-init non puo essere rimosso subito e va pulito dopo il primo avvio completato

API utili

Endpoint interni esposti dall'app:

  • /api/health
  • /api/jobs
  • /api/jobs/create-vm
  • /api/network/bridges
  • /api/network/vlans
  • /api/network/validate
  • /api/proxmox/free-vmid

Verifiche rapide

Verifiche applicative: <syntaxhighlight lang="bash"> curl -I https://bot.gazzi.net/pyinfra/ curl -sS http://127.0.0.1:18180/api/health </syntaxhighlight>

Verifiche systemd: <syntaxhighlight lang="bash"> systemctl status pyinfra-webui.service journalctl -u pyinfra-webui.service -n 50 --no-pager </syntaxhighlight>

Verifiche Proxmox lato UI:

  • test lookup bridge
  • test lookup VLAN
  • test validazione bridge + vlan
  • test ricerca VMID libero

Problemi noti

  • il guid di WordPress o altri metadati editoriali non hanno relazione con questa automazione
  • il cleanup automatico dello snippet cloud-init dipende dal primo boot e dalla disponibilita del guest agent
  • la VLAN viene validata in base a cio che il nodo Proxmox espone al momento del controllo

Riferimenti collegati

Repository

Sorgente versionata:

  • scripts-repo/pyinfra-proxmox-webui/

Questa pagina wiki va tenuta come documentazione operativa ad alto livello e runbook sintetico. Segreti e dettagli sensibili restano fuori dalla wiki.