// DevOps

Installing n8n on FastPanel with Docker Compose: A Clear Guide

Published on 2025-07-03

In this guide, I’ll show you how to easily install n8n, a powerful workflow automation tool, on your server with FastPanel using Docker Compose. FastPanel is great for managing web servers, and Docker Compose simplifies the deployment of complex applications like n8n with its dependencies (PostgreSQL and Redis).

What You’ll Need

  • Your server with FastPanel installed.
  • A domain or subdomain you’ll use to access n8n (e.g., n8n.yourdomain.com).
  • Basic knowledge of SSH and command line.

Step 1: Prepare the Server

Connect to your server via SSH and create a directory:

bash
sudo mkdir -p /opt/n8n_stack
cd /opt/n8n_stack

Step 2: Create Configuration Files

You’ll need the following files:

  • docker-compose.yml
  • .env
  • init-data.sh
  • healthcheck.js

2.1. docker-compose.yml

bash
nano docker-compose.yml
yaml
version: '3.8'

x-shared: &shared
  restart: always
  image: docker.n8n.io/n8nio/n8n:1.91.3
  env_file: .env
  user: "1000:1000"
  volumes:
    - /opt/n8n_stack/n8n_storage:/home/node/.n8n
    - ./healthcheck.js:/healthcheck.js
  depends_on:
    redis:
      condition: service_healthy
    postgres:
      condition: service_healthy

services:
  postgres:
    image: postgres:11
    restart: always
    env_file: .env
    volumes:
      - /opt/n8n_stack/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

  redis:
    image: redis:6-alpine
    restart: always
    volumes:
      - /opt/n8n_stack/redis_storage:/data
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    <<: *shared
    ports:
      - "127.0.0.1:5678:5678"
    healthcheck:
      test: ["CMD", "node", "/healthcheck.js"]
      interval: 5s
      timeout: 5s
      retries: 10

  n8n-worker:
    <<: *shared
    command: worker
    depends_on:
      - n8n
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O - http://localhost:5678/healthz || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 10

2.2. .env

bash
nano .env
env
# n8n
N8N_HOST=your_n8n_domain.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://your_n8n_domain.com/
N8N_ENCRYPTION_KEY=your_secure_password_for_n8n
GENERIC_TIMEZONE=Europe/Moscow
TZ=Europe/Moscow
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=your_db_name
DB_POSTGRESDB_USER=your_non_root_db_user
DB_POSTGRESDB_PASSWORD=your_non_root_db_password

# PostgreSQL (root)
POSTGRES_DB=your_db_name
POSTGRES_USER=your_db_user
POSTGRES_PASSWORD=your_db_password

# PostgreSQL (non-root for n8n)
POSTGRES_NON_ROOT_USER=your_non_root_db_user
POSTGRES_NON_ROOT_PASSWORD=your_non_root_db_password

2.3. init-data.sh

bash
nano init-data.sh
bash
#!/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 EXTENSION IF NOT EXISTS "pgcrypto";
        CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
        DO
        \$do\$
        BEGIN
           IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${POSTGRES_NON_ROOT_USER}') THEN
              CREATE USER "${POSTGRES_NON_ROOT_USER}" WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
           ELSE
              ALTER USER "${POSTGRES_NON_ROOT_USER}" WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
           END IF;
        END
        \$do\$;
        GRANT ALL PRIVILEGES ON DATABASE "${POSTGRES_DB}" TO "${POSTGRES_NON_ROOT_USER}";
EOSQL
else
    echo "SETUP INFO: Environment variables POSTGRES_NON_ROOT_USER or POSTGRES_NON_ROOT_PASSWORD are not set."
fi
bash
chmod +x init-data.sh

2.4. healthcheck.js

bash
nano healthcheck.js
javascript
var http = require('http');

var options = {
  host: '127.0.0.1',
  port: 5678,
  path: '/healthz',
  method: 'GET',
};

var req = http.request(options, function(res) {
  console.log('STATUS: ' + res.statusCode);
  process.exit(res.statusCode === 200 ? 0 : 1);
});

req.on('error', function(e) {
  console.log('ERROR: ' + e.message);
  process.exit(1);
});

req.end();

Step 3: Launch n8n with Docker Compose

bash
docker compose up -d

Check the status:

bash
docker compose ps

All services should be in running or healthy status.


Step 4: Configure FastPanel

  1. Go to FastPanel → SitesAdd site.

  2. Use the domain specified in .env (n8n.yourdomain.com).

  3. After creation:

    • Go to site settings.
    • Enable Reverse Proxy.
    • Enter the address: 127.0.0.1:5678.
    • Make sure SSL is issued (usually Let’s Encrypt does it automatically).

WebSocket Support (if needed manually):

nginx
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Step 5: Access n8n

Open in your browser:

https://n8n.yourdomain.com

You’ll see the n8n welcome page. Everything is ready — start building automations!


If you have questions or run into issues — feel free to ask in the comments.

// Reviews

Related reviews

// Contact

Need help?

Get in touch with me and I'll help solve the problem

Message on Telegram

Отвечаю в течение рабочего дня (03:00–13:00 GMT)

Или оставьте заявку здесь:

Send request
Write and get a quick reply