n8n Nginx Reverse Proxy & SSL Certificate Setup

I put n8n behind nginx because exposing it directly to the internet is reckless. Here’s the exact nginx configuration I use for every self-hosted instance.

Running n8n on port 5678 and pointing a browser at it works fine locally. But production demands encryption, proper headers, and a layer of indirection. Nginx gives me all three without adding complexity.

I’ve run n8n behind nginx for 18 months across three different servers. The configuration below has handled everything from daily personal automations to enterprise workflow pipelines.

Basic Nginx Reverse Proxy Setup

Start with the core proxy configuration. This sits in /etc/nginx/sites-available/n8n:

`nginx
server {
listen 80;
server_name n8n.yourdomain.com;

# Redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl http2;
server_name n8n.yourdomain.com;

# SSL certificate paths (set up in next section)
ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;

# n8n backend
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;

# WebSocket support for real-time features
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;

# Standard proxy headers
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;

# Timeouts for long-running workflows
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;

# Buffer size for large payloads
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}

# Health check endpoint
location /healthz {
proxy_pass http://127.0.0.1:5678;
proxy_set_header Host $host;
}
}
`

Three lines here deserve special attention. The Upgrade and Connection headers enable WebSocket connections. n8n uses WebSockets for real-time canvas updates and live execution monitoring. Without them, those features break silently.

The timeout settings at 300 seconds handle long-running workflows. Default nginx timeouts are 60 seconds. A data pipeline workflow that processes thousands of records can easily exceed that.

The buffer settings prevent nginx from truncating large API responses. If you’re pulling data from APIs with big JSON payloads, default buffers chop the response and n8n gets incomplete data.

Enable the site and reload:

`bash
ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
`

Test it works:

`bash
curl -I https://n8n.yourdomain.com
`

You should get a 200 OK response. If you get a 502, nginx can’t reach n8n. Check that n8n is running on port 5678 and the proxy_pass directive points to the right address.

SSL Certificate with Let’s Encrypt

Free certificates from Let’s Encrypt eliminate the cost barrier. The trick is keeping them renewed. Certbot handles this automatically.

Install certbot:

`bash
apt update && apt install certbot python3-certbot-nginx -y
`

Request a certificate:

`bash
certbot –nginx -d n8n.yourdomain.com
`

Certbot modifies your nginx configuration to add SSL directives and sets up automatic renewal. Verify it worked:

`bash
curl -vI https://n8n.yourdomain.com 2>&1 | grep -i “subject:”
`

You should see your Let’s Encrypt certificate in the output.

Auto-renewal runs twice daily by default through systemd timers. Check the status:

`bash
systemctl status certbot.timer
`

Test the renewal process without actually renewing:

`bash
certbot renew –dry-run
`

If this fails, your DNS or nginx configuration is blocking certbot’s HTTP challenge. Make sure port 80 is accessible from the internet and that your server_name matches the domain you’re requesting a certificate for.

For multiple n8n instances on the same server, request separate certificates:

`bash
certbot –nginx -d n8n.yourdomain.com -d n8n-staging.yourdomain.com
`

Certbot bundles them into a single certificate. This is cheaper than managing separate certificates and simplifies renewal.

Security Headers and Hardening

HTTPS alone isn’t enough. Add these headers to your nginx server block:

`nginx

HSTS – force browsers to use HTTPS for 1 year

add_header Strict-Transport-Security “max-age=31536000; includeSubDomains” always;

Prevent clickjacking

add_header X-Frame-Options “SAMEORIGIN” always;

XSS protection

add_header X-XSS-Protection “1; mode=block” always;

Content type sniffing prevention

add_header X-Content-Type-Options “nosniff” always;

Referrer policy

add_header Referrer-Policy “strict-origin-when-cross-origin” always;

Remove server version

server_tokens off;
`

HSTS is the most important. It tells browsers that your site only speaks HTTPS. Even if someone types http://n8n.yourdomain.com, the browser upgrades before connecting. This prevents cookie theft and session hijacking on the initial request.

X-Frame-Options prevents other sites from embedding your n8n instance in an iframe. Without it, a phishing site could load your n8n canvas inside their page and trick users into authorizing malicious workflows.

Server tokens off hides the nginx version from response headers. Attackers use version numbers to find known vulnerabilities. There’s no reason to advertise your nginx version publicly.

Restart nginx after adding headers:

`bash
nginx -t && systemctl reload nginx
`

Rate Limiting for Protection

Add rate limiting to prevent brute-force attacks on your n8n login:

`nginx
limit_req_zone $binary_remote_addr zone=n8n_limit:10m rate=10r/s;

server {
listen 443 ssl http2;
server_name n8n.yourdomain.com;

location /login {
limit_req zone=n8n_limit burst=20 nodelay;
proxy_pass http://127.0.0.1:5678;
# … rest of proxy config
}

location / {
# Allow higher rate for workflow execution
limit_req zone=n8n_limit burst=50 nodelay;
proxy_pass http://127.0.0.1:5678;
# … rest of proxy config
}
}
`

The login endpoint gets a stricter limit (10 requests/second with burst of 20). Workflow execution endpoints get a higher limit since automated processes generate more requests naturally.

Adjust these numbers based on your actual traffic. If you’re hitting rate limits during normal operation, increase the burst value. If you’re getting attacked, decrease it.

Connecting to Your Existing Setup

If you already have n8n running in Docker, the n8n Docker Deployment guide covers the container setup. Nginx proxies to the container the same way it proxies to a local process — just change 127.0.0.1:5678 to the container name or IP.

The n8n Docker Compose production stack includes nginx as part of the compose file. If you’re using that setup, the proxy configuration is already embedded in the nginx service definition.

For security hardening, the n8n Security: Encryption, Authentication & HTTPS guide covers encryption keys, credential storage, and network-level protections. Nginx SSL termination is one layer. The encryption key protects your stored credentials at rest. Both matter.

Action Card: One-Command Setup

Deploy nginx + SSL for n8n in one go:

`bash

Install nginx and certbot

apt install nginx certbot python3-certbot-nginx -y

Create nginx config

cat > /etc/nginx/sites-available/n8n << 'EOF' server { listen 80; server_name n8n.yourdomain.com; location / { return 301 https://$host$request_uri; } }

server {
listen 443 ssl http2;
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;

location / {
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_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
}
}
EOF

Enable and test

ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

Get SSL certificate

certbot –nginx -d n8n.yourdomain.com
`

References

  • Nginx Reverse Proxy Documentation
  • Let’s Encrypt Documentation
  • Mozilla SSL Configuration Generator
  • Nginx Security Best Practices
  • Leave a Reply

    Your email address will not be published. Required fields are marked *