Su AlmaLinux 9 la strada più pulita per n8n è installarlo come servizio systemd dietro un reverse proxy, con Node.js LTS, utente dedicato e database esterno se vuoi qualcosa che regga il carico senza diventare fragile al primo riavvio. L’obiettivo non è “farlo partire”, ma tenerlo stabile, aggiornabile e recuperabile senza interventi manuali ogni volta.
Qui sotto trovi una procedura lineare: prerequisiti, installazione di Node.js, utente e directory dedicate, configurazione di n8n, servizio systemd, Nginx come front-end HTTPS e verifiche finali. L’esempio usa porta locale 5678 e dominio dedicato, ma la logica resta la stessa anche dietro un bilanciatore o una CDN.
Scelta architetturale prima di toccare il server
n8n può girare in modalità semplice con il database SQLite incluso, ma in produzione questa scelta va bene solo per prove, automazioni leggere o ambienti dove il ripristino è più importante della continuità. Se prevedi esecuzioni concorrenti, webhook esposti, più utenti o crescita nel tempo, passa subito a PostgreSQL. Eviti lock inutili, semplifichi backup e riduci il rischio di corruzione del file locale.
Per un’installazione pulita su AlmaLinux 9 la base minima sensata è questa: Node.js LTS, un utente non privilegiato, una directory dati separata, systemd per l’avvio automatico e un reverse proxy per terminare TLS. Se il server è esposto a Internet, aggiungi firewall e, se possibile, restrizioni lato rete per limitare l’accesso diretto alla porta applicativa.
1. Aggiorna il sistema e verifica i prerequisiti
Parti da un sistema aggiornato e controlla che non ci siano pacchetti in conflitto. Su AlmaLinux 9 il punto di ingresso è semplice:
sudo dnf update -y
sudo dnf install -y curl wget git unzip tar policycoreutils-python-utils firewalld
Se `firewalld` non è già attivo, abilitalo subito. Su una macchina esposta, lasciare porte aperte “per comodità” è il modo più veloce per creare debito operativo.
sudo systemctl enable --now firewalld
sudo firewall-cmd --state
L’output atteso è `running`. Se non lo è, fermati e chiudi prima il problema di base: senza controllo del traffico, il resto della configurazione conta poco.
2. Installa Node.js LTS in modo coerente
n8n segue bene le versioni LTS di Node.js. Su AlmaLinux 9 puoi usare il modulo ufficiale di NodeSource o repository equivalenti; qui uso un flusso diretto e leggibile. Prima verifica il contesto: se nel server hai già applicazioni Node, allinea la versione per evitare incompatibilità tra runtime diversi.
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
Controlla che la versione sia quella attesa:
node -v
npm -v
Se `node -v` restituisce una major LTS compatibile e `npm -v` risponde senza errori, puoi andare avanti. Evita di installare n8n come root e evita anche di fare affidamento sul profilo shell di un utente amministrativo: in produzione è un antipattern che complica permessi, backup e troubleshooting.
3. Crea utente dedicato, directory e permessi
La separazione minima corretta è un utente di servizio con home dedicata e directory dati esplicita. Questo riduce il blast radius: se n8n viene compromesso o si rompe, il resto del sistema resta più isolato.
sudo useradd --system --create-home --home-dir /var/lib/n8n --shell /sbin/nologin n8n
sudo mkdir -p /var/lib/n8n /etc/n8n
sudo chown -R n8n:n8n /var/lib/n8n /etc/n8n
Se prevedi file persistenti, log dedicati o backup, definisci già le directory prima di partire. È più semplice standardizzare adesso che inseguire permessi sparsi dopo il primo avvio fallito.
4. Installa n8n globalmente o in una directory controllata
Per un server unico, l’installazione globale via npm è la via più lineare. Se vuoi massima ripetibilità, puoi anche usare una directory applicativa con package-lock e servizio che punta al binario locale. Qui resta la soluzione semplice, ma non per questo fragile.
sudo npm install -g n8n
Verifica che il binario sia presente e raggiungibile:
which n8n
n8n --version
Se `which n8n` non restituisce un path coerente con il prefisso di npm, il problema è nel PATH o nel metodo di installazione. In quel caso non andare avanti a tentativi: prima risolvi la visibilità del comando, poi il servizio.
5. Prepara la configurazione di runtime
n8n legge bene le variabili d’ambiente. Su un’installazione manuale conviene mettere tutto in un file dedicato con permessi stretti, così il servizio systemd lo carica in modo deterministico. Per esempio:
sudo tee /etc/n8n/n8n.env > /dev/null <<'EOF'
N8N_HOST=n8n.example.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.example.com/
N8N_EDITOR_BASE_URL=https://n8n.example.com/
N8N_ENCRYPTION_KEY=replace-with-strong-random-value
N8N_BASIC_AUTH_ACTIVE=false
N8N_DIAGNOSTICS_ENABLED=false
EOF
sudo chown root:n8n /etc/n8n/n8n.env
sudo chmod 640 /etc/n8n/n8n.env
Qui c’è un punto importante: `N8N_ENCRYPTION_KEY` non va trattata come una password qualsiasi. Se la perdi, i segreti salvati dentro n8n non saranno più decifrabili; se la esponi, hai creato un problema serio. Generane una nuova con un comando locale e conserva il valore in un vault o in un sistema di segreti, non in chiaro in chat o nei ticket.
openssl rand -hex 32
Se vuoi usare PostgreSQL, aggiungi le variabili dedicate al database e prepara il servizio prima del primo avvio. In questa guida resto su SQLite per tenere il flusso lineare, ma per ambienti condivisi la migrazione a PostgreSQL è la scelta giusta.
6. Crea il servizio systemd per n8n
systemd ti dà avvio automatico, restart policy e log centralizzati. Il servizio deve partire come utente `n8n`, caricare il file ambiente e scrivere il database nella home dedicata. Un’unità minimale può essere questa:
sudo tee /etc/systemd/system/n8n.service > /dev/null <<'EOF'
[Unit]
Description=n8n automation platform
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=n8n
Group=n8n
EnvironmentFile=/etc/n8n/n8n.env
WorkingDirectory=/var/lib/n8n
ExecStart=/usr/bin/n8n
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ReadWritePaths=/var/lib/n8n
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now n8n
Il blocco di hardening non è decorativo: `NoNewPrivileges`, `PrivateTmp` e `ProtectSystem` riducono il rischio che un processo compromesso faccia più danni del necessario. Occhio però a `ProtectHome=true`: se cambi percorsi o plugin, potresti dover aprire directory specifiche con `ReadWritePaths`.
Verifica subito lo stato del servizio:
sudo systemctl status n8n --no-pager
sudo journalctl -u n8n -b --no-pager | tail -n 50
Se il servizio fallisce, il journal ti dice quasi sempre dove guardare: porta occupata, variabile mancante, permessi insufficienti o path sbagliato del binario. Non cambiare più cose insieme. Correggi un punto, riavvia, osserva di nuovo.
7. Esporre n8n dietro Nginx con HTTPS
Lasciare n8n esposto direttamente su 5678 non è una buona idea. Il reverse proxy ti consente TLS, header corretti, eventuale rate limiting e una gestione più pulita dei certificati. Su AlmaLinux 9 con Nginx il setup base è lineare.
sudo dnf install -y nginx
sudo systemctl enable --now nginx
Configura un server block dedicato, ad esempio in `/etc/nginx/conf.d/n8n.conf`:
server {
listen 80;
server_name n8n.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name n8n.example.com;
ssl_certificate /etc/letsencrypt/live/n8n.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.example.com/privkey.pem;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
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 https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}
}
Prima di ricaricare Nginx, valida la sintassi. È il controllo più economico che puoi fare e ti evita di buttare giù il front-end per un punto e virgola fuori posto.
sudo nginx -t
sudo systemctl reload nginx
Per il certificato puoi usare Let’s Encrypt con certbot, oppure un certificato già gestito dal tuo stack. Se usi certbot, il flusso tipico è questo:
sudo dnf install -y certbot python3-certbot-nginx
sudo certbot --nginx -d n8n.example.com
Dopo l’emissione, controlla che il redirect verso HTTPS sia attivo e che il certificato sia servito dal nome corretto. Un mismatch tra `N8N_HOST`, `WEBHOOK_URL` e il server block è una delle cause più comuni di webhook che non tornano o URL generati male nell’editor.
8. Apri solo le porte necessarie
Se Nginx termina TLS, al firewall servono solo 80 e 443. La porta 5678 deve restare locale, non pubblica. È una regola semplice, ma spesso viene dimenticata quando si testa velocemente su un server nuovo.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services
Se vuoi essere più rigido, usa regole rich specifiche per l’IP di management o per la sola subnet di frontend. In produzione, meno superficie esponi e meno tempo perdi in audit e incident response.
9. Primo avvio funzionale e verifica end-to-end
A questo punto il test non è “il servizio è attivo”, ma “l’intero percorso funziona”: systemd, n8n, Nginx, TLS e accesso web. Verifica prima localmente e poi dal dominio pubblico.
curl -I http://127.0.0.1:5678
curl -Ik https://n8n.example.com
Il primo comando deve rispondere con un codice HTTP coerente con il servizio vivo; il secondo deve mostrare una risposta TLS valida e un redirect o una pagina raggiungibile secondo la tua configurazione. Se `curl -Ik` fallisce ma il servizio è attivo, il problema è quasi sempre tra Nginx, certificato, DNS o `server_name` errato.
Apri poi l’interfaccia web e crea un workflow minimale, per esempio un trigger manuale con un nodo di output. Questo ti conferma che editor, sessione e persistenza funzionano davvero. Non fermarti al solo login: alcuni problemi emergono solo quando n8n prova a salvare o a eseguire un workflow.
10. Backup e ripristino: decidi prima di averne bisogno
Con SQLite il backup minimo è il file del database e la directory dati di n8n. Con PostgreSQL devi aggiungere dump coerenti del database e, se usi allegati o file esterni, anche il loro storage. In ogni caso non aspettare il primo guasto per capire cosa salvare.
sudo systemctl stop n8n
sudo tar -czf /root/n8n-backup-$(date +%F).tar.gz /var/lib/n8n /etc/n8n
sudo systemctl start n8n
Lo stop temporaneo riduce il rischio di snapshot incoerenti con SQLite. Se vuoi fare meglio, usa un backup a caldo solo dopo aver validato la consistenza del file e il comportamento del tuo storage. Il punto chiave è uno: un backup non testato non è un backup, è un’ipotesi.
11. Errori tipici e come leggerli in fretta
Se n8n non parte, il primo file da guardare è il journal di systemd. Se la UI si apre ma i webhook non rispondono, guarda `WEBHOOK_URL`, proxy headers e DNS. Se i workflow falliscono in modo intermittente, sospetta risorse insufficienti, limiti di memoria o un database troppo lento.
sudo journalctl -u n8n -b --no-pager | tail -n 100
sudo ss -lntp | grep 5678
sudo tail -n 50 /var/log/nginx/error.log
Un errore molto comune è l’allineamento sbagliato tra host pubblico e URL interni. Se il browser vede `https://n8n.example.com` ma n8n genera callback o webhook su `http://localhost:5678`, la diagnosi è quasi già scritta nei log. In questi casi correggere il proxy senza sistemare le variabili d’ambiente risolve solo metà del problema.
12. Hardening minimo che vale davvero la pena fare
La sicurezza non si risolve con un singolo parametro, ma alcune scelte riducono parecchio l’esposizione. Tieni aggiornati Node.js e n8n, limita l’accesso amministrativo, usa un secret manager o almeno permessi stretti sul file ambiente, e disabilita tutto ciò che non ti serve. Se l’istanza è per un team, pianifica l’accesso con account individuali e non con credenziali condivise.
Se vuoi aggiungere un ulteriore livello di protezione, valuta l’autenticazione a monte sul reverse proxy o un access control esterno. È utile soprattutto quando l’istanza è destinata a integrazioni interne e non a utenti finali. Il punto non è complicare l’accesso, ma ridurre il rischio che una dashboard esposta venga scansionata come qualsiasi altro servizio web.
13. Quando passare a PostgreSQL
Il momento giusto non è “quando SQLite si rompe”, ma prima che il carico renda scomoda la manutenzione. Se hai workflow critici, più utenti, esecuzioni concorrenti o retention lunga dei dati, PostgreSQL è la base corretta. Ti semplifica backup, replica, manutenzione e, soprattutto, ti evita di trattare un file locale come se fosse un database server.
La migrazione va pianificata con calma: backup completo, finestra di cambio, test su istanza parallela e verifica dei segreti. Se il tuo ambiente è già in produzione, non farla durante una giornata operativa piena. Il rischio non è solo il database, ma anche la coerenza dei workflow e dei webhook in corso.
Checklist finale operativa
Se vuoi una verifica rapida prima di considerare chiusa l’installazione, controlla questi punti: servizio attivo, porta locale in ascolto, reverse proxy valido, TLS funzionante, URL pubblici coerenti, backup definito e segreti fuori dal testo in chiaro. Sono i dettagli che separano un test riuscito da un’installazione davvero usabile.
systemctl is-active n8n
ss -lntp | grep 5678
curl -Ik https://n8n.example.com
journalctl -u n8n -b --no-pager | tail -n 20
Se tutti questi controlli tornano, hai un’installazione n8n su AlmaLinux 9 che non dipende dalla sessione del terminale, non espone più del necessario e può essere gestita come un servizio vero. Da qui in poi il lavoro serio è manutenzione: aggiornamenti, backup testati e monitoraggio dei log prima che gli utenti ti segnalino il problema.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.