perfetti.tech
← tutti gli appunti

n8n in Docker dietro Cloudflare Tunnel: la mia architettura completa

Yuri PerfettiYuri Perfetti5 min1 lettura

Tempo di lettura: 8 minuti — Livello: intermedio

Perché questo setup

n8n è il cuore delle mie automazioni: parser di email, bot Telegram, sincronizzazioni tra knowledge base, monitoraggio news. Tutto self-hosted, per tre motivi: controllo dei dati, nessun limite di esecuzioni, costo zero oltre l'hardware che già possiedo.

Ma self-hosted significa un problema classico: come esponi n8n su internet (serve per i webhook e per gli OAuth) senza aprire porte sul router di casa? La risposta che uso da tempo: Cloudflare Tunnel.

L'architettura in un colpo d'occhio

Internet
   │
   ▼
Cloudflare (DNS + certificato HTTPS + protezione)
   │
   ▼  tunnel cifrato in uscita
cloudflared (connettore sul mio server)
   │
   ▼  http://localhost:5678
Container Docker n8n
   │
   ├── volume n8n_data  (database, credenziali, encryption key)
   └── network dedicata (per parlare con gli altri container)

Il punto chiave: il tunnel è una connessione in uscita dal mio server verso Cloudflare. Nessuna porta aperta in ingresso, nessun port forwarding sul router, il mio IP di casa non è esposto da nessuna parte. Per il mondo esterno esiste solo n8n.miodominio.it, che vive sull'infrastruttura di Cloudflare.

Pezzo 1: il container n8n

Uso un'immagine custom (ci torno tra un attimo), ma la struttura del run è questa:

docker run -d --name n8n \
  --restart unless-stopped \
  --network n8n-network \
  -v n8n_data:/home/node/.n8n \
  --env-file /percorso/n8n.env \
  -p 127.0.0.1:5678:5678 \
  la-tua-immagine-n8n

Tre scelte deliberate:

Il volume nominato (n8n_data) contiene il database SQLite, i workflow e — attenzione — la encryption key con cui n8n cifra tutte le credenziali salvate. La chiave vive nel volume, non nell'env file. Se distruggi il volume, le tue credenziali diventano illeggibili per sempre. È il pezzo da proteggere e backuppare.

La network dedicata (n8n-network) permette a n8n di parlare con gli altri container per nome. Nel mio caso, per esempio, un microservizio di generazione documenti Word: n8n lo chiama come http://docx-service:3000 e Docker risolve tutto internamente, senza esporre nulla.

L'env file esterno tiene fuori dal comando (e dalla history della shell) le variabili sensibili: URL dei webhook, chiavi API, configurazione proxy. Un file, un posto solo da modificare.

⚠️ La regola che mi sono scritto in grande dopo un incidente: quando ricrei il container, ricordati SEMPRE --network e --env-file. Un docker run frettoloso senza quei due flag produce un n8n che parte, sembra sano, e poi fallisce in modi misteriosi: i webhook puntano all'URL sbagliato, i container vicini non rispondono. Tenete il comando completo in un file di note e copiatelo da lì, sempre.

Pezzo 2: perché un'immagine custom

L'immagine ufficiale di n8n va benissimo per iniziare. Io sono passato a una custom per un motivo preciso: i moduli npm esterni. Alcuni miei workflow usavano librerie come docxtemplater per generare documenti Word, e per permetterne l'uso nei nodi Code serve la variabile NODE_FUNCTION_ALLOW_EXTERNAL più i pacchetti installati nell'immagine.

(Nota per chi è su n8n 2.x: il nuovo task runner ha reso questa strada molto più rigida. Io alla fine ho spostato la generazione documenti in un microservizio separato — ne ho scritto un articolo dedicato. La versione corta: quando combatti contro la piattaforma, spesso la risposta è un container in più, non una configurazione in più.)

Pezzo 3: il tunnel

Cloudflare Tunnel si può gestire in due modi: da file di configurazione o dalla dashboard Zero Trust. Io uso la seconda: crei il tunnel dall'interfaccia web, ti dà un token, avvii il connettore cloudflared con quel token, e da lì in poi la mappatura hostname → servizio la gestisci dal browser.

La mappatura nel mio caso è semplice:

n8n.miodominio.it  →  http://localhost:5678

Cloudflare termina l'HTTPS, quindi il certificato non lo gestisco io: rinnovi automatici, zero Let's Encrypt, zero cron job.

Le due trappole di questo setup

  1. n8n non sa di essere dietro un proxy. Il tunnel inoltra il traffico in HTTP verso localhost, e n8n — se non glielo dici — genera URL interni sbagliati. Il sintomo più famoso: OAuth di Google che fallisce con "Unauthorized". La cura sono quattro variabili d'ambiente da impostare insieme, e ci ho dedicato un articolo intero la settimana scorsa.

  2. Le protezioni di Cloudflare possono bloccare il TUO traffico. Cloudflare offre protezioni contro bot e scraper, inclusa una specifica per gli "AI bots". Ottima idea, finché non colleghi un client MCP al tuo n8n e scopri che la tua stessa protezione sta bloccando la tua integrazione. Se qualcosa che passa dal tunnel fallisce in modo strano, i log di Cloudflare (sezione Security) sono il primo posto dove guardare.

Manutenzione: quello che faccio davvero

  • Backup del volume prima di ogni aggiornamento: docker run --rm -v n8n_data:/data -v $(pwd):/backup alpine tar czf /backup/n8n_backup.tar.gz /data
  • Aggiornamenti: mai a caldo, mai di venerdì. Nuova immagine, stop, rm, run con il comando completo salvato nelle note
  • Test post-aggiornamento: un workflow di "canarino" con un webhook che chiamo a mano per verificare che il giro completo internet → tunnel → n8n funzioni

Vale la pena?

Per me sì, e tanto. Il costo di gestione reale, superata la configurazione iniziale, è di qualche minuto al mese. In cambio ho una piattaforma di automazione senza limiti, raggiungibile da ovunque, con i miei dati a casa mia. Il compromesso vero è un altro: sei tu il tuo sysadmin. Se questa frase ti suona come una minaccia più che come una promessa, n8n cloud esiste apposta.


Questo articolo fa parte della serie "Stack & Infrastruttura" su perfetti.tech — dove racconto quello che costruisco davvero, errori compresi.

Condividi

Hai un problema simile?

Mandami due righe: ti dico se ha senso trasformarlo in uno strumento vero e quanto tempo serve.

Scrivimi →

Commenti

Ancora nessun commento. Scrivi il primo!

Lascia un commento

Questo sito è protetto da reCAPTCHA: si applicano la Privacy Policy e i Termini di servizio di Google.