Dedicated Servers & VPSDecember 12, 2025 114 views

n8n Installation Guide on Linux Server

n8n Installation Guide on Linux Server

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) and postgres (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.com with your actual domain
  • YourEncryptionKeyMin32Characters! 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.com with 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:

  1. Enter your email address
  2. Agree to the terms of service
  3. Choose whether to share your email with EFF
  4. 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:

  1. Email: Enter your professional email address
  2. First and Last Name: Your identity information
  3. Password: Choose a strong password (min. 8 characters, uppercase, numbers, special characters)

Creating the Admin Account

After filling out the form:

  1. Click on "Create account"
  2. A popup will appear to activate the community license (free)
  3. 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:

  1. Click on "Create Workflow" in the side menu
  2. Click on the "+" to add a node
  3. Search for "Schedule Trigger" and add it
  4. Add a "Set" node to define data
  5. Connect the two nodes
  6. 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:

  1. Check the .env file:
    grep WEBHOOK_URL /opt/docker-compose/n8n/.env
    
  2. The URL should be https://n8n.yourdomain.com/
  3. 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:

  1. Check PostgreSQL status:
    docker compose logs postgres
    
  2. Verify variables in .env
  3. 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


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