Torna al Blog
Tutorial

Audit di sicurezza n8n: checklist per proteggere la tua istanza

Checklist pratica e completa per mettere in sicurezza la tua istanza n8n: reverse proxy, SSL, autenticazione, rate limiting, crittografia credenziali e backup.

Team n8n.it- Specialisti in Automazione30 marzo 20269 min read
Audit di sicurezza n8n: checklist per proteggere la tua istanza

Perché la sicurezza di n8n è importante

La tua istanza n8n contiene alcune delle informazioni più sensibili della tua azienda: credenziali API, token di accesso, webhook endpoint e logiche di business. Una compromissione non significa solo che qualcuno vede i tuoi workflow, significa che ha accesso a tutti i servizi collegati: CRM, email, database, sistemi di pagamento.

Questa guida è una checklist pratica, ordinata per priorità, che puoi seguire passo-passo per verificare e migliorare la sicurezza della tua istanza n8n.

Livello 1: fondamentali (fai subito)

1.1 Reverse proxy con Nginx

Mai esporre n8n direttamente su internet. Il server web integrato in n8n non è progettato per gestire traffico diretto. Usa Nginx come reverse proxy.

Configurazione base di Nginx per n8n:

server {
    listen 80;
    server_name n8n.tuodominio.it;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name n8n.tuodominio.it;

    ssl_certificate /etc/letsencrypt/live/n8n.tuodominio.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.tuodominio.it/privkey.pem;

    # Header di sicurezza
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;

    # Limita dimensione upload
    client_max_body_size 16M;

    # Timeout per webhook lunghi
    proxy_read_timeout 300s;
    proxy_connect_timeout 60s;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support (per l'editor)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Checklist:

  • Nginx installato e configurato come reverse proxy
  • Redirect HTTP -> HTTPS attivo
  • Header di sicurezza impostati
  • WebSocket configurato per l'editor
  • client_max_body_size limitato

1.2 SSL/TLS con Let's Encrypt

Il certificato SSL è obbligatorio, non opzionale:

# Installa Certbot
apt install certbot python3-certbot-nginx

# Ottieni certificato
certbot --nginx -d n8n.tuodominio.it

# Verifica rinnovo automatico
certbot renew --dry-run

# Cron per rinnovo (aggiunto automaticamente da Certbot)
# 0 12 * * * /usr/bin/certbot renew --quiet

Checklist:

  • Certificato SSL attivo e valido
  • Rinnovo automatico configurato e testato
  • Solo TLS 1.2+ permesso (TLS 1.0 e 1.1 disabilitati)

1.3 Autenticazione

n8n supporta diversi metodi di autenticazione. Come minimo, configura username e password:

# .env di n8n
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin_tuo_nome
N8N_BASIC_AUTH_PASSWORD=password_molto_lunga_e_complessa_32_caratteri_minimo

Regole per la password:

  • Minimo 32 caratteri
  • Generata con un password manager (non inventata)
  • Mai riutilizzata da altri servizi
  • Cambiata ogni 90 giorni

Per team con più utenti, configura l'autenticazione LDAP o SAML (disponibile nei piani enterprise).

Checklist:

  • Autenticazione attiva (non accessibile senza login)
  • Password forte (32+ caratteri, generata casualmente)
  • Password diversa da quelle usate altrove

1.4 Crittografia delle credenziali

n8n cripta le credenziali salvate con una chiave di cifratura. Assicurati che sia impostata correttamente:

# Genera una chiave di cifratura casuale
N8N_ENCRYPTION_KEY=chiave_casuale_generata_con_openssl_rand_hex_32

Per generare una chiave sicura:

openssl rand -hex 32

Attenzione: se perdi questa chiave, perdi l'accesso a tutte le credenziali salvate in n8n. Conservala in un posto sicuro (password manager, vault) separato dal server.

Checklist:

  • N8N_ENCRYPTION_KEY impostata con chiave casuale
  • Chiave salvata in un luogo sicuro separato dal server
  • File .env con permessi 600 (solo owner)

Livello 2: protezione attiva (fai entro la prima settimana)

2.1 Rate limiting su Nginx

Proteggi n8n da brute force e abuso dei webhook:

# Nella sezione http {} di nginx.conf
limit_req_zone $binary_remote_addr zone=n8n_general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=n8n_webhook:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=n8n_auth:10m rate=3r/m;

# Nel server block di n8n
server {
    # ... configurazione SSL ...

    # Rate limit per login
    location /rest/login {
        limit_req zone=n8n_auth burst=5 nodelay;
        proxy_pass http://127.0.0.1:5678;
        # ... proxy headers ...
    }

    # Rate limit per webhook
    location /webhook/ {
        limit_req zone=n8n_webhook burst=50 nodelay;
        proxy_pass http://127.0.0.1:5678;
        # ... proxy headers ...
    }

    # Rate limit generale
    location / {
        limit_req zone=n8n_general burst=20 nodelay;
        proxy_pass http://127.0.0.1:5678;
        # ... proxy headers ...
    }
}

Checklist:

  • Rate limiting attivo per endpoint di login (max 3/minuto)
  • Rate limiting attivo per webhook (max 30/secondo)
  • Rate limiting generale (max 10/secondo)

2.2 Fail2ban per blocco IP

Installa fail2ban per bloccare automaticamente IP che tentano brute force:

apt install fail2ban

Crea un filtro per n8n in /etc/fail2ban/filter.d/n8n.conf:

[Definition]
failregex = ^<HOST> .* "POST /rest/login HTTP.*" 401
ignoreregex =

E il jail in /etc/fail2ban/jail.d/n8n.conf:

[n8n]
enabled = true
port = http,https
filter = n8n
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 3600

Checklist:

  • fail2ban installato e attivo
  • Filtro per n8n configurato
  • Ban automatico dopo 5 tentativi falliti

2.3 Firewall (UFW)

Configura il firewall per permettere solo il traffico necessario:

# Reset e configura
ufw default deny incoming
ufw default allow outgoing

# Permetti SSH (cambia porta se diversa)
ufw allow 22/tcp

# Permetti HTTP/HTTPS
ufw allow 80/tcp
ufw allow 443/tcp

# Attiva
ufw enable

# Verifica
ufw status verbose

Importante: n8n sulla porta 5678 non deve essere accessibile dall'esterno. Solo Nginx (porta 80/443) deve essere esposto.

Checklist:

  • UFW attivo con policy deny-by-default
  • Solo porte 22, 80, 443 aperte
  • Porta 5678 NON accessibile dall'esterno

2.4 Variabili d'ambiente sicure

Non inserire mai credenziali direttamente nei workflow. Usa le variabili d'ambiente di n8n:

# .env
N8N_EXTERNAL_STORAGE_S3_ACCESS_KEY=AKIA...
N8N_EXTERNAL_STORAGE_S3_SECRET_KEY=secret...

# Oppure usa Docker secrets
docker secret create n8n_encryption_key ./encryption_key.txt

Checklist:

  • Nessuna credenziale hardcoded nei workflow
  • File .env con permessi 600
  • Docker secrets per dati sensibili (se usi Docker Swarm)

Livello 3: hardening avanzato (fai entro il primo mese)

3.1 Sicurezza dei webhook

I webhook sono l'endpoint più esposto della tua istanza n8n. Proteggili:

Usa webhook con autenticazione header:

URL: https://n8n.tuodominio.it/webhook/ordini-woocommerce
Header: X-Webhook-Secret: token_segreto_generato_casualmente

Nel workflow n8n, aggiungi un nodo IF che verifica l'header:

// Nel nodo Function/Code
const expectedSecret = $env.WEBHOOK_SECRET_WOOCOMMERCE;
const receivedSecret = $input.first().headers['x-webhook-secret'];

if (receivedSecret !== expectedSecret) {
  throw new Error('Webhook non autorizzato');
}

Usa URL non prevedibili:

SBAGLIATO: /webhook/ordini
GIUSTO:    /webhook/a7f3b2c1-ordini-9d4e

Checklist:

  • Ogni webhook ha autenticazione (header secret o HMAC)
  • URL webhook non prevedibili
  • Validazione del payload nel workflow

3.2 Aggiornamenti regolari

n8n rilascia aggiornamenti frequenti che includono fix di sicurezza:

# Con Docker Compose
docker compose pull
docker compose up -d

# Verifica versione
docker exec n8n n8n --version

Checklist:

  • Procedura di aggiornamento documentata
  • Aggiornamenti applicati entro 7 giorni dal rilascio
  • Backup prima di ogni aggiornamento

3.3 Logging e audit

Configura n8n per registrare le attività:

# Logging
N8N_LOG_LEVEL=info
N8N_LOG_OUTPUT=console,file
N8N_LOG_FILE_LOCATION=/data/logs/n8n.log
N8N_LOG_FILE_MAX_SIZE=20

# Esecuzioni
EXECUTIONS_DATA_SAVE_ON_ERROR=all
EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true

Configura la rotazione dei log:

# /etc/logrotate.d/n8n
/data/logs/n8n.log {
    daily
    rotate 30
    compress
    missingok
    notifempty
}

Checklist:

  • Logging attivo su file
  • Rotazione log configurata
  • Esecuzioni salvate (successi e errori)
  • Log accessibili per audit

3.4 Isolamento con Docker

Se usi Docker (consigliato), configura l'isolamento correttamente:

# docker-compose.yml
services:
  n8n:
    image: n8nio/n8n:latest
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
    volumes:
      - n8n_data:/home/node/.n8n
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      # ... altre variabili ...
    networks:
      - n8n_network
    # NON esporre la porta 5678 all'esterno
    # ports:
    #   - "5678:5678"  # NO!
    expose:
      - "5678"  # Solo internamente alla rete Docker

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - /etc/letsencrypt:/etc/letsencrypt:ro
    networks:
      - n8n_network

networks:
  n8n_network:
    driver: bridge

volumes:
  n8n_data:

Checklist:

  • n8n in container Docker isolato
  • Porta 5678 non esposta all'esterno (solo expose, non ports)
  • no-new-privileges attivo
  • Volume dati persistente

Livello 4: backup e disaster recovery

4.1 Backup automatico dei dati n8n

#!/bin/bash
# /opt/scripts/backup-n8n.sh

BACKUP_DIR="/opt/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
N8N_DATA="/var/lib/docker/volumes/n8n_data/_data"

mkdir -p "$BACKUP_DIR"

# Esporta workflow
docker exec n8n n8n export:workflow --all --output="/tmp/workflows_${DATE}.json"
docker cp n8n:/tmp/workflows_${DATE}.json "$BACKUP_DIR/"

# Esporta credenziali (criptate)
docker exec n8n n8n export:credentials --all --output="/tmp/credentials_${DATE}.json"
docker cp n8n:/tmp/credentials_${DATE}.json "$BACKUP_DIR/"

# Backup database SQLite
cp "$N8N_DATA/database.sqlite" "$BACKUP_DIR/database_${DATE}.sqlite"

# Comprimi
tar -czf "$BACKUP_DIR/n8n_backup_${DATE}.tar.gz" \
  "$BACKUP_DIR/workflows_${DATE}.json" \
  "$BACKUP_DIR/credentials_${DATE}.json" \
  "$BACKUP_DIR/database_${DATE}.sqlite"

# Pulisci file temporanei
rm "$BACKUP_DIR/workflows_${DATE}.json" \
   "$BACKUP_DIR/credentials_${DATE}.json" \
   "$BACKUP_DIR/database_${DATE}.sqlite"

# Mantieni solo gli ultimi 30 backup
find "$BACKUP_DIR" -name "n8n_backup_*.tar.gz" -mtime +30 -delete

echo "Backup completato: $BACKUP_DIR/n8n_backup_${DATE}.tar.gz"

Aggiungi al crontab:

# Backup giornaliero alle 3:00
0 3 * * * /opt/scripts/backup-n8n.sh >> /var/log/n8n-backup.log 2>&1

Checklist:

  • Backup automatico giornaliero attivo
  • Backup include workflow, credenziali e database
  • Retention policy definita (es. 30 giorni)
  • Backup testato con restore (almeno 1 volta/mese)
  • Backup copiato su storage esterno (non solo sullo stesso server)

Riepilogo checklist completa

Priorità critica (giorno 1)

  • Reverse proxy Nginx configurato
  • SSL/TLS attivo con rinnovo automatico
  • Autenticazione con password forte
  • Chiave di cifratura impostata e salvata

Priorità alta (prima settimana)

  • Rate limiting attivo
  • Fail2ban configurato
  • Firewall UFW attivo
  • Variabili d'ambiente per credenziali

Priorità media (primo mese)

  • Webhook protetti con secret
  • Procedura aggiornamenti definita
  • Logging e audit attivi
  • Docker con isolamento corretto

Priorità normale (ongoing)

  • Backup automatici testati
  • Disaster recovery plan documentato
  • Review sicurezza trimestrale
  • Aggiornamenti applicati regolarmente

Ogni punto di questa checklist riduce la superficie di attacco della tua istanza. Non serve implementarli tutti in un giorno, ma ignora quelli di priorità critica a tuo rischio.


Hai dubbi sulla sicurezza della tua istanza n8n? Contattaci per un audit di sicurezza personalizzato.

T

Team n8n.it

Specialisti in Automazione

Siamo un team di esperti n8n focalizzati sull'automazione dei processi aziendali e la sicurezza delle implementazioni self-hosted.

Articoli correlati