n8n — Installation sur Raspberry Pi (Podman + PostgreSQL)

# Stack

  • OS : Debian 12 Bookworm (aarch64)
  • n8n : v2.37.11 (stable, épinglé) — containerisé
  • Container : Podman 4.3.1, managé par systemd (podman generate systemd)
  • Base de données : PostgreSQL 15.18 (installation système via apt)
  • Réseau : Network=host (pas de reverse proxy, pas de SSL, LAN uniquement)
  • Utilisateur container : node (UID 1000) — pas de remap USER_UID/USER_GID possible
  • Données : /var/lib/n8n/home/node/.n8n dans le container

Pourquoi ce montage ? L’image officielle n8n tourne en UID 1000 fixe (node) et ne supporte pas les variables USER_UID/USER_GID contrairement à Forgejo. Le répertoire hôte doit donc être possédé par UID 1000 avant le premier démarrage, sinon erreurs d’écriture dans /home/node/.n8n.

# Architecture

┌────────────────────────────────────────────┐
│  HÔTE (raspberrypi)                        │
│                                            │
│  ┌─────────────────────────┐   ┌─────────┐ │
│  │  Container n8n          │   │ Postgres│ │
│  │  ┌───────────────────┐  │   │ :5432   │ │
│  │  │ n8n editor+API    │  │   └─────────┘ │
│  │  │ :5678 (HTTP)      │  │               │
│  │  │ Task broker       │  │               │
│  │  │ 127.0.0.1:5679    │  │               │
│  │  │                   │  │               │
│  │  │ /home/node/.n8n   │  │               │
│  │  │   → /var/lib/n8n  │  │               │
│  │  └───────────────────┘  │               │
│  └─────────────────────────┘               │
│       Network=host (127.0.0.1:5432)        │
└────────────────────────────────────────────┘

Le Task Broker interne (runners JS) écoute sur 127.0.0.1:5679 — non exposé, contrairement au port 5678. Vérifié dans les logs au démarrage.

# Fichiers de configuration

# 1. Service systemd — /etc/systemd/system/n8n.service

Généré par podman generate systemd --new, puis After=postgresql.service ajouté manuellement :

[Unit]
Description=Podman container-n8n.service
Wants=network-online.target
After=network-online.target postgresql.service
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run \
	--cidfile=%t/%n.ctr-id \
	--cgroups=no-conmon \
	--rm \
	--sdnotify=conmon \
	--replace \
	-d \
	--name n8n \
	--network host \
	-v /var/lib/n8n:/home/node/.n8n:Z \
	-e GENERIC_TIMEZONE=Europe/Paris \
	-e TZ=Europe/Paris \
	-e N8N_HOST=192.168.0.80 \
	-e N8N_PROTOCOL=http \
	-e N8N_PORT=5678 \
	-e DB_TYPE=postgresdb \
	-e DB_POSTGRESDB_HOST=127.0.0.1 \
	-e DB_POSTGRESDB_PORT=5432 \
	-e DB_POSTGRESDB_DATABASE=n8n \
	-e DB_POSTGRESDB_USER=n8n \
	-e DB_POSTGRESDB_PASSWORD=<password> docker.io/n8nio/n8n:2.37.11
ExecStop=/usr/bin/podman stop --ignore -t 10 --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore -t 10 --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target

Note : le mot de passe est aussi stocké dans /etc/n8n/pg_password (root only, mode 700). Pas de fichier app.ini ici — la config n8n passe par variables d’environnement, le reste (owner, préférences) vit dans la base PostgreSQL.

# 2. Variables clés

Variable Valeur Rôle
N8N_HOST / N8N_PROTOCOL / N8N_PORT 192.168.0.80 / http / 5678 URLs générées (webhooks) et cookie
GENERIC_TIMEZONE / TZ Europe/Paris Fuseau des executions et du container
DB_TYPE=postgresdb + DB_POSTGRESDB_*   Connexion au PostgreSQL hôte via 127.0.0.1:5432

Pas de N8N_RUNNERS_ENABLED : le Task Broker démarre par défaut sur 127.0.0.1:5679.

# PostgreSQL

CREATE ROLE n8n WITH LOGIN PASSWORD '<password>';
CREATE DATABASE n8n OWNER n8n;

Différence avec Forgejo : pas de CREATE SCHEMA n8n AUTHORIZATION n8n ici. n8n utilise le schéma public de sa propre base (propriétaire = pg_database_owner en PG15, donc le rôle n8n peut créer ses tables sans privilèges supplémentaires). 131 tables créées par les migrations au premier démarrage.

# Commandes utiles

# Gestion du service
sudo systemctl status n8n          # Statut
sudo systemctl restart n8n         # Redémarrage
sudo journalctl -u n8n -f          # Logs en direct

# Inspecter le container
sudo podman logs n8n               # Logs n8n
sudo podman exec -u node n8n ls /home/node/.n8n   # Explorer le volume

# Vérifier la santé
curl http://localhost:5678/healthz # → {"status":"ok"}

# PostgreSQL
sudo -u postgres psql -d n8n       # Console DB

# Mise à jour

sudo podman pull docker.io/n8nio/n8n:<nouvelle-version>
# Éditer /etc/systemd/system/n8n.service : remplacer le tag de version
sudo systemctl daemon-reload && sudo systemctl restart n8n

Tag toujours épinglé (jamais latest) — n8n publie plusieurs fois par semaine.

# Accès

  • HTTP (LAN) : http://192.168.0.80:5678
  • Tailscale : http://bastion:5678
  • Premier lancement : wizard de création du compte owner (email + mot de passe), type d’instance Self-hosted, télémetrie désactivable.

# Limites & pièges

  • Webhooks publics : en Network=host + HTTP, les webhooks ne sont joignables que depuis le LAN. Pour exposer à internet il faudra un reverse proxy TLS et la variable WEBHOOK_URL — hors périmètre actuel.
  • Permissions : oublier le chown 1000:1000 /var/lib/n8n avant le premier démarrage → n8n ne peut pas écrire sa config. Symptôme : erreurs d’accès à /home/node/.n8n.
  • Cookie en HTTP pur : si boucle de login sur http://, ajouter N8N_SECURE_COOKIE=false.
  • s6-override : sans objet — l’image n8n utilise tini, pas s6 (contrairement à Forgejo).
  • Version : migrations automatiques au démarrage ; toujours sauvegarder la base (pg_dump n8n) avant une montée de version majeure.
Written on September 9, 2026, Last update on
n8n hermes