Setup n8n Linux Service

I installed n8n from npm but the moment SSH tunnel close n9n stops is there a way I can run it as systemd service so that it starts when VM reboot

Hey @MXA_Music,

We officially encourage to use Docker to deploy n8n. You can find the guide for the setup here: Server Setup | Docs

If you want an alternate option you can use PM2. Here’s an article on that: How to set up n8n via PM2 ⚙️

My issue with Docker n8n was not able to reach other services running on same machine which is accessible using localhost my guess n8n was access localhost inside the docker not in the host so that’s why it tried npm package. I will check PM2

Thanks a lot :blush:

A user in the Discord server has also created a systemd install for n8n on the RPi. It should work for your system as well. It is available as a Github gist.

@harshil1712

I tried to setup a Docker server using n8n and Postgres instead of SQLite but failed.

Do you have any docker-compose file that is working?
mine is here:

version: “3.7”

services:

traefik:

image: traefik:latest

container_name: traefik

restart: always

command:

  - "--api=true"

  - "--api.insecure=true"

  - "--providers.docker=true"

  - "--providers.docker.exposedbydefault=false"

  - "--entrypoints.websecure.address=:443"

  - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"

  - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"

  - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"

ports:

  - "443:443"

volumes:

  - ${DATA_FOLDER}/letsencrypt:/letsencrypt

  - /var/run/docker.sock:/var/run/docker.sock:ro

n8n:

image: n8nio/n8n:latest

container_name: n8n

restart: always

ports:

  - "127.0.0.1:5678:5678"

labels:

  - traefik.enable=true

  - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)

  - traefik.http.routers.n8n.tls=true

  - traefik.http.routers.n8n.entrypoints=websecure

  - traefik.http.routers.n8n.tls.certresolver=mytlschallenge

  - traefik.http.middlewares.n8n.headers.SSLRedirect=true

  - traefik.http.middlewares.n8n.headers.STSSeconds=315360000

  - traefik.http.middlewares.n8n.headers.browserXSSFilter=true

  - traefik.http.middlewares.n8n.headers.contentTypeNosniff=true

  - traefik.http.middlewares.n8n.headers.forceSTSHeader=true

  - traefik.http.middlewares.n8n.headers.SSLHost=${SUBDOMAIN}.${DOMAIN_NAME}

  - traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true

  - traefik.http.middlewares.n8n.headers.STSPreload=true

environment:

  - DB_TYPE=postgresdb

  - DB_POSTGRESDB_HOST=postgres

  - DB_POSTGRESDB_PORT=5432

  - DB_POSTGRESDB_DATABASE=${POSTGRES_DB}

  - DB_POSTGRESDB_SCHEMA=${POSTGRES_SCHEMA}

  - DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}

  - DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}

  - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}

  - N8N_PORT=5678

  - N8N_PROTOCOL=https

  - NODE_ENV=production

  - WEBHOOK_TUNNEL_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/

  - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}

volumes:

  - /var/run/docker.sock:/var/run/docker.sock

  - ${DATA_FOLDER}:/home/node/.n8n

  - /home/ubuntu/n8n-local-files:/files

depends_on:

  - postgres

links:

  - postgres

command: /bin/sh -c "sleep 5; n8n start"

postgres:

image: postgres:latest

container_name: postgres

restart: always

labels:

  - traefik.enable=false

environment:

  - POSTGRES_USER

  - POSTGRES_PASSWORD

  - POSTGRES_DB

  - POSTGRES_NON_ROOT_USER

  - POSTGRES_NON_ROOT_PASSWORD

expose:

  - 5432

volumes:

  - ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh

Hey @intelioum!

I used the docker-compose file from here: n8n/docker/compose/withPostgres at master · n8n-io/n8n · GitHub and added the Traefik configurations to it. My docker-compose has the following content

version: '3.1'
services:

  postgres:
    image: postgres
    restart: always
    environment:
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB
      - POSTGRES_NON_ROOT_USER
      - POSTGRES_NON_ROOT_PASSWORD
    volumes:
      - ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh

  traefik:
    image: "traefik"
    restart: always
    command:
      - "--api=true"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
      - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
    volumes:
      - ~/.n8n/letsencrypt:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro
  n8n:
    image: n8nio/n8n
    restart: always
    labels:
      - traefik.enable=true
      - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
      - traefik.http.routers.n8n.tls=true
      - traefik.http.routers.n8n.entrypoints=websecure
      - traefik.http.routers.n8n.tls.certresolver=mytlschallenge
      - traefik.http.middlewares.n8n.headers.SSLRedirect=true
      - traefik.http.middlewares.n8n.headers.STSSeconds=315360000
      - traefik.http.middlewares.n8n.headers.browserXSSFilter=true
      - traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
      - traefik.http.middlewares.n8n.headers.forceSTSHeader=true
      - traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
      - traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
      - traefik.http.middlewares.n8n.headers.STSPreload=true
    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_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER
      - N8N_BASIC_AUTH_PASSWORD
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_TUNNEL_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
    ports:
      - 5678:5678
    links:
      - postgres
    volumes:
      - ~/.n8n:/home/node/.n8n
    # Wait 5 seconds to start n8n to make sure that PostgreSQL is ready
    # when n8n tries to connect to it
    command: /bin/sh -c "sleep 5; n8n start"

My .env file looks like this

POSTGRES_USER=USER
POSTGRES_PASSWORD=PASSWORD

POSTGRES_NON_ROOT_USER=USER
POSTGRES_NON_ROOT_PASSWORD=PASSWORD

N8N_BASIC_AUTH_USER=changeUser
N8N_BASIC_AUTH_PASSWORD=changePassword
SUBDOMAIN=n8n
DOMAIN_NAME=example.com
[email protected]

And lastly, the init-data.sh file has the following code

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};
EOSQL
else
echo "SETUP INFO: No Environment variables given!"
fi