Self-hosting n8n means running the open-source Community Edition in a Docker container on your own Linux server: no execution limits, no per-workflow fee, and you maintain it. A working setup is four pieces. A Docker Compose file defining the n8n container. A named volume so workflows and credentials survive restarts. An N8N_ENCRYPTION_KEY that must never change. Nginx in front terminating HTTPS. Budget 25 to 40 minutes on a fresh Ubuntu server. n8n also publishes a one-line installer if you would rather not write the files yourself.
Updated September 2026: re-verified against n8n's current self-hosting docs. The important correction: N8N_BASIC_AUTH_ACTIVE and its companions no longer exist, because n8n 1.0 replaced basic auth with built-in user management. The old Compose file in this guide would have started an instance with no login at all. The file also drops the obsolete version: key, pins an image tag instead of tracking :latest, and binds the port to localhost.
No Docker experience required, just basic comfort with a command line.
What we cover: Docker install, the Compose file, environment variables, volumes, HTTPS via Nginx, backups, updates.
Why Self-Host N8N?
n8n Cloud charges by execution and caps you monthly. Self-hosted, you run as many executions as the server can handle, with no per-execution fee.
Three situations where self-hosting wins:
- Data compliance: workflows handling personal, financial or HR data keep their execution logs on your infrastructure.
- High volume: 10,000 executions a month is €50 on n8n Cloud Pro and a $10 VPS self-hosted.
- Custom nodes: community nodes and custom integrations install freely on a self-hosted instance.
New to n8n? Start with building your first n8n workflow.
What You Need Before You Start
You need three things:
- A Linux VPS (Ubuntu 24.04 LTS recommended). DigitalOcean, Hetzner, Vultr and Linode all work. n8n's own Docker Compose guide asks for at least 2 vCPUs and 4 GB of RAM, so treat that as the floor rather than an upgrade path.
- A domain name pointed to your server's IP. You need this for HTTPS. Use an A record:
n8n.yourdomain.com → your.server.ip. - SSH access to the server with a non-root sudo user.
Self-Hosted vs Cloud: Cost and Feature Comparison
An honest side-by-side:
| Factor | n8n Cloud (Starter) | Self-Hosted (Docker / VPS) |
|---|---|---|
| Monthly cost | €20 (2,500 executions/month) | $5 to $20 (unlimited executions) |
| Setup time | 2 minutes | 25 to 40 minutes |
| Maintenance burden | None (managed) | Low (monthly Docker updates) |
| Execution limits | Yes (varies by plan) | None (server-bound only) |
| Community nodes | Limited | Full access |
| Data residency control | No | Yes (your server, your region) |
| Custom SSL / domain | Subdomain only | Any domain |
| Backups | Managed by N8N | Your responsibility (easy to automate) |
Step 1: Install Docker and Docker Compose
SSH in and install Docker Engine plus the Compose plugin from Docker's official repository:
sudo apt update && sudo apt upgrade -y
# Install dependencies
sudo apt install -y ca-certificates curl gnupg
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine + Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add your user to the docker group (so you don't need sudo for every command)
sudo usermod -aG docker $USER
newgrp docker
Verify both are working:
docker --version
docker compose version
Step 2: Create the N8N Directory and Docker Compose File
Create a directory for the setup:
mkdir -p ~/n8n && cd ~/n8n
Create the Compose file, which defines how n8n runs:
nano docker-compose.yml
Paste in the following. We'll explain each key section below:
services:
n8n:
# Pin a version. Check https://github.com/n8n-io/n8n/releases
image: n8nio/n8n:${N8N_VERSION}
container_name: n8n
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=${N8N_HOST}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://${N8N_HOST}/
- GENERIC_TIMEZONE=Europe/Paris
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
Key settings to understand:
- restart: unless-stopped ensures N8N restarts automatically if the container crashes or the server reboots.
- n8n_data volume persists all workflows, credentials, and execution history between container restarts and upgrades.
- N8N_ENCRYPTION_KEY encrypts stored credentials. Generate a strong random key and never change it after setup.
- No basic-auth variables.
N8N_BASIC_AUTH_ACTIVE,N8N_BASIC_AUTH_USERandN8N_BASIC_AUTH_PASSWORDwere removed when n8n 1.0 replaced basic auth with built-in user management. They appear in a lot of older tutorials and they do nothing now. You create an owner account with an email and password the first time you open the UI, and that is your login. - Port bound to localhost.
127.0.0.1:5678:5678means only the reverse proxy on the same box can reach n8n. Publishing5678on all interfaces exposes the editor to the internet directly. - Pinned image tag. n8n recommends pinning a release rather than tracking
:latest, so an unattendeddocker compose pullcannot move you across a breaking change.
Step 3: Configure Environment Variables
Create a .env in the same directory, keeping secrets out of the Compose file:
nano .env
Fill in your values:
# Your n8n domain
N8N_HOST=n8n.yourdomain.com
# Pin the release you want. Latest stable:
# https://github.com/n8n-io/n8n/releases
N8N_VERSION=1.x.x
# Generate with: openssl rand -hex 32
N8N_ENCRYPTION_KEY=your-64-character-random-hex-key
Generate your encryption key with this one-liner:
openssl rand -hex 32
Copy the output into N8N_ENCRYPTION_KEY and store it somewhere safe. Lose it and every credential in the instance becomes unreadable.
There is no password in this file. n8n dropped basic auth in version 1.0: the first time you open the editor it asks you to create an owner account, and user management takes it from there. Until you have created that account and put HTTPS in front of the instance, keep the port bound to localhost as shown above.
Step 4: Set Up Nginx as a Reverse Proxy with HTTPS
Port 5678 over plain HTTP is not acceptable in production. Nginx terminates HTTPS and proxies to the container.
Install Nginx and Certbot:
sudo apt install -y nginx certbot python3-certbot-nginx
Create an Nginx configuration file for N8N:
sudo nano /etc/nginx/sites-available/n8n
Paste the following (replace n8n.yourdomain.com with your actual domain):
server {
listen 80;
server_name n8n.yourdomain.com;
location / {
proxy_pass http://localhost:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
chunked_transfer_encoding on;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Enable the site and obtain an SSL certificate:
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
# Issue the SSL certificate (follow prompts)
sudo certbot --nginx -d n8n.yourdomain.com
Certbot rewrites the Nginx config for HTTPS and sets up auto-renewal. n8n is now at https://n8n.yourdomain.com.
Step 5: Start N8N
With Nginx configured, start the N8N container:
cd ~/n8n
docker compose up -d
Check that the container is running:
docker compose ps
docker compose logs -f n8n
Open https://n8n.yourdomain.com. On a fresh instance n8n asks you to create the owner account (email and password); after that you land on the workflow editor.
Step 6: Configure Timezone and Email (Optional but Recommended)
Set the timezone so scheduled triggers fire correctly. In .env:
GENERIC_TIMEZONE=America/New_York
Use IANA tz database strings. This matters most for the Schedule trigger, covered in our n8n scheduled triggers tutorial.
If you want N8N to send email alerts on workflow errors, add SMTP settings to .env:
N8N_EMAIL_MODE=smtp
N8N_SMTP_HOST=smtp.yourmailprovider.com
N8N_SMTP_PORT=587
N8N_SMTP_USER=your@email.com
N8N_SMTP_PASS=your-smtp-password
N8N_SMTP_SENDER=n8n@yourdomain.com
Restart N8N to apply changes:
docker compose down && docker compose up -d
Step 7: Set Up Backups
Everything (workflows, credentials, execution history) lives in the n8n_data volume. Backing it up is a cron job.
Create a backup script:
nano ~/n8n/backup.sh
#!/bin/bash
DATE=$(date +%Y-%m-%d)
BACKUP_DIR=~/n8n-backups
mkdir -p $BACKUP_DIR
# Stop N8N (prevents partial writes)
docker compose -f ~/n8n/docker-compose.yml stop n8n
# Archive the volume data
docker run --rm \
-v n8n_n8n_data:/data \
-v $BACKUP_DIR:/backup \
alpine tar czf /backup/n8n-backup-$DATE.tar.gz -C /data .
# Restart N8N
docker compose -f ~/n8n/docker-compose.yml start n8n
# Remove backups older than 30 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
echo "Backup complete: n8n-backup-$DATE.tar.gz"
chmod +x ~/n8n/backup.sh
Schedule it daily at 2 AM with cron:
crontab -e
# Add this line:
0 2 * * * /home/youruser/n8n/backup.sh >> /home/youruser/n8n/backup.log 2>&1
Copy backups off-server to S3 or similar. A backup on the same box as the application is not a disaster-recovery backup.
Step 8: Update N8N
Updating is two commands:
cd ~/n8n
docker compose pull
docker compose up -d
Docker pulls the tag named in your .env and recreates the container. Workflows and credentials survive because they live in the named volume, not in the container. Expect a few seconds of downtime; a single-container setup has no rolling update.
Because the tag is pinned, updating means editing N8N_VERSION in .env and then pulling. Back up first and read the release notes before crossing a major version.
Common Self-Hosting Issues and Fixes
Webhooks not receiving requests
Check that WEBHOOK_URL in your .env matches your public domain exactly, including the trailing slash. Also verify your server firewall allows inbound traffic on ports 80 and 443.
Credentials not saving after restart
This almost always means the n8n_data volume is not mounted correctly, or the N8N_ENCRYPTION_KEY changed between restarts. The key must remain identical for the container lifetime.
N8N UI slow or unresponsive
The container needs more RAM. Upgrade to a 4 GB RAM server if you see memory pressure. You can also limit execution history retention in N8N settings to reduce database size. For advanced error handling patterns in workflows themselves, see our N8N error handling guide.
SSL certificate not renewing
Certbot sets up a systemd timer for auto-renewal. Check its status with sudo systemctl status certbot.timer. Test renewal manually with sudo certbot renew --dry-run.
Connecting Your Self-Hosted N8N to Business Systems
Node setup is identical to n8n Cloud. Common starting points:
- Connect to Google Sheets for data logging (see our N8N + Google Sheets guide)
- Pull data via HTTP requests to connect any API without a dedicated node
- Trigger workflows from webhooks when form submissions, payments, or CRM events fire
Le Marquier, a premium outdoor kitchen brand, runs its customer inquiry routing and follow-up on a self-hosted n8n instance. The full case study has the numbers.
Our ROI calculator puts a number on the financial case in two minutes.
When to Use N8N Cloud Instead
Self-hosting is not always the right choice. Use N8N Cloud if:
- You are evaluating N8N for the first time and do not want infrastructure overhead
- Your team has no one comfortable managing a Linux server
- You run fewer than 2,500 executions per month, where the €20 Starter plan is competitive with a VPS once you price in your own time
Not sure where to start? The AI readiness assessment points at the highest-impact process.
Want n8n without the infrastructure? Our n8n automation service covers setup, workflow development and support.
Frequently Asked Questions
How much does it cost to self-host N8N?
Self-hosting n8n on a VPS costs between $5 and $20 per month depending on the provider. A 2 vCPU, 4 GB RAM server from DigitalOcean, Hetzner or Linode meets n8n's documented minimum. Compare that to n8n Cloud, which starts at €20 per month for 2,500 executions and €50 for 10,000.
What is the minimum server spec for N8N?
n8n's own Docker Compose guide asks for at least 2 vCPUs and 4 GB of RAM. Smaller boxes will boot n8n, but n8n does not publish a supported figure below that, so treat 2 vCPU / 4 GB as the floor for anything you depend on. Storage tracks execution-history retention; 20 GB SSD is a safe start.
Is self-hosted N8N secure?
Self-hosted n8n is secure when configured correctly. Use HTTPS with a valid certificate, create the owner account through n8n's built-in user management (basic auth was removed in n8n 1.0 and is no longer an option), restrict the firewall to ports 22, 80 and 443, and bind the n8n port to localhost so only the reverse proxy reaches it. Update the pinned image regularly.
Can I migrate from N8N Cloud to self-hosted?
Yes. Export your workflows from N8N Cloud using the menu in each workflow (Download as JSON) or the API. Import them into your self-hosted instance via Settings > Import Workflows. Credentials need to be re-entered manually since they are not exported for security reasons.
How do I update N8N when self-hosting with Docker?
Bump N8N_VERSION in your .env, then run docker compose pull && docker compose up -d. The container is recreated, with a few seconds of downtime. Back up the n8n_data volume before crossing a major version.
Ready to Get Started?
Book a free 30-minute discovery call. We'll identify your biggest opportunities and show you exactly what AI automation can do for your business.