10 min di letturaIntegrazioni

Automazione n8n self-hosted per i link: da Docker ai webhook

Esegui l'automazione dei link con n8n self-hosted e i webhook Elido, Docker Compose e la modalità coda, mantenendo i dati dei workflow su infrastruttura che controlli tu, in EU.

Marius Voß
DevRel · edge infra
Automazione n8n self-hosted per i link: i webhook Elido passano attraverso un reverse proxy in un'istanza n8n con una coda e dei worker, tutto dentro infrastruttura che controlli tu

L'automazione n8n self-hosted per i link significa tre cose in esecuzione su server che controlli tu: un'istanza n8n in Docker, un endpoint HTTPS pubblico che riceve gli eventi webhook di Elido, e chiamate in uscita verso l'API Elido con un token scoped. Gli eventi di link e dominio arrivano firmati, e gli eventi per singolo clic sono sulla roadmap. I tuoi workflow decidono cosa succede dopo, e i log di esecuzione non lasciano mai la tua infrastruttura.

Questa è l'intera architettura. Il resto di questo post è la parte che i quickstart saltano: come far passare i webhook attraverso un reverse proxy, come controllare la firma così uno sconosciuto non può far scattare i tuoi workflow, cosa cambia la modalità coda, e quando n8n Cloud è onestamente la scelta migliore. Io eseguo questa configurazione su una singola piccola VM, e le parti in movimento stanno tutte su uno schermo.

Se vuoi che anche i link stessi vivano sul tuo hardware, è un lavoro separato e molto più grande. Il playbook per il self-hosting di Elido su k3s lo copre. Qui, Elido resta gestito e solo il livello di automazione si sposta in casa.

Il motivo abituale sono i dati. Un workflow n8n self hosted url shortener vede ogni payload che elabora: l'URL di destinazione, i tag, a volte un nome campagna che dice più di quanto vorresti, e paese, dispositivo e referrer se ci fai confluire i click analytics. Su n8n Cloud quelle esecuzioni sono memorizzate sui server di qualcun altro, sotto i valori di retention predefiniti di qualcun altro. Self-hosted, restano nel tuo Postgres, nella regione che hai scelto.

Secondo l'articolo 28 del GDPR ogni processore che tocca dati personali richiede un contratto e un posto nei tuoi registri. Meno processori, meno burocrazia. Se i tuoi dati di marketing devono già restare in EU, la guida alla residenza dei dati EU spiega perché anche il livello di automazione conta allo stesso modo.

Il secondo motivo è la forma dei costi. n8n Cloud tariffa per esecuzioni, e un trigger webhook impegnato o un polling analytics frequente consuma esecuzioni in fretta. Self-hosted, un'esecuzione è una riga in una tabella e qualche millisecondo di CPU.

Il terzo è la portata. Un'istanza self-hosted sta sulla stessa rete del tuo database CRM o dello strumento di ticketing interno, quindi un evento sui link può arrivare in un sistema che non era mai stato pensato per affacciarsi su internet.

Lo stack Docker Compose

Uno stack minimo n8n docker link automation richiede quattro servizi. La guida Docker Compose di n8n è il riferimento; questa è la versione da cui partirei per il lavoro sui link, con la modalità coda già attivata così non devi migrare più avanti.

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${PG_PASSWORD}
      POSTGRES_DB: n8n
    volumes: [pgdata:/var/lib/postgresql/data]

  redis:
    image: redis:7

  n8n:
    image: docker.n8n.io/n8nio/n8n
    env_file: .env.n8n
    ports: ["127.0.0.1:5678:5678"]
    depends_on: [postgres, redis]

  n8n-worker:
    image: docker.n8n.io/n8nio/n8n
    command: worker
    env_file: .env.n8n
    depends_on: [n8n]

volumes:
  pgdata:

E il file di ambiente condiviso:

DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=change-me
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
N8N_ENCRYPTION_KEY=generate-a-long-random-string
N8N_WEBHOOK_URL=https://n8n.example.com/
N8N_PROXY_HOPS=1

Due righe contano più di quanto sembri. La chiave di cifratura deve essere identica sul processo main e su ogni worker, altrimenti i worker non possono decifrare la credenziale Elido e ogni esecuzione fallisce con un errore di autenticazione confuso. E la porta 5678 è vincolata solo a localhost, perché il reverse proxy è l'unica cosa che dovrebbe affacciarsi su internet.

Architettura n8n self-hosted per l'automazione dei link: Elido invia webhook firmati via HTTPS a un reverse proxy, che li inoltra al processo main di n8n, che accoda le esecuzioni in Redis per i worker supportati da Postgres, mentre i worker chiamano l'API Elido in uscita con un token scoped

Chiamare l'API Elido da n8n self-hosted

Le chiamate in uscita non richiedono nulla oltre a ciò che n8n include di serie. Crea una credenziale Header Auth con nome Authorization e valore Bearer seguito da una API key dalla dashboard Elido, poi usala dal nodo HTTP Request integrato. n8n la cifra a riposo con la chiave del file di ambiente, il che è un motivo in più per cui quella chiave deve corrispondere ovunque.

Ogni rotta sui link è scoped a un workspace. Per accorciare un URL, invia una POST a https://api.elido.app/v1/workspaces/{workspace_id}/links con un body JSON:

{
  "domain_id": 12,
  "destination_url": "{{ $json.url }}",
  "title": "Spring launch",
  "tags": ["n8n", "spring"]
}

Lascia fuori slug e Elido ne genera uno. Il domain_id è il dominio breve su cui vive il link; una GET a /v1/workspaces/{workspace_id}/domains elenca i tuoi, e io fisserei l'ID nel workflow piuttosto che cercarlo a ogni esecuzione. Una GET sulla stessa rotta links elenca i link, e PATCH /v1/workspaces/{workspace_id}/links/{link_id} cambia una destinazione o i tag in un secondo momento.

Imposta un header Idempotency-Key sulla POST, costruito a partire da qualcosa di stabile nell'elemento che ha attivato il trigger, come un ID di riga. Se n8n riprova il nodo dopo un timeout, l'API riproduce la prima risposta invece di creare un secondo link. Il quickstart API e SDK copre il resto della superficie, e la pagina API e SDK è lì se preferisci spostare un passaggio nel codice più avanti.

Esiste anche un community node pacchettizzato, n8n-nodes-elido, pensato per avvolgere queste chiamate in una forma più amichevole. È pubblicato su npm (versione 0.2.0), ma resta opzionale e, poiché non è un nodo verificato, si installa solo su n8n self-hosted, che è comunque la configurazione presupposta da questo post. Mantieni la versione HTTP Request come base. Se installi pacchetti community in modalità coda, ricorda che la GUI installa solo nel container main; i worker non lo vedono mai. Da n8n 2.21, la rotta di installazione tramite variabile d'ambiente risolve questo problema riconciliando ogni container all'avvio, anche se al primo avvio disinstalla tutto ciò che non è nella sua lista.

Far passare i webhook Elido attraverso il tuo reverse proxy

Gli eventi scorrono nell'altro senso. Elido emette link.created, link.updated e domain.verified (tra gli altri) verso un endpoint che registri sotto Settings, Webhooks, e su n8n self-hosted quell'endpoint è l'URL di produzione di un nodo Webhook. Un evento click.created per singolo clic è sulla roadmap ma non ancora rilasciato, quindi per ora i dati sui clic arrivano da un pull programmato dell'API analytics. L'elenco completo degli eventi e le forme dei payload sono nel riferimento webhook per gli eventi sui link.

Dietro un proxy, n8n costruisce il proprio URL webhook a partire dal proprio protocollo, host e porta, il che significa che pubblicizzerà felicemente http://localhost:5678/webhook/... a chiunque lo chieda. La pagina di configurazione del reverse proxy è breve e vale la pena leggerla per intero: imposta N8N_WEBHOOK_URL sul tuo indirizzo pubblico, imposta N8N_PROXY_HOPS=1, e fai in modo che l'ultimo proxy inoltri X-Forwarded-For, X-Forwarded-Host e X-Forwarded-Proto. Le guide più vecchie parlano di WEBHOOK_URL; le release attuali la leggono ancora ma registrano un avviso di deprecazione.

Nginx, Traefik, quello che già usi va bene. Ciò che conta è il TLS sul lato pubblico e che il percorso /webhook/* raggiunga n8n intatto.

Un dettaglio di tempistica mi ha morso. Elido aspetta dieci secondi per una risposta prima di contare una consegna come fallita. Un workflow che scrive su un'API a foglio di calcolo lenta e poi risponde può superare quel limite, essere riprovato, e scrivere due volte la stessa riga. Imposta il nodo Webhook per rispondere immediatamente ed eseguire il lavoro dopo.

Se stai configurando questo per un cliente e vuoi che il lato webhook sia gestito per te, la pagina delle funzionalità webhook mostra a cosa puoi iscriverti prima di costruire qualsiasi cosa.

Verificare la firma prima che qualsiasi cosa venga eseguita

Un URL webhook pubblico è un URL pubblico. Chiunque lo trovi può inviare una POST con un evento falso e far scattare il tuo workflow, quindi il primo nodo dopo il trigger dovrebbe essere un controllo della firma.

Ogni consegna Elido porta X-Webhook-Signature (valore v1= più un digest esadecimale), X-Webhook-Timestamp in secondi Unix, X-Webhook-Event e X-Webhook-Delivery. Il digest è HMAC-SHA256 sopra il timestamp, un punto e il body grezzo della richiesta, con chiave il segreto whsec_ mostrato una sola volta quando hai creato l'endpoint.

Attiva prima Raw Body sul nodo Webhook. Questo è il passo che la gente salta. Se calcoli l'hash di JSON.stringify($json.body) invece dei byte esatti inviati da Elido, l'ordine delle chiavi o gli spazi differiscono e ogni firma fallisce, e passerai una serata convinto che il segreto sia sbagliato. Poi un nodo Code:

const crypto = require("crypto");
const item = $input.first();
const h = item.json.headers;
const raw = (await this.helpers.getBinaryDataBuffer(0, "data")).toString(
  "utf8",
);

const ts = Number(h["x-webhook-timestamp"]);
if (Math.abs(Date.now() / 1000 - ts) > 300) throw new Error("stale delivery");

const expected =
  "v1=" +
  crypto
    .createHmac("sha256", $env.ELIDO_WEBHOOK_SECRET)
    .update(`${ts}.${raw}`)
    .digest("hex");
const got = h["x-webhook-signature"] || "";
if (
  got.length !== expected.length ||
  !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))
) {
  throw new Error("bad signature");
}
return [{ json: JSON.parse(raw) }];

Il modulo crypto è disponibile nel nodo Code di default, quindi non serve alcuna configurazione extra lì. La finestra di cinque minuti blocca le riproduzioni di una richiesta catturata. Quando ruoti il segreto, Elido invia anche X-Elido-Signature-Previous durante il periodo di grazia, così puoi accettare entrambe le chiavi mentre aggiorni la variabile. La guida alla verifica delle firme webhook presenta una versione di questo nodo che controlla entrambe le intestazioni, oltre allo stesso controllo in Node, Python e Go.

Verifica della firma webhook in n8n self-hosted: leggi il timestamp e il body grezzo, rifiuta le consegne più vecchie di 300 secondi, ricalcola HMAC-SHA256 sopra timestamp punto body grezzo con il segreto dell'endpoint, confronta a tempo costante, poi esegui il workflow oppure ferma l'esecuzione

Modalità coda e retry

Con il controllo della firma in atto, la domanda che resta è cosa succede sotto carico o quando qualcosa è offline. Sono in gioco due sistemi di retry, e coprono guasti diversi.

In modalità coda di n8n il processo main riceve il webhook, crea un'esecuzione e consegna il suo ID a Redis; i worker lo prelevano. Un picco di eventi si accumula nella coda invece di bloccare la risposta HTTP. Per un volume in entrata maggiore puoi aggiungere processori webhook dedicati dietro un load balancer, anche se per la maggior parte dei carichi di lavoro sui link un processo main e due worker bastano ampiamente.

Il lato Elido gestisce il caso in cui n8n sia irraggiungibile. Qualsiasi risposta non-2xx o timeout viene riprovata dopo 1, 5 e 15 minuti; dopo tre tentativi la consegna viene segnata come fallita e puoi riattivarla dalla dashboard. Questo copre un riavvio del container o un deploy rapido. Non copre un'interruzione nel weekend, motivo per cui abbinerei i webhook a una riconciliazione notturna che elenca i link tramite l'API, come sostiene il post webhook vs polling.

Usa X-Webhook-Delivery come chiave di idempotenza. I retry la riutilizzano.

n8n self-hosted vs n8n Cloud: compromessi onesti

Preferisco il self-hosting per questo caso, ma ho visto team pentirsene. Ecco il confronto senza il discorso di vendita da nessuna delle due parti.

Aspetton8n self-hostedn8n Cloud
Dove vivono i dati di esecuzioneI tuoi server, la tua regione, la tua retentionL'infrastruttura e i valori predefiniti di n8n
Raggiungere sistemi interniStessa rete del tuo CRM e dei databaseSolo ciò che esponi pubblicamente
URL webhook pubblico e TLSGestisci tu proxy e certificatiFornito
Aggiornamenti, backup, patchingCompito tuo, ogni meseGestito
Costo ad alto volume di eventiCosto server fissoScala con le esecuzioni

L'ultima riga taglia in entrambi i sensi. Una piccola VM costa poco, ma un'ora di un ingegnere su un aggiornamento andato male non lo è, e n8n rilascia spesso. Se nessuno nel team è responsabile della macchina, Cloud con il nodo HTTP Request e l'API REST di Elido è la scelta più sensata, e le ricette Make e IFTTT oppure la guida a Zapier mostrano come appare quella via gestita su altre piattaforme.

Quello che non posso dirti è se il tuo responsabile della protezione dei dati accetterà una macchina self-hosted come più semplice di un DPA con un fornitore. Nella mia esperienza di solito sì, ma dipende da quanto bene viene gestita la macchina. Per come funziona il lato shortener del contratto, la guida GDPR per gli URL shortener è il punto da cui partire. E se sei pronto a collegare il primo workflow, prendi un token API su un workspace e punta un nodo Webhook verso di esso.

Correlati sul blog

Domande frequenti

Posso usare uno shortener URL con n8n self-hosted?

Sì. n8n self-hosted può chiamare qualsiasi shortener con un'API REST attraverso il nodo HTTP Request integrato. Per Elido questo significa una credenziale Header Auth con la tua API key e una POST verso la rotta links scoped al workspace. Gli eventi in entrata come link.created arrivano attraverso il nodo Webhook integrato di n8n, che richiede un URL HTTPS pubblico. Un evento click.created per singolo clic è previsto ma non ancora disponibile.

Come installo community node su n8n self-hosted?

Su un'istanza singola, usa Settings, poi Community Nodes, e incolla il nome del pacchetto npm. In modalità coda l'installazione via GUI non raggiunge i tuoi worker, quindi installa il pacchetto dentro ogni container oppure, da n8n 2.21, elencalo in N8N_COMMUNITY_PACKAGES con N8N_COMMUNITY_PACKAGES_MANAGED_BY_ENV impostato a true. Per Elido non ne serve uno: il nodo HTTP Request copre l'API.

Cos'è WEBHOOK_URL in n8n?

Dice a n8n quale indirizzo pubblico mostrare nell'editor e registrare presso servizi esterni, perché dietro un reverse proxy n8n non può dedurlo dal proprio host e porta. Le versioni attuali di n8n leggono N8N_WEBHOOK_URL e registrano un avviso di deprecazione per la vecchia WEBHOOK_URL. Abbinalo a N8N_PROXY_HOPS=1 e agli header forwarded sul proxy.

Come verifico una firma webhook in n8n?

Attiva l'opzione Raw Body nel nodo Webhook, poi aggiungi un nodo Code che ricalcola HMAC-SHA256 sopra l'header timestamp, un punto e il body grezzo, usando il segreto del tuo endpoint. Confrontalo con l'header signature a tempo costante e rifiuta qualsiasi cosa più vecchia di cinque minuti. Verifica contro i byte grezzi, mai contro JSON ri-serializzato.

La modalità coda di n8n richiede Redis?

Sì. In modalità coda l'istanza main e ogni processore webhook trasformano i trigger in arrivo in ID di esecuzione e li mettono in una coda basata su Redis, e i worker li estraggono da lì. n8n sconsiglia anche la modalità coda con SQLite, quindi pianifica per Postgres. Ogni processo deve condividere la stessa chiave di cifratura o i worker non possono leggere le credenziali memorizzate.

n8n self-hosted è migliore di n8n Cloud per il GDPR?

Può esserlo, perché scegli dove vivono fisicamente i dati dei workflow, i log di esecuzione e le credenziali, e chi li amministra. Non è automaticamente conforme: diventi responsabile di patch, controllo accessi, backup e retention. Per l'automazione dei link che gestisce dati di clic, il self-hosting in una regione EU rimuove un processore dai tuoi registri, il che semplifica la burocrazia.

Prova Elido

Incolla un URL, ottieni un link breve

Senza registrazione. Il link vive 30 giorni. Iscriviti per conservarlo.

Gratis, nessuna registrazione richiesta · 2 al giorno

Prova Elido

Accorciatore di URL ospitato nell'UE: domini personalizzati, analisi approfondite e API aperta. Piano gratuito - senza carta di credito.

Tag
self-hosted n8n automation links
n8n self hosted url shortener
n8n docker link automation
n8n webhook signature verification
n8n queue mode
n8n http request node api

Continua a leggere