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.
Perché fare self-hosting di n8n per l'automazione dei link
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.
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.
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.
| Aspetto | n8n self-hosted | n8n Cloud |
|---|---|---|
| Dove vivono i dati di esecuzione | I tuoi server, la tua regione, la tua retention | L'infrastruttura e i valori predefiniti di n8n |
| Raggiungere sistemi interni | Stessa rete del tuo CRM e dei database | Solo ciò che esponi pubblicamente |
| URL webhook pubblico e TLS | Gestisci tu proxy e certificati | Fornito |
| Aggiornamenti, backup, patching | Compito tuo, ogni mese | Gestito |
| Costo ad alto volume di eventi | Costo server fisso | Scala 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
- Self-hosting di Elido su k3s: il playbook - quando anche i link devono vivere in casa.
- Webhook per gli eventi sui link - ogni tipo di evento e forma del payload.
- Webhook vs polling per il click tracking - perché conta la riconciliazione notturna.
- Automazione dei link brevi con Make e IFTTT - la via low-code gestita.
- n8n URL shortener - la configurazione del nodo HTTP Request e tre workflow nel dettaglio.
- Verifica delle firme webhook - body grezzo, finestra di replay e rotazione del segreto in quattro runtime.
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