Installation Guide for n8n on Linux Server
What is n8n?
n8n (pronounced "n-eight-n") is an open-source, self-hosted workflow automation platform. It allows you to connect different applications and services to automate repetitive tasks, all through an intuitive visual interface with "drag and drop" capabilities.
n8n is often presented as a self-hosted alternative to SaaS solutions like Zapier, Make (formerly Integromat), or Microsoft Power Automate, with the advantage of maintaining full control over your data.
Main Features
- +400 native integrations: Gmail, Slack, Notion, GitHub, Google Sheets, Stripe, databases, REST APIs, etc.
- Visual workflow editor: Workflow creation through drag and drop
- Integrated AI nodes: Native support for OpenAI, Ollama, and other LLM models
- Event-based execution: Webhooks, cron scheduling, manual triggers
- Custom code: Ability to integrate JavaScript or Python into workflows
- Full API: Programmatic workflow management
- Multi-users: Team and permission management (Enterprise version)
Typical Use Cases
- Automatic data synchronization between applications
- Automated notifications and alerts
- Collection and processing of marketing leads
- Automation of reports and dashboards
- Integration with AI tools for data analysis
- DevOps automation (CI/CD, monitoring, alerts)
Documented Version
This guide covers the installation of n8n version 1.123.x (recommended stable version for production).
ℹ️ Note: Version 2.0 is currently in beta (December 2025). It brings security and stability improvements but requires migration. For a production environment, we recommend the stable 1.x version.
Prerequisites
Hardware Configuration
| Resource | Minimum | Recommended (Production) |
|---|---|---|
| CPU | 2 cores | 4 cores |
| RAM | 2 GB | 4-8 GB |
| Storage | 10 GB SSD | 50 GB SSD |
| Bandwidth | 100 Mbps | 1 Gbps |
💡 Tip: For complex workflows or intensive usage with many users, consider a minimum of 8 GB of RAM and 4 CPU cores.
Required Software
| Software | Minimum Version | Role |
|---|---|---|
| Operating System | Debian 12 / Ubuntu 22.04+ | Server OS |
| Docker | 20.10+ | Containerization |
| Docker Compose | 2.0+ (plugin) | Container orchestration |
| Nginx | 1.18+ | Reverse proxy |
| Certbot | 2.0+ | Let's Encrypt SSL certificates |
Used Network Ports
| Port | Protocol | Usage | Exposure |
|---|---|---|---|
| 22 | TCP | SSH | External (administration) |
| 80 | TCP | HTTP (redirect to HTTPS) | External |
| 443 | TCP | HTTPS | External |
| 5678 | TCP | n8n (internal) | Localhost only |
| 5432 | TCP | PostgreSQL (internal) | Localhost only |
Domain Name and DNS
Before starting, make sure you have:
- A domain name or subdomain (e.g.,
n8n.yourdomain.com) - A DNS record of type A pointing to your server's public IP
Example DNS configuration:
n8n.yourdomain.com. IN A 203.0.113.50
Step-by-Step Installation
Step 1: System Update
Connect to your server via SSH and update the packages:
sudo apt update && sudo apt upgrade -y
This command updates the list of available packages and installs the latest versions of installed packages.
Step 2: Docker Installation
Install the necessary dependencies:
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
Add the official Docker GPG key:
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release && echo "$ID")/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Add the Docker repository:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/$(. /etc/os-release && echo "$ID") $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Install Docker Engine and Compose plugin:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Add your user to the docker group (to avoid using sudo):
sudo usermod -aG docker $USER
newgrp docker
Verification Point: Check the installation:
docker --version
docker compose version
You should see the installed versions (Docker 24.x+ and Compose 2.x+).
Step 3: Directory Structure Creation
Create the working directory for n8n:
sudo mkdir -p /opt/docker-compose/n8n
cd /opt/docker-compose/n8n
Create subdirectories for persistent data:
sudo mkdir -p n8n_data postgres_data
Assign correct permissions:
sudo chown -R 1000:1000 n8n_data
sudo chown -R 999:999 postgres_data
ℹ️ Explanation: The UIDs 1000 and 999 correspond respectively to the users
node(in the n8n container) andpostgres(in the PostgreSQL container).
Step 4: Environment File Creation
Create the .env file to store sensitive variables:
sudo nano /opt/docker-compose/n8n/.env
Add the following content modifying the values:
# ===========================================
# n8n Configuration - OuiHeberg
# ===========================================
# Domain and URL
N8N_HOST=n8n.yourdomain.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com/
# Security
N8N_ENCRYPTION_KEY=YourEncryptionKeyMin32Characters!
N8N_PROXY_HOPS=1
# Timezone
GENERIC_TIMEZONE=Europe/Paris
TZ=Europe/Paris
# PostgreSQL Database
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=YourPostgresPassword123!
# PostgreSQL Variables (for the container)
POSTGRES_DB=n8n
POSTGRES_USER=n8n
POSTGRES_PASSWORD=YourPostgresPassword123!
POSTGRES_NON_ROOT_USER=n8n
POSTGRES_NON_ROOT_PASSWORD=YourPostgresPassword123!
⚠️ Important: Replace the following:
n8n.yourdomain.comwith your actual domainYourEncryptionKeyMin32Characters!with a unique and complex key (min. 32 characters)YourPostgresPassword123!with a secure password
Generate a secure encryption key:
openssl rand -hex 32
Step 5: Docker Compose File Creation
Create the docker-compose.yml file:
sudo nano /opt/docker-compose/n8n/docker-compose.yml
Add the following content:
version: '3.8'
services:
# ===========================================
# PostgreSQL Database
# ===========================================
postgres:
image: postgres:15-alpine
container_name: n8n-postgres
restart: unless-stopped
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- ./postgres_data:/var/lib/postgresql/data
networks:
- n8n-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
# ===========================================
# n8n Application
# ===========================================
n8n:
image: docker.n8n.io/n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
# General Configuration
- N8N_HOST=${N8N_HOST}
- N8N_PORT=${N8N_PORT}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- WEBHOOK_URL=${WEBHOOK_URL}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_PROXY_HOPS=${N8N_PROXY_HOPS}
# Timezone
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${TZ}
# Database
- DB_TYPE=${DB_TYPE}
- DB_POSTGRESDB_HOST=${DB_POSTGRESDB_HOST}
- DB_POSTGRESDB_PORT=${DB_POSTGRESDB_PORT}
- DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE}
- DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_POSTGRESDB_PASSWORD}
ports:
- "127.0.0.1:5678:5678"
volumes:
- ./n8n_data:/home/node/.n8n
networks:
- n8n-network
networks:
n8n-network:
driver: bridge
💡 Note: Port 5678 is exposed only on
127.0.0.1(localhost) for security reasons. External access will be through the Nginx reverse proxy.
Step 6: Container Startup
Launch the containers in the background:
cd /opt/docker-compose/n8n
docker compose up -d
Verification Point: Check that the containers are running:
docker compose ps
You should see both containers (n8n and n8n-postgres) with status Up or running (healthy).
Check logs in case of issues:
docker compose logs -f n8n
Test local access:
curl http://localhost:5678/healthz
The response should be {"status":"ok"}.
Configuration
Nginx Reverse Proxy Configuration
Nginx Installation
sudo apt install -y nginx
Check if Nginx is active:
sudo systemctl status nginx
Configuration File Creation
Create the configuration file for n8n:
sudo nano /etc/nginx/sites-available/n8n
Add the following content:
# ===========================================
# Nginx Configuration for n8n - OuiHeberg
# ===========================================
# Map for WebSocket management
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP to HTTPS redirection
server {
listen 80;
listen [::]:80;
server_name n8n.yourdomain.com;
# Permanent redirection to HTTPS
return 301 https://$host$request_uri;
}
# HTTPS Configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name n8n.yourdomain.com;
# SSL Certificates (to be configured by Certbot)
# ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;
# Recommended SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# Security headers
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 Referrer-Policy "strict-origin-when-cross-origin" always;
# Maximum upload size (important for workflows with files)
client_max_body_size 50M;
# Timeouts for long workflows
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
# WebSocket support (essential for the n8n editor)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Proxy headers
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;
proxy_set_header X-Forwarded-Host $host;
# Disable buffering for real-time events
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
}
}
⚠️ Important: Replace
n8n.yourdomain.comwith your actual domain.
Enable
sudo rm -f /etc/nginx/sites-enabled/default
Test Nginx configuration:
sudo nginx -t
Obtaining Let's Encrypt SSL Certificate
Install Certbot with Nginx plugin:
sudo apt install -y certbot python3-certbot-nginx
Obtain SSL certificate:
sudo certbot --nginx -d n8n.yourdomain.com
Follow the instructions:
- Enter your email address
- Agree to the terms of service
- Choose whether to share your email with EFF
- Certbot will automatically configure Nginx for HTTPS
Verification Point: Check automatic renewal:
sudo certbot renew --dry-run
Restart Nginx to apply all changes:
sudo systemctl restart nginx
Important Environment Variables
| Variable | Description | Default Value |
|---|---|---|
N8N_HOST | Instance domain name | localhost |
N8N_PORT | Internal listening port | 5678 |
N8N_PROTOCOL | Protocol (http/https) | http |
WEBHOOK_URL | Public URL for webhooks | - |
N8N_ENCRYPTION_KEY | Credentials encryption key | - |
N8N_PROXY_HOPS | Number of proxies in front of n8n | 0 |
GENERIC_TIMEZONE | Timezone | UTC |
DB_TYPE | Database type (postgresdb/sqlite) | sqlite |
N8N_METRICS | Enable Prometheus metrics | false |
N8N_LOG_LEVEL | Log level (info/debug/warn/error) | info |
First Use
Accessing the Interface
Open your browser and go to:
https://n8n.yourdomain.com
Initial Configuration
On first access, n8n will ask you to create an owner account:
- Email: Enter your professional email address
- First and Last Name: Your identity information
- Password: Choose a strong password (min. 8 characters, uppercase, numbers, special characters)
Creating the Admin Account
After filling out the form:
- Click on "Create account"
- A popup will appear to activate the community license (free)
- Click on "Activate" to access all self-hosted features
💡 Tip: The community license is free and provides access to all automation features without restrictions.
First Workflow
To test your installation:
- Click on "Create Workflow" in the side menu
- Click on the "+" to add a node
- Search for "Schedule Trigger" and add it
- Add a "Set" node to define data
- Connect the two nodes
- Click on "Execute Workflow" to test
Maintenance
Updating n8n
To update n8n to the latest version:
cd /opt/docker-compose/n8n
# Stop containers
docker compose down
# Download the new image
docker compose pull
# Restart
docker compose up -d
# Check
docker compose ps
⚠️ Before any major update (e.g., 1.x to 2.x), check the release notes and perform a full backup.
Backup
Full Backup (recommended)
Create a backup script /opt/docker-compose/n8n/backup.sh:
#!/bin/bash
# ===========================================
# n8n Backup Script - OuiHeberg
# ===========================================
BACKUP_DIR="/opt/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
N8N_DIR="/opt/docker-compose/n8n"
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup PostgreSQL database
docker exec n8n-postgres pg_dump -U n8n n8n > $BACKUP_DIR/n8n_db_$DATE.sql
# Backup n8n files
tar -czf $BACKUP_DIR/n8n_data_$DATE.tar.gz -C $N8N_DIR n8n_data
# Backup configuration files
tar -czf $BACKUP_DIR/n8n_config_$DATE.tar.gz -C $N8N_DIR .env docker-compose.yml
# Clean up backups older than 30 days
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE"
Make the script executable and schedule it:
sudo chmod +x /opt/docker-compose/n8n/backup.sh
# Add to cron (daily backup at 3 AM)
echo "0 3 * * * /opt/docker-compose/n8n/backup.sh >> /var/log/n8n-backup.log 2>&1" | sudo tee -a /etc/crontab
Restoration
To restore from a backup:
cd /opt/docker-compose/n8n
# Stop containers
docker compose down
# Restore database
cat /opt/backups/n8n/n8n_db_YYYYMMDD_HHMMSS.sql | docker exec -i n8n-postgres psql -U n8n n8n
# Restore n8n files
tar -xzf /opt/backups/n8n/n8n_data_YYYYMMDD_HHMMSS.tar.gz -C /opt/docker-compose/n8n/
# Restart
docker compose up -d
Logs and Monitoring
Viewing Logs
# Real-time n8n logs
docker compose logs -f n8n
# PostgreSQL logs
docker compose logs -f postgres
# Last 100 lines of n8n logs
docker compose logs --tail=100 n8n
Checking Service Status
# Container status
docker compose ps
# Resource usage
docker stats n8n n8n-postgres
# Used disk space
docker system df
Health Endpoint
n8n exposes a health endpoint locally:
curl http://localhost:5678/healthz
Troubleshooting
Common Issues and Solutions
1. "Connection lost" in the editor
Cause: WebSocket issue with the reverse proxy.
Solution:
# Check Nginx configuration
sudo nginx -t
# Ensure these lines are present in the Nginx config:
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection $connection_upgrade;
2. Webhooks not working
Cause: Incorrect webhook URL or undefined WEBHOOK_URL variable.
Solution:
- Check the
.envfile:grep WEBHOOK_URL /opt/docker-compose/n8n/.env - The URL should be
https://n8n.yourdomain.com/ - Restart n8n after modification:
docker compose restart n8n
3. "EACCES: permission denied"
Cause: Incorrect permissions on volumes.
Solution:
sudo chown -R 1000:1000 /opt/docker-compose/n8n/n8n_data
sudo chown -R 999:999 /opt/docker-compose/n8n/postgres_data
sudo chmod -R 755 /opt/docker-compose/n8n/n8n_data
4. "Connection to database failed"
Cause: PostgreSQL not ready or incorrect credentials.
Solution:
- Check PostgreSQL status:
docker compose logs postgres - Verify variables in
.env - Test connection:
docker exec -it n8n-postgres psql -U n8n -d n8n -c "SELECT 1;"
5. Interface is slow or unresponsive
Cause: Insufficient resources.
Solution:
# Check resource usage
docker stats
# If RAM is saturated, increase it or add limits:
# In docker-compose.yml, under the n8n service:
# deploy:
# resources:
# limits:
# memory: 2G
Diagnostic Commands
# Full Docker system status
docker system info
# Inspect n8n container
docker inspect n8n
# Check Docker networks
docker network ls
docker network inspect n8n_n8n-network
# Internal connectivity test
docker exec n8n ping -c 3 postgres
# Check used ports
sudo netstat -tlnp | grep -E "80|443|5678"
Where to Find Help
- Official Documentation: https://docs.n8n.io
- Community Forum: https://community.n8n.io
- GitHub Issues: https://github.com/n8n-io/n8n/issues
- Discord: n8n Community Server
Resources
Official Links
| Resource | URL |
|---|---|
| Official Website | https://n8n.io |
| Documentation | https://docs.n8n.io |
| GitHub | https://github.com/n8n-io/n8n |
| Docker Hub | https://hub.docker.com/r/n8nio/n8n |
| Forum | https://community.n8n.io |
| Release Notes | https://docs.n8n.io/release-notes/ |
| Official Blog | https://blog.n8n.io |
Workflow Templates
n8n offers a library of ready-to-use workflows:
Popular Integrations
- Google Workspace (Gmail, Sheets, Drive, Calendar)
- Slack, Discord, Microsoft Teams
- GitHub, GitLab, Bitbucket
- Notion, Airtable, Coda
- Stripe, PayPal
- OpenAI, Anthropic, Ollama
Appendix: Advanced Configuration
Enabling Prometheus Metrics
Add to the .env file:
N8N_METRICS=true
N8N_METRICS_PREFIX=n8n_
The metrics will be available at http://localhost:5678/metrics.
SMTP Configuration for Notifications
Add to the .env file:
N8N_EMAIL_MODE=smtp
N8N_SMTP_HOST=smtp.yourdomain.com
N8N_SMTP_PORT=587
[email protected]
N8N_SMTP_PASS=YourSMTPPassword
[email protected]
N8N_SMTP_SSL=false
Queue Mode with Redis (High Availability)
For high-load deployments, n8n supports a "queue" mode with Redis:
# Add this service in docker-compose.yml
redis:
image: redis:7-alpine
container_name: n8n-redis
restart: unless-stopped
networks:
- n8n-network
And these variables in .env:
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
Guide written by OuiHeberg - December 2025 Last updated: 12/12/2025

