How to Install n8n: Self-Hosted Setup with Docker Compose on Ubuntu

Sunucun 5 min read

n8n is a workflow automation tool that connects apps and services, and you can host it on your own server. This guide shows how to install n8n on a Linux server (for example an Ubuntu VDS) with Docker Compose, serve it over HTTPS on your own domain, update it and back it up. The commands and files follow the “Docker Compose” installation in n8n’s official documentation.

Illustration: Ubuntu

Note: n8n’s own documentation recommends self-hosting for users experienced with servers, containers and security; mistakes can lead to data loss, security issues and downtime.

Requirements

  • A Linux server (Ubuntu in this guide) with root/sudo access and a static public IP
  • A domain name and access to its DNS records (for example n8n.example.com)
  • TCP ports 80 and 443 open on the server (for the SSL certificate and web access)

1. Install Docker and Docker Compose

Install Docker Engine and the Compose plugin with the steps on Docker’s official Ubuntu install page, then check both:

docker --version
docker compose version

Optional: to run Docker without sudo, add your user to the docker group:

sudo usermod -aG docker ${USER}
exec sg docker newgrp
groups

2. Point a Subdomain to the Server (DNS)

Record typeNameDestination
An8n (or your subdomain)Your server’s IP address

Wait for the record to propagate; the SSL certificate can only be issued once the domain points to your server.

3. Project Folder and .env File

mkdir n8n-compose
cd n8n-compose

Create a file named .env in the folder with your own values:

# n8n will be served at https://n8n.example.com
DOMAIN_NAME=example.com
SUBDOMAIN=n8n

# Timezone used by Cron and other scheduling nodes
GENERIC_TIMEZONE=Europe/Istanbul

# Email address for the TLS/SSL certificate
SSL_EMAIL=you@example.com

If you leave the timezone out, n8n uses New York time by default.

4. Shared Files Folder

Create a local-files folder for sharing files between n8n and the host (for example with the Read/Write Files from Disk node). Creating it manually makes sure it gets the right ownership and permissions:

mkdir local-files

5. The compose.yaml File

Create compose.yaml in the same folder. It defines two containers: n8n itself and Traefik, a reverse proxy that obtains the SSL certificate and routes traffic to n8n:

services:
  traefik:
    image: "traefik"
    restart: always
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
      - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - traefik_data:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro

  n8n:
    image: n8nio/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=web,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
      - traefik.http.routers.n8n.middlewares=n8n@docker
    environment:
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - N8N_WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - TZ=${GENERIC_TIMEZONE}
      - N8N_RESTRICT_FILE_ACCESS_TO=/files
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files

volumes:
  n8n_data:
  traefik_data:
  • 127.0.0.1:5678: n8n’s port is reachable only from inside the server; outside traffic arrives through Traefik over HTTPS.
  • N8N_WEBHOOK_URL: makes webhook URLs use https and your domain. It exists from n8n 2.30.0; earlier versions use WEBHOOK_URL.
  • n8n_data: holds the SQLite database and the encryption key that protects your credentials. Deleting this volume loses your data.

6. Open the Firewall

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Keep your SSH port open, and open these ports in your provider’s network firewall too if it has one. Port 5678 does not need to be public.

7. Start n8n

sudo docker compose up -d

Open https://n8n.example.com and create the owner account on first launch. The instance is reachable over HTTPS only. To stop it, run sudo docker compose stop.

How to Update n8n

docker compose pull
docker compose down
docker compose up -d

n8n releases a new minor version most weeks. Use the stable version in production; beta is the newest release and may be unstable. Back up before updating.

Backups and Database

  • Volume backup: n8n_data contains both the database and the encryption key; you need both to move or restore an instance.
  • Export workflows: you can download workflows as JSON from the n8n editor.
  • PostgreSQL: the default database is SQLite. Compose examples with PostgreSQL are in n8n’s official n8n-hosting repository. Keep mounting /home/node/.n8n even with PostgreSQL, because the encryption key lives there.

Troubleshooting

  • Can’t connect: check that the A record points to the server IP and that ports 80/443 are open.
  • Certificate error: if you started before DNS propagated, check docker compose logs traefik.
  • Webhook URLs show localhost: check the domain in .env and the N8N_WEBHOOK_URL line.
  • n8n logs: docker compose logs -f n8n

Prefer not to do this yourself? Sunucun’s n8n server plans are delivered with n8n installed and ready to use, with full server access. To follow the steps above yourself, you can use a VDS server with root access.

Frequently Asked Questions

Is self-hosting n8n free?

n8n is distributed under the Sustainable Use License (fair-code); self-hosting it for your own internal business processes is free. You pay for the server and domain.

Can I use the n8n tunnel on a server?

No. According to n8n, the tunnel is for local development and testing only and is not safe for production. Use a domain with HTTPS as above.

Categories

Latest guides