Home / Software / n8n / How to Put n8n Behind a Reverse Proxy with SSL

How to Put n8n Behind a Reverse Proxy with SSL

How to Put n8n Behind a Reverse Proxy with SSL

Running n8n on a VPS is straightforward enough, but leaving it exposed on port 5678 is not something you want in production. Without a reverse proxy, you have no HTTPS, no custom domain, and your automation tool sitting on an obscure port that is both ugly and insecure. If you are hosting n8n on a Hetzner VPS, a UK provider such as Mythic Beasts or Fasthosts, or any shared server where other services already run, a reverse proxy gives you SSL termination, a clean domain name, and the ability to serve multiple apps from a single IP. This guide walks through two approaches: Nginx, which is the most widely used and gives you full control, and Caddy, which handles SSL automatically and requires almost no configuration.

Why a Reverse Proxy Matters for n8n

n8n’s built-in server is not designed to face the internet directly. A reverse proxy sits in front of it and handles the parts that matter for production: terminating TLS so all traffic is encrypted, forwarding requests to the correct internal port, and allowing you to run Postgres, Gitea, Nextcloud, or any other self-hosted service on the same server without port conflicts. It also means you can block port 5678 from the outside entirely, so n8n is only reachable through the proxy. For webhook-heavy workflows this is especially important — your webhook URLs need to be stable HTTPS addresses, not http://123.456.78.90:5678/webhook/abc.

Before You Start: Firewall Rules

Regardless of which proxy you choose, set your firewall to allow ports 80 and 443 and block port 5678 from external access. On Ubuntu with UFW:

ufw allow 80
ufw allow 443
ufw deny 5678
ufw enable

Port 5678 will still work internally (the proxy forwards to it on localhost), but nothing outside your server can reach it directly.

Option 1: Nginx (Most Common)

Nginx is the standard choice for UK businesses running multiple self-hosted services on a single VPS. If you already have WordPress, a FastAPI app, or anything else behind Nginx, adding n8n is just another server block.

Install Nginx:

apt install nginx

Create the site configuration at /etc/nginx/sites-available/n8n:

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

    location / {
        proxy_pass http://localhost:5678;
        proxy_http_version 1.1;

        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;

        # WebSocket support — required for n8n's UI
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        client_max_body_size 50m;
    }
}

The WebSocket headers are not optional. n8n’s editor uses WebSockets for real-time updates — without the Upgrade and Connection headers, the UI will load but execution status will not update and you will see connection errors in the browser console. The client_max_body_size 50m setting prevents failures when workflows handle file uploads or large JSON payloads.

Enable the site and test:

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

Get an SSL certificate with Certbot:

apt install certbot python3-certbot-nginx
certbot --nginx -d n8n.yourdomain.com

Certbot will modify your server block automatically to redirect HTTP to HTTPS and add the certificate paths. It also installs a renewal timer, so your certificate renews without manual intervention.

Update n8n’s environment variables so it knows its public URL. If you are running n8n with Docker Compose, add these to your .env or docker-compose.yml:

N8N_HOST=n8n.yourdomain.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com

Restart n8n after making these changes. Without WEBHOOK_URL, n8n will generate webhook URLs using the internal hostname, which will not work from outside the server.

Option 2: Caddy (Simpler SSL)

Caddy is a good choice if you are setting up a fresh server and want the simplest possible configuration. It provisions and renews SSL certificates automatically using Let’s Encrypt — there is no Certbot step, no manual certificate renewal to worry about, and the configuration file is minimal.

Install Caddy by following the official instructions for your distro (the Caddy project provides an apt repository). On Ubuntu:

apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install caddy

Create your Caddyfile at /etc/caddy/Caddyfile:

n8n.yourdomain.com {
    reverse_proxy localhost:5678
}

That is the entire configuration. Caddy detects that your site is publicly reachable, requests a certificate from Let’s Encrypt automatically on first request, and handles renewals in the background. WebSocket proxying is enabled by default in Caddy, so there are no additional headers to add.

Start Caddy:

systemctl enable caddy
systemctl start caddy

Update n8n’s environment variables — identical to the Nginx setup:

N8N_HOST=n8n.yourdomain.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com

Using Cloudflare in Front

If your domain’s DNS is managed through Cloudflare, you can proxy traffic through Cloudflare’s network in addition to using Nginx or Caddy on your server. This works without any special configuration, but you must set Cloudflare’s SSL mode to Full (not Flexible) in the SSL/TLS settings for your domain. Flexible mode sends unencrypted traffic between Cloudflare and your server, which defeats the purpose of your certificate. Full mode encrypts the entire connection. n8n’s WebSocket connections work through Cloudflare without additional settings.

A Note for UK Businesses

Many UK teams running n8n self-host it alongside other internal tools — Gitea for code, Nextcloud for file storage, a FastAPI service or two — all behind a single Nginx instance on a Hetzner CX22 or similar. The pattern is the same for each service: one server block per subdomain, one Certbot certificate per domain, and everything internal listening on localhost. If you are already paying for a VPS for something else, adding n8n costs nothing extra and keeps your data entirely within infrastructure you control.