If you're building automation workflows, n8n is one of the best open-source tools available. Instead of paying for n8n Cloud, you can run it on your own VPS for free — with your own subdomain, SSL certificate, and a cookie-based authentication layer so only you can access it.
This guide walks through exactly how I set it up on a Hetzner VPS running Ubuntu, with n8n accessible at n8n.yourdomain.com and protected behind a management dashboard login.
What You'll Need
- A VPS running Ubuntu (I used Hetzner, but any provider works)
- A domain with DNS managed via Hetzner DNS (or any DNS provider)
- Node.js and npm installed on the VPS
- A web server on your main domain (Apache or Nginx) for the auth cookie script
Install n8n on Your VPS
SSH into your VPS and install n8n globally via npm:
npm install -g n8n
Verify it works:
n8n --version
Run n8n with PM2
PM2 keeps n8n running in the background and restarts it automatically on reboot. Install it:
npm install -g pm2
Start n8n, binding it to localhost only so it's not publicly reachable directly:
N8N_HOST=127.0.0.1 N8N_PORT=5678 pm2 start /usr/bin/n8n --name n8n
Important: Use the full path
/usr/bin/n8n, not justn8n— otherwise PM2 can't find the binary.
Make PM2 survive server reboots:
pm2 startup # Run the command it prints pm2 save
Verify n8n is running:
pm2 status
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5678
# Should return 200
Point a Subdomain to Your VPS
In your DNS provider, add an A record:
| Type | Name | Value | TTL |
|---|---|---|---|
| A | n8n | YOUR.VPS.IP.ADDRESS | 300 |
Wait a few minutes, then verify it propagated:
nslookup n8n.yourdomain.com 8.8.8.8
# Should return your VPS IP
Install Nginx and Get an SSL Certificate
Install Nginx and Certbot on your VPS:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx -y
Create a basic Nginx config for the subdomain first (Certbot needs it to exist):
sudo nano /etc/nginx/sites-available/n8n
Paste this minimal config:
server {
listen 80;
server_name n8n.yourdomain.com;
location / {
return 200 'ok';
}
}
Enable it and reload:
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/n8n
sudo nginx -t && sudo systemctl reload nginx
Now get the SSL certificate:
sudo certbot --nginx -d n8n.yourdomain.com
Configure the Full Nginx Reverse Proxy
Now replace the config with the full version that proxies to n8n with WebSocket support and cookie-based authentication:
sudo tee /etc/nginx/sites-available/n8n > /dev/null << 'EOF'
server {
listen 80;
server_name n8n.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name n8n.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
default_type text/html;
location / {
set $allow 0;
if ($cookie_n8n_access = "YOUR_SECRET_HERE") {
set $allow 1;
}
if ($allow = 0) {
return 403 '<!doctype html><html><head><meta charset="utf-8"><title>Access Denied</title><style>*{margin:0;padding:0;box-sizing:border-box}body{min-height:100vh;background:#060d18;display:flex;align-items:center;justify-content:center;font-family:system-ui,sans-serif}div{text-align:center;color:#cbd5e1}h1{font-size:3rem;color:#f1f5f9;margin-bottom:.5rem}p{color:rgba(255,255,255,.4);margin-bottom:1.5rem}a{display:inline-block;padding:10px 24px;background:linear-gradient(135deg,#1a3a52,#0e4f6e);color:#fff;border-radius:8px;text-decoration:none}</style></head><body><div><h1>403</h1><p>Access via the management dashboard</p><a href="https://management.yourdomain.com/n8n_auth.php">Go to Dashboard</a></div></body></html>';
}
proxy_pass http://127.0.0.1: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_set_header Cookie $http_cookie;
proxy_read_timeout 300s;
}
}
EOF
sudo nginx -t && sudo systemctl reload nginx
Generate a strong secret to use in place of YOUR_SECRET_HERE:
openssl rand -hex 32
Create the Auth Cookie Script
The authentication works by setting a shared-secret cookie on your main domain. When you visit n8n, Nginx checks for that cookie. If it's not there, you get the 403 page.
On your main hosting server, create management/n8n_auth.php:
<?php
require_once __DIR__ . '/includes/config.php';
require_once __DIR__ . '/includes/auth.php';
requireLogin(); // Ensures only logged-in users can proceed
const N8N_COOKIE_SECRET = 'YOUR_SECRET_HERE'; // Same secret as Nginx config
setcookie('n8n_access', N8N_COOKIE_SECRET, [
'expires' => time() + 8 * 3600,
'path' => '/',
'domain' => '.yourdomain.com',
'secure' => true,
'httponly' => false,
'samesite' => 'Lax',
]);
header('Location: https://n8n.yourdomain.com');
exit;
The cookie is set on .yourdomain.com (note the leading dot) so it's shared across all subdomains including n8n.yourdomain.com. It expires after 8 hours.
Add the n8n Button to Your Dashboard
In your management dashboard navbar, link the n8n button to n8n_auth.php rather than directly to the subdomain:
<a href="n8n_auth.php" target="_blank">
<i class="fas fa-diagram-project"></i> n8n
</a>
This ensures the cookie is always set before the redirect happens.
How It Works
The full flow when you click the n8n button:
- You're already logged into the management dashboard
n8n_auth.phpruns — verifies your session viarequireLogin()- Sets the
n8n_accesscookie on.yourdomain.comwith the shared secret - Redirects you to
https://n8n.yourdomain.com - Nginx reads the cookie, matches the secret, and proxies the request to
127.0.0.1:5678 - Anyone without the cookie (or with the wrong value) gets the 403 page

This approach avoids the need for n8n's own user management entirely and ties access directly to your existing dashboard authentication.
Why Not Use Nginx auth_request?
The more conventional approach is to use Nginx's auth_request directive, which makes a subrequest to your auth endpoint before allowing access. However, if your main domain is on shared hosting, the hosting server will likely reject HTTP requests originating from your VPS IP with a 421 Misdirected Request error. The cookie-based approach sidesteps this entirely by avoiding any server-to-server communication.
Wrapping Up
You now have n8n running on your own infrastructure, accessible only through your authenticated management dashboard, with SSL, WebSocket support, and automatic restarts. Total ongoing cost: just your VPS. No n8n Cloud subscription needed.