Learn, how you can setup a self-hosted version of N8N using Docker.
N8N Self-Hosted: Made Easy
You want to run your own version of N8N?
You want to keep your data safe and be able to control everything?
You want to have the freedom to customize and extend N8N as you see fit?
Then self-hosting N8N is the way to go!
What you need
- A Server with a public dedicated ip address (a virtual machine is enough) and ssh access
- Your own domain name
- A DNS entry for your domain pointing to your server’s ip address
Step 1: Setup a SSH Key
Before you order your server, make sure you have created a local SSH key pair. This is required for the next step. SSH is a secure way to access your server remotely. You can send commands and talk directly to your server.
Generate a keypair (command for macOS, Linux and the Windows Subsystem for Linux):
ssh-keygen
This command will create two files in your home directory:
~/.ssh/id_rsa:~/.ssh/id_rsa.pub: The .pub file contains the public key, this will be placed on your server. The .rsa file contains the private key, this is the one you need to access your server. Never share this file with anyone!
Step 2: Order your Server
There are many providers out there, such as DigitalOcean, AWS, Google Cloud, or Linode. Choose the one that best fits your needs and budget.
We highly recommend using Hetzner Cloud for this tutorial and also in general. They offer a great deal of resources for a low price, also hosted in Germany.
- Go to hetzner.cloud and sign up for a free account.
- Create a new cloud project
- Go to Keys and add your SSH public key, the content of
~/.ssh/id_rsa.pub. - Create a new server with the following settings:
- Server type: CPX32
- Location: Falkenstein
- OS: Ubuntu Server 24.04 LTS
- Public IPv4 and IPv6: Enabled
- Choose the previous created SSH key
- Enable backups
- Set a name for your server
- Click on “Order Now”
Great job! You now have a server ready to be used.
Step 3: Get a Domain Name
For N8N to be accessible from the outside with a secure connection (https instead of http) you need a domain name. There are several providers out there, such as GoDaddy, Namecheap, etc..
We can also recommend Hetzner for domain registration. They offer competitive prices and a user-friendly interface.
If you do not want to pay extra for a domain name, you can also use a free .tk domain. You can find several providers for this.
After you have purchased your domain name, create a DNS entry for it pointing to your server’s ip address.
DNS is the Domain Name System. This works similar to a phone book and tell your laptop or smartphone where to find a specific website linked to a domain. For this to work we need to create a DNS A record for our domain pointing to the server’s public ip address.
A A-Record is a DNS entry that maps a domain name to an IP address. There are also other kinds of records like MX-Records for Mailing but we don’t need them for now.
Your task is now to create that record, in the host you can enter whatever you want, for example n8n, this will make
your instance available at n8n.yourdomain.com. You could also use a @ as the hostnmae, this will make your instance
available at yourdomain.com.
Use the public IPv4 address of your server as the target, you can find this in the Hetzner Cloud web interface.
Optional: If you want to use Qdrant later, you can also setup a second DNS entry for it pointing to the same ip address.
Use something like qdrant for the host, this will make your instance available at qdrant.yourdomain.com.
Great job, you are doing great so far!
Step 4: Install Docker
Docker is a tool that allows you to run applications in isolated containers. This makes it easy to deploy and update applications without affecting other applications.
Let’s start by connecting to your server via ssh.
Open a terminal and run the following command:
ssh root@yourserverip
After that you should see that you are connected to your server. When you enter commands now you can directly talk to your server.
Just copy and paste the following commands into the terminal:
-
apt updateThis will update the package list, like app store sources -
apt install ca-certificates curlThis will install some default certificates and curl, a tool to download files -
install -m 0755 -d /etc/apt/keyringsThis will create a directory for the docker keyrings, they are used to verify the authenticity of the docker packages -
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.ascThis will download the docker keyring and save it to the directory we just created -
chmod a+r /etc/apt/keyrings/docker.ascThis will make sure the keyring is readable by all users -
tee /etc/apt/sources.list.d/docker.sources <<EOF Types: deb URIs: https://download.docker.com/linux/ubuntu Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") Components: stable Signed-By: /etc/apt/keyrings/docker.asc EOFThis will add the docker repository to the apt sources, this means that after that we are download Docker from something like a ‘App Store’ -
apt updateThis will update the package list again -
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginThis will finall install Docker and Docker Compose
Great! You now have Docker installed on your server
Step 5: Deploy Traefik
Traefik is a reverse proxy and load balancer that makes it easy to configure and deploy N8N. This is needed when you have multiple services running on your server and is also important because it manages your SSL certificates for you.
SSL certificates are used to encrypt the communication between your browser and your server. Without them your browser will tell you that the connection is insecure because all traffic is unencrypted and can be read by anyone on your Wi-Fi.
First make sure that you are still connected to your server via ssh in the terminal, otherwise execute the command from above again to connect.
Let’s create a directory for Traefik to store its data and its configurations:
mkdir -p /opt/docker/traefik
Let’s move our terminal to that folder:
cd /opt/docker/traefik
Now open a new file in a text editor:
nano docker-compose.yml
And paste this content:
services:
traefik:
restart: always
image: "traefik:v3.1"
container_name: "traefik"
command:
- "--configFile=/etc/traefik/traefik.yml"
ports:
- "443:443"
- "8080:8080"
- "80:80"
volumes:
- "./traefik.yaml:/etc/traefik/traefik.yml"
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- web
networks:
web:
external: true
Close the file using CTRL+X and save it with Y.
Now create a second file in the same folder:
nano traefik.yaml
Paste this content and close the file again after you are done:
log:
level: DEBUG
api:
insecure: true
dashboard: false
entryPoints:
web-https:
address: ":443"
web-http:
address: ":80"
providers:
docker:
exposedByDefault: false
network: web
certificatesResolvers:
my-resolver:
acme:
tlsChallenge: true
email: "admin@PUT_YOUR_DOMAIN_HERE"
storage: "/letsencrypt/acme.json"
Remember to replace PUT_YOUR_DOMAIN_HERE with your actual domain name, like example.com.
Last but not least we need to create a network for our services: docker network create web
Now we are ready to start Traefik:
docker-compose up -d
Cool! You now have Traefik running on your server.
Step 6: Deploy N8N
Now we are ready to deploy N8N. Make sure you are still connected to your server via ssh in the terminal,
Create a new directory for N8N:
mkdir -p /opt/docker/n8n
Move your terminal to that directory:
cd /opt/docker/n8n
Create a new file called docker-compose.yml and paste this content using this command the command
nano docker-compose.yml:
services:
n8n:
image: n8nio/n8n
container_name: n8n
restart: always
expose:
- "5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=n8n-db
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=YOUR_SECURE_PASSWORD_HERE_1
- N8N_HOST=n8n.yourdomain.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://n8n.yourdomain.com
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- n8n-db
networks:
- n8n-network
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.yourdomain.com`)"
- "traefik.http.routers.n8n.entrypoints=web-https"
- "traefik.http.routers.n8n.tls=true"
- "traefik.http.routers.n8n.tls.certresolver=my-resolver"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
n8n-db:
image: postgres:13
container_name: n8n-db
restart: always
environment:
- POSTGRES_DB=n8n
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=YOUR_SECURE_PASSWORD_HERE_1
volumes:
- n8n_db:/var/lib/postgresql/data
networks:
- n8n-network
qdrant:
image: qdrant/qdrant
container_name: qdrant
restart: always
expose:
- "6333"
- "6334"
volumes:
- qdrant_data:/qdrant/storage
networks:
- n8n-network
- web
environment:
- QDRANT__SERVICE__GRPC_PORT=6334
- QDRANT__SERVICE__API_KEY=YOUR_SECURE_PASSWORD_HERE_2
labels:
- "traefik.enable=true"
- "traefik.http.routers.qdrant.rule=Host(`qdrant.yourdomain.com`)"
- "traefik.http.routers.qdrant.entrypoints=web-https"
- "traefik.http.routers.qdrant.tls=true"
- "traefik.http.routers.qdrant.tls.certresolver=my-resolver"
- "traefik.http.services.qdrant.loadbalancer.server.port=6333"
networks:
n8n-network:
driver: bridge
web:
external: true
volumes:
n8n_data:
n8n_db:
qdrant_data:
Remeber to replace YOUR_SECURE_PASSWORD_HERE_1 and YOUR_SECURE_PASSWORD_HERE_2 with different random passwords.
Also make sure to replace yourdomain with your actual domain name.
When you are done close the file again using CTRL+X and save it with Y.
Now we are ready to start N8N:
docker-compose up -d
Congratulations! You now have a fully functional self-hosted version of N8N running on your server.
You can access it at https://n8n.yourdomain.com and https://qdrant.yourdomain.com in your browser.
Update N8N or Traefik
You can update N8N and Qdrant by running the following commands in their respective directories:
cd /opt/docker/n8n or cd /opt/docker/traefik
docker-compose pull
docker-compose up -d --force-recreate
Remember to create a backup first of your data before updating! Hetzner does this automatically for you every day and keeps the last 7 days of backups.
Have fun!