Pyinfra
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
pyinfralocale subot.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:
- utente apre
bot.gazzi.net/pyinfra/ - Nginx su
proxy01inoltra verso il servizio subot.gazzi.local - l'app Flask autentica l'utente via LDAP
- la UI crea un job locale
pyinfra - il job usa SSH verso Proxmox ed esegue
qm create/qm set - 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.pyscripts-repo/pyinfra-proxmox-webui/lib/proxmox_ssh.pyscripts-repo/pyinfra-proxmox-webui/deploys/create_vm.pyscripts-repo/pyinfra-proxmox-webui/systemd/pyinfra-webui.servicescripts-repo/pyinfra-proxmox-webui/proxy01-bot-pyinfra-location.conf.examplescripts-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 createeqm set - configura
net0con bridge ed eventuale tag VLAN - imposta
ipconfig0in 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
guiddi 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
- Tips Automation
- Esempi Pyinfra
- Confronto Ansible vs Pyinfra
- Installazione Pyinfra su Fedora
- Scheda pubblica su WordPress
- Articolo di dettaglio
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.