Torna al Blog
Guida

Migrare da n8n Cloud a self-hosted su un VPS europeo: guida con DPA e GDPR

Quando ha senso lasciare n8n Cloud, come scegliere provider e DPA in Europa, cosa esportare prima, il Docker Compose con Postgres e TLS, le variabili degli URL, i webhook da aggiornare e lo switch in parallelo. Con la tabella di cosa migra da solo e cosa va rifatto.

Consulenti n8n.it- Consulenza indipendente su n8n2 settembre 20267 min read
Migrare da n8n Cloud a self-hosted su un VPS europeo: guida con DPA e GDPR

Quando ha senso lasciare n8n Cloud?

Ha senso in tre casi: superi le 2.500 esecuzioni al mese del piano Starter e il piano Pro non basta o costa troppo; i workflow trattano dati personali di clienti o dipendenti e vuoi un solo responsabile del trattamento, europeo, con DPA firmato; i limiti di memoria del piano bloccano i workflow con file. Se nessuno in azienda può gestire un server, resta sul Cloud e sistema gli adempimenti descritti in n8n Cloud e GDPR. Se invece uno dei tre casi è il tuo, questa è la sequenza che seguiamo noi.

Quale provider europeo e quale DPA?

Il vantaggio principale del self-hosted sul fronte GDPR è la catena corta: un solo responsabile esterno del trattamento, il fornitore del server, con un DPA che firmi tu. Perché la catena resti corta, il fornitore deve essere una società europea con data center in UE:

ProviderSedeData center UEDPANote
HetznerGermaniaFalkenstein, Norimberga, HelsinkiSi firma dalla console del cliente (in tedesco AVV)Miglior rapporto qualità prezzo, guida ufficiale n8n con Caddy
OVHcloudFranciaGravelines, Roubaix, StrasburgoAllegato alle condizioni contrattualiUtile se hai già un contratto quadro
ScalewayFranciaParigi, Amsterdam, VarsaviaNei documenti contrattuali dell'area clienteBuona offerta di storage S3 europeo per i backup

Per un'istanza n8n con Postgres bastano 2 vCPU e 4 GB di RAM: i numeri per piano li trovi nel costo reale di n8n self-hosted. Prima di creare il server, scarica il DPA del provider e mettilo nel fascicolo del registro dei trattamenti: il fornitore del server sostituisce n8n GmbH come responsabile esterno, e la privacy policy va aggiornata di conseguenza.

Cosa esportare dal Cloud prima di iniziare?

Dal Cloud escono i workflow, non le credenziali. Hai tre strade per i workflow:

  1. Dashboard di amministrazione: Admin Dashboard, sezione Manage, scheda Export, pulsante Download Workflows. Scarica i workflow dall'ultimo backup dell'istanza.
  2. Editor: menu del singolo workflow, voce Download. Utile per rifare un export puntuale dopo una modifica dell'ultimo minuto.
  3. Pacchetti n8n (in anteprima): con la n8n CLI e una API key, n8n-cli package export --project-id=... --output=cloud.n8np porta workflow, cartelle, tag, variabili con i loro valori e le tabelle dati. È il metodo più completo, ma il formato può ancora cambiare.

Le credenziali invece vanno inventariate a mano. Nell'editor apri la sezione Credentials e annota per ciascuna: nome, tipo, quali workflow la usano. La documentazione ufficiale è esplicita: i segreti delle credenziali non viaggiano mai in un pacchetto, che contiene solo ID, nome e tipo. Tieni gli stessi nomi sull'istanza nuova, così l'import le riaggancia per nome e tipo invece di creare segnaposto vuoti. Le connessioni OAuth (Google, Microsoft, HubSpot) vanno comunque riautorizzate, perché l'URL di callback cambia con il dominio.

Un promemoria di tempi: se sei ancora in trial, hai 90 giorni dalla scadenza per scaricare i workflow, poi vengono cancellati.

Come preparare il server con Docker Compose, Postgres e TLS?

La base è la stessa della guida ufficiale per Hetzner: Docker Compose, Postgres e Caddy come reverse proxy, che ottiene e rinnova da solo il certificato Let's Encrypt. Versione bloccata, mai latest:

services:
  postgres:
    image: postgres:18
    restart: always
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      PGDATA: /var/lib/postgresql/data
    volumes:
      - db-storage:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: n8nio/n8n:2.37.7
    restart: always
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - n8n_data:/home/node/.n8n

  caddy:
    image: caddy:2
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data

volumes:
  db-storage:
  n8n_data:
  caddy_data:

Il Caddyfile è una riga di sostanza: n8n.example.com { reverse_proxy n8n:5678 { flush_interval -1 } }. La porta 5678 non va pubblicata sull'host: è raggiungibile solo da Caddy sulla rete interna di Compose. Il file .env contiene le variabili di Postgres, la N8N_ENCRYPTION_KEY generata da te e le variabili degli URL.

Quali variabili fanno funzionare gli URL?

Dietro un reverse proxy n8n deve sapere con quale indirizzo pubblico viene raggiunto, altrimenti genera URL di webhook e di callback OAuth sbagliati:

N8N_HOST=n8n.example.com
N8N_PORT=5678
N8N_PROTOCOL=https
N8N_EDITOR_BASE_URL=https://n8n.example.com/
N8N_WEBHOOK_URL=https://n8n.example.com/
N8N_PROXY_HOPS=1
GENERIC_TIMEZONE=Europe/Rome
TZ=Europe/Rome
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
N8N_DIAGNOSTICS_ENABLED=false
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
DB_POSTGRESDB_USER=${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}

Due note. WEBHOOK_URL, il nome storico che trovi in molte guide, dalla 2.35.0 è un alias deprecato di N8N_WEBHOOK_URL: funziona ancora, ma n8n scrive un avviso a ogni avvio. N8N_DIAGNOSTICS_ENABLED=false spegne la telemetria anonima verso n8n: è coerente con il motivo per cui stai migrando. Dopo il primo avvio verifica che l'istanza risponda e che la versione sia quella bloccata:

docker compose up -d
docker compose exec n8n n8n --version
curl -s https://n8n.example.com/healthz

Come importare i workflow e aggiornare i webhook?

Importa i JSON scaricati dal Cloud con la CLI interna, che per default lascia tutti i workflow non pubblicati. È esattamente quello che vuoi durante la migrazione:

docker compose exec -u node n8n mkdir -p /home/node/.n8n/import
docker cp ./cloud-export/. "$(docker compose ps -q n8n)":/home/node/.n8n/import/
docker compose exec -u node n8n n8n import:workflow --separate --input=/home/node/.n8n/import/

Poi crea le credenziali con gli stessi nomi del Cloud, apri ogni workflow e riassegna quelle che risultano mancanti. I webhook cambiano solo nella base dell'URL:

Prima (n8n Cloud)Dopo (self-hosted)
https://tua-istanza.app.n8n.cloud/webhook/ordine-nuovohttps://n8n.example.com/webhook/ordine-nuovo
https://tua-istanza.app.n8n.cloud/webhook-test/ordine-nuovohttps://n8n.example.com/webhook-test/ordine-nuovo

Il percorso finale resta uguale perché è salvato nel JSON del workflow. La base va invece aggiornata in ogni servizio che chiama n8n: Stripe, WooCommerce, i moduli del sito, il CRM, i trigger delle app che registrano il webhook da sole (per queste ultime basta disattivare e riattivare il trigger sull'istanza nuova).

Come testare in parallelo e fare lo switch?

Per un paio di giorni le due istanze convivono. Sul self-hosted esegui a mano ogni workflow con dati di prova, usando l'URL webhook-test per quelli a webhook, e verifica che l'esito sia identico a quello del Cloud. I workflow con Schedule Trigger restano pubblicati su una sola istanza per volta, altrimenti l'ordine parte due volte.

Lo switch, workflow per workflow: pubblica sul self-hosted, aggiorna l'URL nel servizio esterno, spubblica sul Cloud, controlla la prima esecuzione reale nei log. Chi ha molti webhook fa lo switch in blocco in una finestra concordata, tenendo il Cloud spubblicato ma vivo per una settimana come rete di sicurezza.

Cosa migra da solo e cosa va rifatto?

Migra da soloVa rifatto a mano
Workflow: nodi, connessioni, espressioni, impostazioniCredenziali, con gli stessi nomi del Cloud
Percorsi dei webhookBase degli URL webhook nei servizi esterni
Variabili con i valori (solo con i pacchetti n8n)Connessioni OAuth: da riautorizzare sul nuovo dominio
Cartelle, tag, tabelle dati (solo con i pacchetti n8n)Utenti, ruoli e condivisioni
Nomi e ID delle credenziali (come riferimenti)Nodi community: da reinstallare prima dell'import
Storico delle esecuzioni e cronologia delle versioni: non si trasferiscono
Registro dei trattamenti, privacy policy, DPA con il nuovo provider

Cosa fare del piano Cloud?

Dopo una settimana di esercizio pulito sul self-hosted: scarica un ultimo export dei workflow dalla dashboard, come copia storica, poi annulla l'abbonamento e cancella l'istanza dall'area di amministrazione. Non lasciare l'istanza Cloud viva con i workflow spubblicati: contiene ancora le credenziali e i dati delle esecuzioni, e nel registro dei trattamenti risulterebbe un responsabile che di fatto non usi più. Aggiorna il registro e la privacy policy nello stesso giorno.

E il server?

La migrazione sposta n8n, ma da questo momento il server è tuo: chi lo aggiorna, chi guarda i log di Caddy e di Postgres, chi fa i backup dell'istanza e li prova, chi riceve l'alert alle tre di notte se il disco è pieno. Se in azienda non c'è nessuno per questo, puoi affidare la migrazione del server e la sua gestione a un servizio esterno, con DPA e compliance della gestione già formalizzati, tenendo n8n dove preferisci.

Il perimetro resta netto: n8n.it segue l'istanza n8n, i workflow e le integrazioni; managedvps.it segue il server sotto, dal sistema operativo al firewall. Se vuoi una mano a pianificare la migrazione o a rifare l'inventario delle credenziali, contattaci.

C

Consulenti n8n.it

Consulenza indipendente su n8n

Siamo consulenti indipendenti focalizzati su automazione dei processi aziendali e sicurezza delle implementazioni n8n self-hosted.

Articoli correlati