Installer Docker Engine et Docker Compose.
On part de zéro avec votre Ubuntu 24.04 fraîchement durci au chapitre 2. Première étape : installer Docker selon la procédure officielle. N'utilisez pas apt install docker.io (paquet Ubuntu obsolète), utilisez le repository officiel Docker.
# Connecté en SSH en tant que "deploy"
# Mise à jour préliminaire
sudo apt update
sudo apt install -y ca-certificates curl gnupg
# Ajouter la clé GPG officielle Docker
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Ajouter le repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Installer Docker Engine + Docker Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# Vérifier
sudo docker --version
sudo docker compose version
Vous devriez voir des versions récentes (Docker 25.x ou plus, Compose v2.x). Pour pouvoir lancer docker sans sudo, ajoutez votre utilisateur au groupe docker :
sudo usermod -aG docker deploy
# Recharger les groupes (ou se reconnecter en SSH)
newgrp docker
# Test
docker ps
Préparer la structure de fichiers n8n.
Créez un dossier dédié pour la stack n8n. On utilise /opt/n8n par convention pour les services système :
sudo mkdir -p /opt/n8n
sudo chown deploy:deploy /opt/n8n
cd /opt/n8n
On va créer 3 fichiers : docker-compose.yml (la stack), .env (les secrets), et init-data.sh (un script qui crée un utilisateur PostgreSQL non-root au premier démarrage).
Le fichier docker-compose.yml de production.
Voici le compose officiel adapté de github.com/n8n-io/n8n-hosting, avec les valeurs sécurisées et la version pinnée :
nano /opt/n8n/docker-compose.yml
Collez exactement ce contenu :
volumes:
db_storage:
n8n_storage:
services:
postgres:
image: postgres:16
restart: always
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_NON_ROOT_USER=${POSTGRES_NON_ROOT_USER}
- POSTGRES_NON_ROOT_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 10
# Pas d'exposition du port, accessible uniquement via le reseau Docker
n8n:
image: docker.n8n.io/n8nio/n8n:2.18.5
restart: always
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
- N8N_HOST=${N8N_HOST}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://${N8N_HOST}/
- N8N_EDITOR_BASE_URL=https://${N8N_HOST}/
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_PROXY_HOPS=1
- GENERIC_TIMEZONE=Europe/Paris
- TZ=Europe/Paris
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=168
ports:
- "127.0.0.1:5678:5678"
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
Le script d'initialisation PostgreSQL.
Ce script crée un utilisateur PostgreSQL non-administrateur dédié à n8n. Bonne pratique de sécurité standard : ne jamais utiliser le compte super-admin Postgres pour une application.
nano /opt/n8n/init-data.sh
#!/bin/bash
set -e
if [ -n "${POSTGRES_NON_ROOT_USER:-}" ] && [ -n "${POSTGRES_NON_ROOT_PASSWORD:-}" ]; then
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER ${POSTGRES_NON_ROOT_USER} WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_NON_ROOT_USER};
GRANT CREATE ON SCHEMA public TO ${POSTGRES_NON_ROOT_USER};
EOSQL
else
echo "SETUP INFO: No Environment variables given!"
fi
Rendez le script exécutable :
chmod +x /opt/n8n/init-data.sh
Générer les secrets et créer le fichier .env.
C'est le moment le plus critique de toute la procédure. La N8N_ENCRYPTION_KEY chiffre tous vos credentials (API keys, tokens OAuth) en AES-256. Si vous la perdez, tous vos credentials deviennent illisibles pour toujours.
Générez les 3 secrets nécessaires :
# Encryption key n8n (CRITIQUE - sauvegardez immédiatement)
openssl rand -hex 32
# Mot de passe Postgres super-admin
openssl rand -base64 24
# Mot de passe Postgres non-root user (utilisé par n8n)
openssl rand -base64 24
Copiez ces 3 valeurs dans un endroit sûr (gestionnaire de mots de passe : Bitwarden, 1Password, KeePass). On va maintenant les mettre dans le fichier .env.
nano /opt/n8n/.env
# PostgreSQL
POSTGRES_USER=postgres
POSTGRES_PASSWORD=COLLER_LE_PREMIER_MOT_DE_PASSE_ICI
POSTGRES_DB=n8n
POSTGRES_NON_ROOT_USER=n8n
POSTGRES_NON_ROOT_PASSWORD=COLLER_LE_DEUXIEME_MOT_DE_PASSE_ICI
# n8n
N8N_HOST=n8n.votreboite.fr
N8N_ENCRYPTION_KEY=COLLER_LA_CLE_HEX_DE_64_CARACTERES_ICI
Remplacez n8n.votreboite.fr par votre vrai sous-domaine (que vous configurerez chez votre registrar pour qu'il pointe vers l'IP du VPS).
Protégez le fichier .env contre les lectures non autorisées :
chmod 600 /opt/n8n/.env
ls -la /opt/n8n/.env
# Doit afficher : -rw------- 1 deploy deploy ...
Premier démarrage de la stack.
Lancez la stack en mode détaché :
cd /opt/n8n
docker compose up -d
Attendez 30 secondes que PostgreSQL initialise sa base, puis vérifiez l'état :
docker compose ps
# Les deux services doivent être "healthy" (postgres) et "running" (n8n)
docker compose logs n8n --tail=50
# Cherchez : "Editor is now accessible via:"
Si vous voyez des erreurs de connexion à Postgres, c'est généralement que le mot de passe a un caractère spécial mal échappé. Mettez votre mot de passe entre guillemets simples dans le .env, ou régénérez-en un sans caractères spéciaux.
Test temporaire via tunnel SSH.
n8n n'est pas encore exposé publiquement (on n'a pas Caddy). Pour vérifier qu'il tourne, créez un tunnel SSH temporaire depuis votre poste :
# Sur votre poste local
ssh -L 5678:localhost:5678 deploy@VOTRE_IP_VPS
Ouvrez votre navigateur sur http://localhost:5678. Vous devriez voir l'écran d'accueil n8n vous demandant de créer le premier compte owner.
Activation de la licence Community gratuite.
n8n Community est gratuit et open-source. Mais depuis la v1.x, n8n demande une activation gratuite pour débloquer certaines features (workflows multi-utilisateurs, partage). C'est totalement gratuit, juste un email à fournir.
Dans n8n : Settings → Community → "Get free license". Vous recevez une clé par email à coller. C'est fait en 2 minutes.
Vérifications finales avant Caddy.
Avant de passer au chapitre suivant, vérifiez que tout est sain :
- ✅ docker compose ps retourne 2 services up et postgres healthy
- ✅ Logs n8n sans erreur (docker compose logs n8n --tail=100)
- ✅ Vous accédez à n8n via tunnel SSH sur localhost:5678
- ✅ Compte owner créé, 2FA activée
- ✅ Licence Community activée
- ✅ N8N_ENCRYPTION_KEY sauvegardée dans 3 endroits indépendants
- ✅ Fichier .env permissions 600
Si tout est vert, fermez le tunnel SSH et passez au chapitre 4 : on installe Caddy pour exposer n8n en HTTPS proprement, on durcit la sécurité, et on active la 2FA.