Pyinfra: differenze tra le versioni
(Creazione pagina introduttiva su pyinfra con esempi e link ufficiali) |
(Aggiornamento) |
||
| Riga 1: | Riga 1: | ||
__NOTOC__ | |||
= Pyinfra = | = Pyinfra = | ||
'''Pyinfra''' e | '''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 <code>https://bot.gazzi.net/pyinfra/</code> | |||
* autenticazione LDAP prima dell'accesso alla form | |||
* runner <code>pyinfra</code> locale su <code>bot.gazzi.local</code> | |||
* provisioning VM su Proxmox via SSH e comandi <code>qm</code> | |||
* 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 <code>100</code> | |||
* lookup bridge e VLAN direttamente dal nodo Proxmox | |||
* validazione preventiva della coppia <code>bridge + vlan</code> | |||
* cleanup dello snippet cloud-init dopo il primo boot se la VM parte subito | |||
== | == Architettura logica == | ||
Flusso sintetico: | |||
# | # utente apre <code>bot.gazzi.net/pyinfra/</code> | ||
# | # Nginx su <code>proxy01</code> inoltra verso il servizio su <code>bot.gazzi.local</code> | ||
# | # l'app Flask autentica l'utente via LDAP | ||
# | # la UI crea un job locale <code>pyinfra</code> | ||
# | # il job usa SSH verso Proxmox ed esegue <code>qm create</code> / <code>qm set</code> | ||
# se richiesto, la VM parte subito e viene atteso il completamento di <code>cloud-init</code> | |||
== 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: | ||
* <code>scripts-repo/pyinfra-proxmox-webui/app.py</code> | |||
* <code>scripts-repo/pyinfra-proxmox-webui/lib/proxmox_ssh.py</code> | |||
* <code>scripts-repo/pyinfra-proxmox-webui/deploys/create_vm.py</code> | |||
* <code>scripts-repo/pyinfra-proxmox-webui/systemd/pyinfra-webui.service</code> | |||
* <code>scripts-repo/pyinfra-proxmox-webui/proxy01-bot-pyinfra-location.conf.example</code> | |||
* <code>scripts-repo/pyinfra-proxmox-webui/.env.example</code> | |||
Runtime: | |||
* working directory: <code>/opt/pyinfra-webui</code> | |||
* environment file: <code>/etc/pyinfra-webui/pyinfra-webui.env</code> | |||
</ | * service systemd: <code>/etc/systemd/system/pyinfra-webui.service</code> | ||
* state dir: <code>/var/lib/pyinfra-webui</code> | |||
== 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 <code>/opt/pyinfra-webui</code> | |||
< | * aggiornare <code>/etc/pyinfra-webui/pyinfra-webui.env</code> | ||
* riavviare il servizio | |||
pyinfra -- | |||
</ | |||
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 <code>qm create</code> e <code>qm set</code> | ||
* [https:// | * configura <code>net0</code> con bridge ed eventuale tag VLAN | ||
* [https:// | * imposta <code>ipconfig0</code> 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 <code>cloud-init status --wait</code> | |||
* 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 <code>/etc/pyinfra-webui/pyinfra-webui.env</code> | |||
* usare HTTPS sul reverse proxy pubblico | |||
* mantenere il controllo umano: il job parte solo a richiesta dell'utente autenticato | |||
Nota importante: | |||
* se <code>start_after_create=false</code>, lo snippet cloud-init non puo essere rimosso subito e va pulito dopo il primo avvio completato | |||
== API utili == | |||
Endpoint interni esposti dall'app: | |||
* <code>/api/health</code> | |||
* <code>/api/jobs</code> | |||
* <code>/api/jobs/create-vm</code> | |||
* <code>/api/network/bridges</code> | |||
* <code>/api/network/vlans</code> | |||
* <code>/api/network/validate</code> | |||
* <code>/api/proxmox/free-vmid</code> | |||
== 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 <code>bridge + vlan</code> | |||
* test ricerca VMID libero | |||
== Problemi noti == | |||
* il <code>guid</code> 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 == | |||
* [[Tips Automation]] | |||
* [[Esempi Pyinfra]] | |||
* [[Confronto Ansible vs Pyinfra]] | |||
* [[Installazione Pyinfra su Fedora]] | |||
* [https://www.gazzi.net/pyinfra-proxmox-webui/ Scheda pubblica su WordPress] | |||
* [https://www.gazzi.net/2026/03/29/pyinfra-proxmox-webui-proxmox-ldap-bot-gazzi-net/ Articolo di dettaglio] | |||
== Repository == | |||
Sorgente versionata: | |||
* <code>scripts-repo/pyinfra-proxmox-webui/</code> | |||
Questa pagina wiki va tenuta come documentazione operativa ad alto livello e runbook sintetico. Segreti e dettagli sensibili restano fuori dalla wiki. | |||
Versione delle 18:43, 29 mar 2026
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.