self hosting

N8N Reverse Proxy Setup

When n8n runs behind a reverse proxy, configure the public host, protocol, and webhook base URL so editor links and incoming webhook URLs match the external domain.

Match your incident first

Start with the symptom you can prove

Jump to checks

Test URL works, production URL returns 404

First check: Open the Webhook node and compare the active production URL with the external app callback URL.

Wrong fix to avoid: Do not rebuild the whole workflow before proving whether the active production endpoint exists.

Verify: Activate the workflow, send a POST to the production URL, and confirm one new production execution appears.

Production URL shows localhost, container hostname, or http instead of public HTTPS

First check: Check the public URL shown in n8n and compare it with WEBHOOK_URL and reverse proxy forwarded headers.

Wrong fix to avoid: Do not paste the internal Docker service name into external SaaS callback settings.

Verify: The Webhook node displays the public HTTPS domain and an external curl reaches n8n without redirect loops.

External app times out but n8n logs show no execution

First check: Run an external curl smoke test and inspect reverse proxy access logs for the same timestamp.

Wrong fix to avoid: Do not rotate credentials when the request never reaches n8n.

Verify: Proxy access log and n8n execution log both show the same request.

Use when
self-hosted, reverse proxy
First check
Copy the callback URL shown in n8n and compare it exactly with the provider app redirect URL.
Time to check
5-10 minutes
Next step
Match the symptom, then run the verification checks.

Independent third-party notes. n8n is a trademark of its owner and is referenced only for compatibility and troubleshooting context.

Quick Answer

When n8n runs behind a reverse proxy, configure the public host, protocol, and webhook base URL so editor links and incoming webhook URLs match the external domain.

Does this match your symptom?

OAuth callback or credentials are blocking execution

The OAuth login does not return to n8n, credentials reconnect but still fail, or provider scopes and callback URLs do not match production.

First check: Copy the callback URL shown in n8n and compare it exactly with the provider app redirect URL.

Version awareness

Last reviewed 2026-05-21

Key Facts

Public webhook base
WEBHOOK_URL sets the public base URL used for generated webhook URLs.
Host variable
N8N_HOST controls the host name n8n uses.
Protocol variable
N8N_PROTOCOL helps align generated URLs with HTTP or HTTPS.
Proxy risk
Internal container URLs can leak into webhook URLs if endpoint variables are wrong.

Production Diagnostic Matrix

Turn checks into a brief
Exact symptom or log Likely cause First check Wrong fix to avoid Verification
Test URL works, production URL returns 404 Workflow is not active, caller is using the test URL, or the production path was changed after activation. Open the Webhook node and compare the active production URL with the external app callback URL. Do not rebuild the whole workflow before proving whether the active production endpoint exists. Activate the workflow, send a POST to the production URL, and confirm one new production execution appears.
Production URL shows localhost, container hostname, or http instead of public HTTPS WEBHOOK_URL, N8N_HOST, N8N_PROTOCOL, or proxy headers do not match the public domain. Check the public URL shown in n8n and compare it with WEBHOOK_URL and reverse proxy forwarded headers. Do not paste the internal Docker service name into external SaaS callback settings. The Webhook node displays the public HTTPS domain and an external curl reaches n8n without redirect loops.
External app times out but n8n logs show no execution DNS, firewall, Cloudflare, reverse proxy, or path routing blocks the request before it reaches n8n. Run an external curl smoke test and inspect reverse proxy access logs for the same timestamp. Do not rotate credentials when the request never reaches n8n. Proxy access log and n8n execution log both show the same request.
Workflow receives payload but caller gets wrong response or hangs Respond to Webhook is missing, configured for the wrong response mode, or waits for a branch that does not finish. Check the Webhook node response mode and the Respond to Webhook node path. Do not add arbitrary Wait nodes to hide timeout behavior. Caller receives the intended status code and body within the provider timeout window.
Webhook path works internally but fails through reverse proxy Proxy location, base path, body size, TLS termination, or forwarded proto/host headers are wrong. Compare direct container access with the public reverse proxy route and check forwarded headers. Do not disable HTTPS verification as a proxy troubleshooting shortcut. Public HTTPS request preserves method, path, body, and host all the way to n8n.
  1. Point the public domain to the reverse proxy.
  2. Proxy traffic to the internal n8n service and port.
  3. Set N8N_HOST to the public host name.
  4. Set N8N_PROTOCOL=https when public access uses HTTPS.
  5. Set WEBHOOK_URL to the full public base URL.
  6. Generate a webhook URL and confirm it uses the public domain.

Verification

  • The editor loads on the public domain.
  • Generated webhook URLs use HTTPS and the public domain.
  • An external request reaches a Webhook node.

First Commands / Checks

Webhook smoke test Use when an external app reports timeout, 404, or wrong response.
curl -i -X POST https://automation.example.com/webhook/example-path \
  -H "content-type: application/json" \
  -d '{"smokeTest":true}'
Secrets note
Use a disposable path or non-sensitive payload. Do not paste provider signing secrets into curl examples.
Verification
The response status and body match the Webhook or Respond to Webhook configuration.
Check container state Use first when n8n is down, restarting, or behaving differently after a deploy.
docker compose ps
Secrets note
This lists service names and status only; it should not print credential values.
Verification
n8n, database, Redis, and worker services are running or the failing service is obvious.
Read recent n8n logs Use when the editor, webhook, or startup path fails.
docker compose logs n8n --tail=100
Secrets note
Review before sharing; remove tokens, private hostnames, and customer payloads.
Verification
The log contains a timestamped error, migration message, or clean startup line.
Check public URL variables only Use when webhook URLs show localhost, http, or the wrong domain.
docker compose exec n8n printenv WEBHOOK_URL N8N_HOST N8N_PROTOCOL N8N_EDITOR_BASE_URL
Secrets note
Do not run a full env dump in public channels; print only these non-secret routing names.
Verification
Values point to the intended HTTPS public domain.

Safe Copyable Config

Reverse proxy header shape Use when the public route reaches the proxy but n8n generates wrong URLs or websockets fail.
location / {
  proxy_pass http://n8n: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;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}
.env.example with redacted production placeholders Use as a review checklist for self-hosted n8n environment variables.
N8N_HOST=automation.example.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://automation.example.com/
GENERIC_TIMEZONE=UTC
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n_app
DB_POSTGRESDB_PASSWORD=REDACTED_CHANGE_ME
N8N_ENCRYPTION_KEY=REDACTED_GENERATE_ONCE

Warnings

  • If WEBHOOK_URL is wrong, third-party services may receive unusable webhook URLs.
  • Forwarded headers and HTTPS termination should be handled consistently by the proxy.

Best For

  • Self-hosted n8n behind Nginx, Caddy, Traefik, Cloudflare Tunnel, or a platform proxy.
  • Public domains where the browser and external webhook providers must use the same HTTPS host.
  • Deployments where n8n runs on an internal container port but should appear on a clean public URL.

Not For

  • Local-only testing with no external webhook providers.
  • n8n Cloud users who do not control the proxy layer.
  • Cases where the real issue is a Webhook node path or workflow activation problem.

Common Mistakes

  • Proxying the UI but forgetting that webhook URLs also need the public domain.
  • Leaving WEBHOOK_URL unset so generated URLs use an internal host.
  • Terminating HTTPS at the proxy but letting n8n generate http:// URLs.
  • Not forwarding large request bodies or long-running webhook responses correctly.

Examples

Public URL environment values Use your actual domain and confirm these against your proxy setup.
N8N_HOST=automation.example.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://automation.example.com/
Reverse proxy smoke test Confirm both UI and webhooks work from outside the server.
Open UI: https://automation.example.com
Copy production webhook URL from n8n
Send external curl request
Check execution history
Confirm generated URL does not contain localhost

FAQ

Why does the UI work but webhooks fail?

The proxy may route browser traffic correctly while n8n still generates webhook URLs with the wrong base URL, or the proxy may not forward webhook paths correctly.

Should WEBHOOK_URL include a path?

Usually it should be the public base URL for the instance. Match the official endpoint variable docs and your proxy path strategy.

Can I run n8n under a subpath?

Subpath deployments need extra care because generated URLs, proxy rewriting, and webhook paths must all agree.

Sources