Self-hosting di Windmill nel 2026: worker, PostgreSQL, isolamento e aggiornamenti sicuri
Un approfondimento aggiornato e orientato alla produzione che traduce la documentazione dei fornitori in controlli operativi, decisioni di migrazione e criteri di rilascio verificabili.
Cosa è cambiato nel 2026
Torniamo su questo tema perché i confini operativi sono cambiati. I principi di fondo restano validi, ma le versioni attuali rendono alcune scorciatoie del passato incomplete o rischiose. Questo approfondimento parte dalla documentazione ufficiale disponibile al 14 luglio 2026, distingue i fatti dalle scelte locali e tratta ogni modifica di configurazione come un intervento controllato in produzione.
Fonti primarie aggiornate
Come utilizziamo questo aggiornamento
Leggi prima le fonti, registra le versioni realmente distribuite e definisci il risultato osservabile prima di modificare qualsiasi impostazione. Prova il più piccolo intervento reversibile in un ambiente rappresentativo. Un comando eseguito con successo non è un criterio di accettazione: lo sono lo stato del servizio, l’integrità dei dati, la latenza, i confini di sicurezza e il tempo necessario al rollback. La sequenza diagnostica ancora utile dell’articolo precedente viene mantenuta come base operativa; gli esempi legati a una versione devono comunque essere verificati nella documentazione corrente.
Prima del rilascio registriamo le differenze di configurazione, un backup o un’istantanea di cui sia già stato verificato almeno una volta il ripristino e i comandi necessari per annullare l’intervento. Una persona osserva la prima finestra di produzione e un’altra autorizza l’escalation se gli indicatori concordati si muovono nella direzione sbagliata. Gli avvisi devono descrivere il rischio visibile per l’utente, non soltanto il componente che li ha emessi. Durante la finestra di verifica confrontiamo tassi di errore, lunghezza delle code, saturazione delle risorse, latenza di elaborazione e completezza dei dati con il riferimento iniziale concordato. Esaminiamo medie e code della distribuzione, perché una media stabile può nascondere errori che colpiscono una quota piccola ma importante del lavoro. La modifica viene chiusa solo dopo il completamento di job differiti, nuovi tentativi, attività pianificate ed esportazioni verso i sistemi a valle. Ogni azione manuale di ripristino viene documentata: se manca dal manuale operativo, il manuale non è ancora completo. Questa disciplina di rilascio produce evidenze riutilizzabili al prossimo aggiornamento, evitando al team di dover riscoprire le stesse dipendenze.
- La scelta del self-hosting: quando il SaaS costa più della propria infrastruttura
- Ripristino di emergenza per i servizi gestiti sulla propria infrastruttura: la nostra strategia di backup
- Self-hosting di più istanze di database su un singolo server
Base operativa
Le piattaforme di automazione dei flussi di lavoro sono essenziali per i team di sviluppo moderni, ma le soluzioni cloud come Windmill Cloud possono diventare costose con l’aumento dell’utilizzo. Ti mostreremo come configurare la tua istanza Windmill su Ubuntu con Docker Compose e l’integrazione con Traefik, superando i problemi critici di autenticazione PostgreSQL che possono compromettere l’installazione.
Cosa realizzerai
Al termine di questo tutorial avrai:
- ✅ Un’installazione Windmill pienamente funzionante con HTTPS
- ✅ Certificati SSL automatici tramite Let’s Encrypt e Traefik
- ✅ Un database PostgreSQL pronto per la produzione con autenticazione corretta
- ✅ Una configurazione dei worker ottimizzata per le risorse disponibili
- ✅ Integrazione con l’infrastruttura Docker esistente
- ✅ Una configurazione pronta per la produzione per l’automazione professionale dei flussi di lavoro
Costo mensile: da 5,99 € IVA esclusa, con un indirizzo IPv4 primario incluso (Hetzner CX23, 4 GB RAM, a ottobre 2026) + costo del dominio – la stessa infrastruttura può gestire più strumenti di automazione
Prerequisiti
- Server Ubuntu 24.04 LTS con Docker e Docker Compose installati
- Reverse proxy Traefik già configurato (consulta la nostra guida alla configurazione di n8n per configurare Traefik)
- Un nome di dominio che punti all’IP del server
- Si consigliano almeno 4GB di RAM e 2 vCPU
- Accesso SSH e conoscenza di base della riga di comando
Come funziona Windmill
Windmill è un motore open source per i flussi di lavoro che offre:
- Editor visuale dei flussi di lavoro con supporto per TypeScript/Python/Go
- Pianificazione dei job e gestione dell’esecuzione
- Funzionalità di integrazione API
- Funzionalità di collaborazione in team
- Self-hosting con esecuzioni illimitate nella Community Edition gratuita
A differenza dell’approccio a nodi di n8n, Windmill punta su flussi di lavoro basati sul codice, con un potente ambiente di sviluppo.
Passaggio 1: preparazione del server e struttura delle directory
Per prima cosa prepariamo l’ambiente del server. Useremo nomi di alimenti per le istanze Windmill, così da evitare conflitti:
# Create Windmill directory (first instance: "pizza")
mkdir -p /opt/windmill-pizza
cd /opt/windmill-pizza
# Create required subdirectories
mkdir -p postgres-data windmill-data lsp-cache
# Verify directory structure
ls -la
Convenzione di denominazione: usa semplici nomi di alimenti per distinguere più istanze Windmill:
- Prima istanza: pizza
- Istanze aggiuntive: pasta, salad, soup, burger, ecc.
- Questo evita conflitti e semplifica la gestione
Passaggio 2: configurazione dell’ambiente
Crea un file delle variabili d’ambiente sicuro con le credenziali corrette:
# Generate a secure hex password (no special characters!)
SECURE_PASSWORD=$(openssl rand -hex 16)
# Create environment file
cat > /opt/windmill-pizza/.env << EOF
# Windmill Image Version (pin a release; change it deliberately when you update)
WM_IMAGE=ghcr.io/windmill-labs/windmill:1.767.0
# Database Configuration - SECURE PASSWORDS
DATABASE_URL=postgresql://postgres:${SECURE_PASSWORD}@windmill-db:5432/windmill_pizza?sslmode=disable
POSTGRES_PASSWORD=${SECURE_PASSWORD}
POSTGRES_DB=windmill_pizza
POSTGRES_USER=postgres
# Windmill Configuration
BASE_URL=https://windmill.yourdomain.com
RUST_LOG=info
# Worker Configuration
WORKER_GROUP=default
KEEP_JOB_DIR=false
# Instance Identifier
INSTANCE_NAME=pizza
EOF
# The file holds the database password: make it readable by its owner only
chmod 600 /opt/windmill-pizza/.env
Attenzione: sostituisci windmill.yourdomain.com con il tuo dominio effettivo!
Passaggio 3: configurazione di Docker Compose
Crea la configurazione principale di Docker Compose:
cat > /opt/windmill-pizza/docker-compose.yml << 'EOF'
services:
# PostgreSQL Database for Windmill
windmill-db:
image: postgres:16
container_name: windmill-pizza-db
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
volumes:
- ./postgres-data:/var/lib/postgresql/data
networks:
- proxy
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
# Windmill Server
windmill-server:
image: ${WM_IMAGE}
container_name: windmill-pizza-server
restart: unless-stopped
environment:
- DATABASE_URL=${DATABASE_URL}
- BASE_URL=${BASE_URL}
- RUST_LOG=${RUST_LOG}
- MODE=server
networks:
- proxy
depends_on:
windmill-db:
condition: service_healthy
volumes:
- ./windmill-data:/tmp/windmill
labels:
- "traefik.enable=true"
- "traefik.http.routers.windmill-pizza.rule=Host(`windmill.yourdomain.com`)"
- "traefik.http.routers.windmill-pizza.entrypoints=https"
- "traefik.http.routers.windmill-pizza.tls.certresolver=letsencrypt"
- "traefik.http.services.windmill-pizza.loadbalancer.server.port=8000"
# Windmill Worker
windmill-worker:
image: ${WM_IMAGE}
container_name: windmill-pizza-worker
restart: unless-stopped
environment:
- DATABASE_URL=${DATABASE_URL}
- BASE_URL=${BASE_URL}
- RUST_LOG=${RUST_LOG}
- MODE=worker
- WORKER_GROUP=${WORKER_GROUP}
- KEEP_JOB_DIR=${KEEP_JOB_DIR}
networks:
- proxy
depends_on:
windmill-db:
condition: service_healthy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./windmill-data:/tmp/windmill
- worker_dependency_cache:/tmp/windmill/cache
deploy:
resources:
limits:
cpus: '1'
memory: 2G
networks:
proxy:
external: true
volumes:
worker_dependency_cache:
driver: local
EOF
Importante: aggiorna il dominio nelle etichette Traefik in modo che corrisponda alla tua configurazione!
Passaggio 4: il problema della password PostgreSQL (problema critico)
È qui che fallisce la maggior parte delle installazioni Windmill; individuare la causa ha richiesto un lungo lavoro di diagnosi:
Il problema: caratteri speciali nelle password
Quando usi openssl rand -base64 32 per generare password, il risultato può contenere +, / e =. All’interno di DATABASE_URL, questi caratteri devono essere codificati tramite codifica percentuale; se non vengono codificati, possono compromettere l’analisi dell’URL e manifestarsi come errori di autenticazione PostgreSQL. Le password esadecimali evitano del tutto questo passaggio di codifica.
Esempio di password problematica:
# Unless percent-encoded, the "/" in this password breaks DATABASE_URL:
PASSWORD="305t6m9KrChkvbyN/FLEYQ6pqAGlApn9rbJPH3D5y9g="
La soluzione: password con soli caratteri esadecimali
Usa password con soli caratteri esadecimali, senza caratteri speciali:
# This WORKS reliably:
PASSWORD=$(openssl rand -hex 16)
# Example result: 5781b14ec0ec1bc184653ffa5e379411
Altri problemi di configurazione PostgreSQL
- Configurazione dell’utente: Usa il superutente postgres, come nella configurazione di esempio di Windmill. Un utente personalizzato funziona solo dopo aver ricevuto i ruoli windmill_admin e windmill_user richiesti dalle migrazioni di Windmill (vedi la documentazione sul self-hosting di Windmill)
- Persistenza dei volumi: PostgreSQL ignora le variabili d’ambiente POSTGRES_PASSWORD quando i volumi dati esistenti contengono credenziali diverse
- Formato dell’URL: Includi ?sslmode=disable nell’URL del database quando quest’ultimo è raggiungibile solo sulla rete Docker interna, come nella configurazione di esempio di Windmill; usa una modalità SSL come require per i database raggiunti tramite altre reti
Passaggio 5: installazione e avvio
Ora installiamo Windmill con la configurazione corretta:
cd /opt/windmill-pizza
# Verify configuration syntax
docker compose config --quiet
# Pull images
docker compose pull
# Start services
docker compose up -d
# Check status
docker compose ps
Dovresti vedere un output simile a questo:
NAME STATUS PORTS
windmill-pizza-db Up (healthy) 5432/tcp
windmill-pizza-server Up 8000/tcp
windmill-pizza-worker Up 8000/tcp
Passaggio 6: risoluzione dei problemi comuni
Problema 1: errori di autenticazione PostgreSQL
Sintomi:
windmill-pizza-server | Error: password authentication failed for user "postgres"
Soluzione: La reimpostazione del database elimina tutti i dati di Windmill. Eseguila solo su una nuova installazione o dopo un backup verificato.
# WARNING: this deletes all Windmill data (fresh install or verified backup only)
cd /opt/windmill-pizza
# Stop containers
docker compose down --volumes
# Remove old data
rm -rf /opt/windmill-pizza/postgres-data/*
# Regenerate hex password and write it to both variables
NEW_PASSWORD=$(openssl rand -hex 16)
sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$NEW_PASSWORD/" .env
sed -i "s|^DATABASE_URL=postgresql://postgres:[^@]*@|DATABASE_URL=postgresql://postgres:$NEW_PASSWORD@|" .env
# Restart
docker compose up -d
Problema 2: il container non si avvia
Sintomi:
- Il container termina immediatamente
- Errori di allocazione delle risorse
Soluzione:
# Check container logs
docker logs windmill-pizza-server
docker logs windmill-pizza-db
# Check system resources
docker stats
free -h
Problema 3: certificati SSL
Sintomi:
- HTTPS non funziona
- Errori dei certificati
Soluzione:
# Check Traefik logs
docker logs traefik
# Verify DNS resolution
nslookup windmill.yourdomain.com
# Restart Traefik if needed
docker restart traefik
Passaggio 7: accesso e configurazione iniziale
Una volta completata l’installazione:
- Accedi a Windmill: https://windmill.yourdomain.com
- Credenziali predefinite:
Email: [email protected]
- Password: changeme
- Completa la configurazione:
Cambia la password dell’amministratore
- Configura l’URL di base
- Configura gli account utente
Passaggio 8: ottimizzazione delle risorse
Allocazione della memoria (per un server da 8GB)
La nostra configurazione alloca le risorse in modo efficiente:
- Server Windmill: ~800MB
- Worker Windmill: 2GB (limite)
- PostgreSQL: ~500MB
- Riserva per il sistema: ~4.7GB
Allocazione della CPU (per un server con 4 vCPU)
- Worker: 1 vCPU (limite)
- Altri servizi: 3 vCPU (condivise)
Regola di scalabilità: 1 worker per vCPU con 1-2GB di RAM ciascuno
Passaggio 9: rafforzamento della sicurezza in produzione
Crea uno script di backup
cat > /opt/windmill-pizza/backup.sh << 'EOF'
#!/bin/bash
set -euo pipefail
umask 077
# docker compose needs the project directory, also when run from cron
cd /opt/windmill-pizza
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE=/opt/backups/windmill_pizza_${DATE}.sql
mkdir -p /opt/backups
if ! docker compose exec -T windmill-db pg_dump -U postgres windmill_pizza > "$BACKUP_FILE" || [ ! -s "$BACKUP_FILE" ]; then
rm -f "$BACKUP_FILE"
echo "Backup FAILED" >&2
exit 1
fi
echo "Backup created: $BACKUP_FILE"
EOF
chmod +x /opt/windmill-pizza/backup.sh
Configura il monitoraggio
cd /opt/windmill-pizza
# Monitor container health
docker compose ps
# Check resource usage
docker stats
# Monitor logs
docker compose logs -f windmill-server
Configura gli aggiornamenti automatici
cat > /opt/windmill-pizza/update.sh << 'EOF'
#!/bin/bash
set -euo pipefail
cd /opt/windmill-pizza
# Back up first; stop here if the backup fails
./backup.sh
# Pull and start the images set in .env (raise WM_IMAGE there to update Windmill)
docker compose pull
docker compose up -d
EOF
chmod +x /opt/windmill-pizza/update.sh
Passaggio 10: configurazione avanzata
Integrazione con il servizio SMTP esistente
Se hai un mailserver (come quello della nostra configurazione n8n), integralo:
# Add to docker-compose.yml environment for windmill-server:
- SMTP_HOST=mailserver
- SMTP_PORT=25
- [email protected]
# Only if your mail server requires authentication:
# - SMTP_USERNAME=...
# - SMTP_PASSWORD=...
Più istanze Windmill
Per i team che richiedono ambienti isolati:
# Create second instance from the configuration files only (not the data)
mkdir -p /opt/windmill-pasta/{postgres-data,windmill-data,lsp-cache}
cp /opt/windmill-pizza/{.env,docker-compose.yml,backup.sh,update.sh} /opt/windmill-pasta/
chmod 600 /opt/windmill-pasta/.env
cd /opt/windmill-pasta
# Update names, paths and domain
sed -i 's/pizza/pasta/g' .env docker-compose.yml backup.sh update.sh
sed -i 's/windmill.yourdomain.com/pasta.yourdomain.com/g' .env docker-compose.yml
# Generate new password and write it to both variables
NEW_PASSWORD=$(openssl rand -hex 16)
sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$NEW_PASSWORD/" .env
sed -i "s|^DATABASE_URL=postgresql://postgres:[^@]*@|DATABASE_URL=postgresql://postgres:$NEW_PASSWORD@|" .env
# Start the new instance
docker compose up -d
Considerazioni sulla sicurezza
Isolamento della rete
- PostgreSQL è raggiungibile solo dai container sulla sua rete Docker; se questa rete è condivisa con il reverse proxy e altri servizi, usa una rete interna separata per un isolamento più rigoroso
- Nessuna porta del database è esposta all’esterno
- Terminazione HTTPS a livello di Traefik
Limiti delle risorse
- I container dei worker hanno limiti di CPU e memoria
- I limiti delle risorse riducono l’impatto dei job fuori controllo e dei tentativi di esaurimento delle risorse
- Configurabile in base alla capacità del server
Sicurezza SSL
- Certificati Let’s Encrypt automatici
- Reindirizzamenti da HTTP a HTTPS
- Configurazione TLS moderna
Monitoraggio e manutenzione
Controlli settimanali dello stato dei servizi
cd /opt/windmill-pizza
# Container status
docker compose ps
# Resource usage
docker stats --no-stream
# Log analysis
docker compose logs | grep -i error
Manutenzione mensile
# Back up and update containers (update.sh runs backup.sh first)
cd /opt/windmill-pizza
./update.sh
# Clean unused images, containers and networks
docker system prune -f
Dettaglio e confronto dei costi
Costi mensili
Configurazione sulla propria infrastruttura:
- Hetzner CX23 (4 GB RAM): 5,99 €/mese IVA esclusa, con un indirizzo IPv4 primario incluso (a ottobre 2026)
- Costo del dominio: ~€1/mese
- Totale: ~7 €/mese IVA esclusa
Confronto con Windmill Cloud:
- Cloud: 20 $/mese per postazione sviluppatore, 10 $/mese per operatore (a ottobre 2026)
- Risparmio: oltre 250 $ all’anno quando due o più sviluppatori hanno bisogno di una postazione
Vantaggi in termini di prestazioni
Vantaggi del self-hosting:
- Esecuzioni illimitate dei flussi di lavoro
- Nessun limite esterno alla frequenza delle richieste
- Controllo completo dei dati
- Integrazioni personalizzate
- Flessibilità nell’aumento delle risorse
Riferimenti per la risoluzione dei problemi
Diagnostica rapida
cd /opt/windmill-pizza
# Container health
docker compose ps | grep -E "(healthy|Up)"
# Network connectivity
docker network inspect proxy
# Database connection
docker compose exec windmill-db psql -U postgres -d windmill_pizza -c "SELECT version();"
# Log analysis
docker compose logs --tail 50 windmill-server | grep -E "(ERROR|WARN)"
Errori comuni
- “password authentication failed” → Usa password esadecimali; svuota i volumi solo dopo un backup o su una nuova installazione
- “connection refused” → Controlla la configurazione di rete
- “certificate errors” → Verifica il DNS e la configurazione di Traefik
- “out of memory” → Regola i limiti delle risorse dei worker
Scalabilità dell’infrastruttura Windmill
Scalabilità orizzontale
Per gli ambienti con volumi elevati:
# Add additional workers (under services: in docker-compose.yml)
windmill-worker-2:
image: ${WM_IMAGE}
container_name: windmill-pizza-worker-2
restart: unless-stopped
environment:
- DATABASE_URL=${DATABASE_URL}
- MODE=worker
- WORKER_GROUP=heavy
networks:
- proxy
depends_on:
windmill-db:
condition: service_healthy
deploy:
resources:
limits:
cpus: '2'
memory: 4G
Scalabilità verticale
Aumenta le risorse del server (prezzi Hetzner IVA esclusa, con un indirizzo IPv4 primario incluso a ottobre 2026):
- CX33 (8 GB RAM): 8,99 €/mese per carichi di lavoro elevati
- CX43 (16 GB RAM): 16,49 €/mese per l’uso aziendale
Integrazione con l’infrastruttura esistente
Uso insieme a n8n
Se usi già n8n (come nei nostri tutorial precedenti):
- Windmill gestisce flussi di lavoro basati sul codice
- n8n gestisce automazioni semplici e visuali
- Entrambi condividono lo stesso proxy Traefik
- Database separati evitano conflitti
Servizi condivisi
Sfrutta l’infrastruttura esistente:
- Traefik: Gestisce SSL per tutti i servizi
- Mailserver: SMTP condiviso per le notifiche
- Monitoraggio: Log e metriche unificati
- Backup: Strategia di backup centralizzata
Conclusione
Il self-hosting di Windmill offre automazione dei flussi di lavoro di livello aziendale a una frazione del costo dell’hosting cloud. Per riuscirci è essenziale comprendere come vengono passate e conservate in modo persistente le credenziali PostgreSQL e usare password con soli caratteri esadecimali, evitando i problemi di codifica degli URL che possono compromettere le installazioni.
Vantaggi principali di questa configurazione
- Convenienza: Risparmi centinaia all’anno rispetto alle soluzioni cloud
- Pronta per la produzione: Gestisce i carichi di lavoro aziendali in modo affidabile
- Sicurezza: HTTPS, nessuna porta del database esposta e limiti delle risorse
- Scalabilità: È facile aggiungere worker e risorse secondo le necessità
- Riservatezza: Il codice e i dati rimangono sulla tua infrastruttura, a meno che i tuoi flussi di lavoro non li inviino a servizi esterni
Questa configurazione è stata testata in ambienti di produzione e offre l’affidabilità necessaria per l’automazione dei flussi di lavoro critici per l’azienda. I passaggi di risoluzione dei problemi affrontano difficoltà reali incontrate durante la distribuzione, in particolare i problemi di autenticazione PostgreSQL che interessano molte installazioni sulla propria infrastruttura.
Per flussi di lavoro complessi o distribuzioni aziendali, valuta una consulenza professionale per ottimizzare il tuo caso d’uso specifico e garantire un’allocazione ottimale delle risorse.
Prossimi passi
- Esplora le tecniche di risoluzione dei problemi dei webhook applicabili a Windmill
- Approfondisci l’ottimizzazione del payload per gestire grandi insiemi di dati
- Valuta l’integrazione con le installazioni n8n esistenti
Informazioni su tva
tva assicura una gestione completa dell’infrastruttura di sistemi di database, ambienti cloud e catene di approvvigionamento globali. Il nostro approccio metodico combina rigorosi protocolli di sicurezza con l’ottimizzazione delle prestazioni, mentre i servizi di consulenza strategica consentono di coordinare con precisione sia le capacità digitali sia le risorse fisiche, mantenendo i più elevati standard di eccellenza operativa e conformità in tutti gli incarichi.
Visita tva.sg per maggiori informazioni sui nostri servizi e altri tutorial sull’automazione.
Dalla configurazione alla decisione operativa
La domanda pratica non è se una piattaforma possa essere configurata. È se il team sappia chiarire le responsabilità, rilevare gli scostamenti, ripristinare il servizio senza improvvisare e dimostrare che la modifica abbia migliorato il risultato previsto. Per questo associamo ogni configurazione a un responsabile, un riferimento iniziale, un percorso di rollback e una finestra di verifica. Una correzione isolata diventa così una capacità operativa. Il registro di produzione dovrebbe includere il motivo della modifica, le evidenze esaminate, l’ambito esatto e la persona autorizzata a interromperla o annullarla. Dopo il rilascio, confronta gli indicatori concordati con il riferimento iniziale e conserva il risultato insieme alla registrazione della modifica. Se il miglioramento atteso non si verifica, il rollback è un esito valido, non un fallimento. Questa disciplina conta più di qualsiasi singolo valore di configurazione. La stessa registrazione offre a chi subentra nella gestione un punto di partenza affidabile e rende le ottimizzazioni successive decisioni basate su misurazioni anziché un nuovo ciclo di ipotesi.
Approfondimenti correlati
- Oltre cento container Docker: la nostra routine mensile di verifica dello stato dei servizi
- GitHub Actions per pipeline di distribuzione sulla propria infrastruttura
- Il problema dell’idoneità dei dati per l’IA aziendale
- Hetzner Cloud a fine 2026: piani e prezzi per il self-hosting di n8n, Windmill, Twenty e Ollama