How to Self-Host n8n on a VPS in 2026 (Docker, Nginx & SSL)
For modern developers and startups, n8n has become the absolute gold standard for building automated workflows, connecting AI agents, and replacing expensive platforms like Zapier or Make.
However, n8n’s Cloud plans are notoriously restrictive. The basic plan limits you to a handful of workflows and executions, and costs spiral quickly once your automations start running at scale.
The solution? Self-hosting n8n on your own Virtual Private Server (VPS).
By hosting n8n locally on a VPS, you get:
- Unlimited Executions: Run as many workflows as your server’s hardware can handle.
- Flat-rate Cost: A stable $5/month VPS handles thousands of executions daily.
- Direct Database Access: Connect directly to local databases, file systems, and internal APIs without complex webhooks.
This guide provides a production-ready, step-by-step walk-through to deploy n8n using Docker Compose, PostgreSQL (database), Nginx, and Let’s Encrypt SSL.
Prerequisites: What You Need
Before starting, ensure you have the following ready:
- A VPS Server: Run Ubuntu 22.04 or 24.04. We highly recommend a server with at least 2GB RAM (e.g., Hetzner CX22 or a standard DigitalOcean Droplet) to ensure smooth n8n execution and handle heavy payload processing.
- A Domain Name: A subdomain (e.g.,
n8n.yourdomain.com) with an A Record pointing directly to your VPS’s public IP address. - SSH Access: Root or sudo access to your server.
Step 1: Install Docker and Docker Compose
We will deploy n8n inside Docker to make updates, backups, and migration painless.
Log into your VPS via SSH and run the following commands to update the system and install Docker:
# Update package index
sudo apt update && sudo apt upgrade -y
# Install prerequisite packages
sudo apt install -y curl apt-transport-https ca-certificates gnupg lsb-release
# Add Docker's official GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Set up the repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine and Docker Compose
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Verify that Docker is active and running:
sudo systemctl status docker
Step 2: Set Up the Directory Structure
Create a dedicated directory on your VPS to house your n8n configuration, docker-compose file, and persistent database volumes:
mkdir -p ~/n8n-setup
cd ~/n8n-setup
Step 3: Configure Docker Compose with PostgreSQL
n8n uses SQLite by default, which is fine for hobby projects but dangerous for production. If your server crashes or undergoes high traffic, SQLite can corrupt your workflow database.
We will configure n8n to use PostgreSQL as its persistent database engine.
Create a docker-compose.yml file:
nano docker-compose.yml
Paste the following production-ready configuration. Be sure to replace the placeholder database passwords with secure, randomly generated strings:
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: n8n-db
restart: always
environment:
- POSTGRES_USER=n8n_db_user
- POSTGRES_PASSWORD=YOUR_SECURE_DB_PASSWORD
- POSTGRES_DB=n8n_data
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n_db_user -d n8n_data"]
interval: 5s
timeout: 5s
retries: 5
n8n:
image: n8nio/n8n:latest
container_name: n8n-app
restart: always
ports:
- "127.0.0.1:5678:5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n_data
- DB_POSTGRESDB_USER=n8n_db_user
- DB_POSTGRESDB_PASSWORD=YOUR_SECURE_DB_PASSWORD
- N8N_HOST=n8n.yourdomain.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://n8n.yourdomain.com/
- GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
volumes:
db_data:
n8n_data:
Key Environment Variables Explained:
127.0.0.1:5678:5678: We bind the n8n container port to localhost only. This blocks direct public access to port 5678, forcing all traffic to pass securely through our Nginx reverse proxy.N8N_HOST: Change this to your domain/subdomain.WEBHOOK_URL: Crucial for receiving external webhooks (e.g., from Stripe, GitHub, or Typeform). Must match your public HTTPS domain.GENERIC_TIMEZONE: Set to your local timezone to ensure scheduled workflows run at the correct local hour.
Save and exit the file (Press CTRL+O, then Enter, then CTRL+X).
Step 4: Boot n8n and PostgreSQL
Launch your containers in detached mode:
docker compose up -d
Verify both containers are healthy and running:
docker compose ps
Your n8n application is now running securely behind the scenes on port 5678.
Step 5: Configure Nginx Reverse Proxy with SSL
To access n8n in a web browser via HTTPS and allow n8n’s editor UI to communicate smoothly, we need to configure Nginx to act as a secure proxy.
Install Nginx:
sudo apt install -y nginx
Create a new Nginx server block configuration for n8n:
sudo nano /etc/nginx/sites-available/n8n
Paste the following Nginx configuration, replacing n8n.yourdomain.com with your actual domain:
server {
listen 80;
server_name n8n.yourdomain.com;
# Redirect all HTTP traffic to HTTPS (Certbot will handle this, but good to have)
location / {
proxy_pass http://127.0.0.1:5678;
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# WebSockets support (Crucial for n8n workflow execution logs and UI updates)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
[!IMPORTANT] n8n heavily relies on WebSockets and Server-Sent Events (SSE) to update the canvas UI in real-time when workflows are running. The
UpgradeandConnectionheaders in the Nginx config block above are mandatory. Omitting them will cause the n8n UI to freeze or crash when running workflows.
Activate the site and test the Nginx configuration:
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t
If the test is successful, reload Nginx:
sudo systemctl reload nginx
Step 6: Secure Your n8n Deployment with Let’s Encrypt SSL
Install Certbot and the Nginx plugin to generate a free, auto-renewing Let’s Encrypt SSL certificate:
sudo apt install -y certbot python3-certbot-nginx
Run Certbot to fetch and install the certificate:
sudo certbot --nginx -d n8n.yourdomain.com
Follow the on-screen prompts. Certbot will automatically verify your domain, fetch the SSL certificate, and edit your Nginx configuration to force HTTPS redirection securely.
Step 7: Access n8n and Finalize Setup
Open your browser and navigate to https://n8n.yourdomain.com.
On your first visit, you will be prompted to Create Owner Account. This setup is entirely local to your VPS database; no data is sent back to n8n’s servers.
Once logged in, you can start building, importing, and executing automation workflows with zero execution limits!
Pro-Tips for Production n8n Management
1. How to Update n8n
Upgrading n8n to the latest version takes less than 30 seconds:
cd ~/n8n-setup
docker compose pull
docker compose up -d
Docker will pull the latest :latest image and reboot n8n without losing any of your workflows (since all data resides safely in the PostgreSQL database volume).
2. Set Up a Clean-Up Job
n8n stores every execution log in the database. Over months of heavy use, these logs can consume gigabytes of disk space. To prevent your VPS storage from filling up, add this environment variable under the n8n service in your docker-compose.yml:
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=168 # Keeps logs for 7 days (168 hours), then auto-deletes them
Conclusion
Self-hosting n8n on a VPS is an absolute game-changer. For the price of a cup of coffee per month, you gain a highly scalable, enterprise-level automation engine completely under your control.
To further optimize your server and ensure it runs flawlessly, check out our Node.js VPS Performance Optimization Guide or learn how to secure Nginx further against bot attacks.