CALIBRATING SYSTEMS
Home / Blog / How to Secure n8n Self Hosted: A Practical Hardening Checklist
Tools

How to Secure n8n Self Hosted: A Practical Hardening Checklist

· 8 min read · Ali Raza Abro

If you want to know how to secure n8n self hosted, the short answer is this: put it behind a reverse proxy that terminates HTTPS, use n8n's built-in user management with two-factor authentication, protect the encryption key and the database, lock down what Code nodes and expressions can reach, and run the built-in security audit on a schedule. Most self-hosted n8n incidents I have seen come from one of those five being skipped, usually because someone spun up a test instance on a public IP and it quietly became production.

This guide walks through each layer in the order I set it up for agencies, with the reasoning behind each step.

Why self-hosted n8n needs more care than cloud tools

An n8n instance is a vault of keys. Every credential you add, whether it is a Google OAuth connection, a GoHighLevel API key, a ClickUp token or a Slack bot token, lives inside it. If someone gets into the editor, they do not just see your workflows. They can run any of those credentials against your clients' accounts.

With Zapier or Make, the vendor handles the server, TLS, patching and access control. When you self-host, all of that becomes your job. That is the real trade-off covered in my n8n self-hosted vs cloud comparison: you swap a subscription for responsibility.

Step 1: Never expose n8n directly, use a reverse proxy with HTTPS

n8n listens on port 5678 by default. Do not publish that port to the internet. Instead, run a reverse proxy in front of it and only expose ports 80 and 443.

Good options:

  • Caddy, which gets and renews Let's Encrypt certificates automatically with almost no config.
  • Nginx, with Certbot for certificates. Very common and well documented.
  • Traefik, which works nicely if you already run several containers with Docker labels.

Whichever you pick, the order is:

  1. Point a subdomain such as automations.youragency.com at the server.
  2. Configure the proxy to forward requests to the n8n container on the internal Docker network, not on a public port.
  3. Turn on HTTPS and redirect plain HTTP to HTTPS.
  4. Make sure the proxy passes websocket connections, because the editor uses them for live updates.
  5. Tell n8n about its public address with the N8N_HOST, N8N_PROTOCOL and WEBHOOK_URL environment variables, so webhook URLs and OAuth callbacks are generated with https and the right domain.
  6. If n8n sits behind one proxy, set N8N_PROXY_HOPS to 1 so it reads the client IP correctly.

n8n's N8N_SECURE_COOKIE setting defaults to true, which means session cookies only travel over HTTPS. That is another reason to get TLS right first. People who hit login loops on a fresh install often turn this off. Do not. Fix the HTTPS setup instead.

On the firewall, allow only 22 (ideally restricted to your IP or behind a VPN), 80 and 443. Your database port should never be reachable from outside the server.

Step 2: n8n basic auth is gone, use user management and MFA

A lot of older tutorials tell you to set N8N_BASIC_AUTH_ACTIVE and a username and password. That advice is out of date. According to n8n's docs, version 1.0 removed basic auth and external JWT auth, and user management became mandatory. There is no supported way to disable the login screen in current versions.

So the modern answer to "n8n basic auth" is:

  • Create the owner account immediately after first boot. An unclaimed fresh instance is the most dangerous state n8n can be in.
  • Give each person their own account. Never share the owner login across the team.
  • Turn on two-factor authentication for every user. n8n's security policy settings can enforce MFA for everyone, and there is an N8N_MFA_ENFORCED_ENABLED variable to set it from the environment.
  • Use roles. Most people on an agency team only need to edit the workflows they own, not manage users or every credential.
  • If your plan supports it, connect SSO through SAML or OIDC so leaving staff lose access when their Google or Microsoft account is disabled.

If you still want an extra gate, you can add basic auth or an IP allowlist at the reverse proxy level for the editor. If you do, exclude the webhook paths, otherwise your forms, GoHighLevel webhooks and Stripe events will all start failing with 401 errors.

Step 3: Protect the encryption key and the database

n8n encrypts stored credentials with an encryption key. On Docker, that key lives in the /home/node/.n8n folder unless you set N8N_ENCRYPTION_KEY yourself. Two rules follow from this:

  • Persist that folder on a volume. If the container is recreated without it, n8n generates a new key and every saved credential becomes unreadable.
  • Back up the key separately from the database. A database backup without the key is useless, and a key stored next to the backup defeats the point of encrypting.

I prefer setting N8N_ENCRYPTION_KEY explicitly from a secrets file or a password manager entry, so it is documented and the same on every rebuild. n8n also supports rotating the encryption key, which is worth doing if a former contractor had server access.

For the database, use Postgres for anything beyond testing. Give n8n its own database user with a strong password, keep Postgres on the internal Docker network only, and back it up nightly. My n8n backup and update guide covers the backup routine in detail.

Step 4: Limit what workflows themselves can do

This is the part most people skip. Anyone who can edit a workflow can run code on your server through the Code node and expressions. Reduce the blast radius:

  • Block environment access. N8N_BLOCK_ENV_ACCESS_IN_NODE stops expressions and the Code node from reading environment variables, which is where your database password and encryption key may live.
  • Restrict file access. N8N_RESTRICT_FILE_ACCESS_TO limits file nodes to specific directories, and N8N_BLOCK_FILE_ACCESS_TO_N8N_FILES (on by default) keeps workflows out of the .n8n folder.
  • Block risky nodes. n8n lets you block specific nodes. If nobody on your team needs Execute Command or SSH, block them.
  • Use task runners. n8n's docs describe task runners for isolating Code node execution. Turn them on so a buggy or malicious script does not run in the main process.
  • Consider SSRF protection. n8n has settings that control which hosts and IP ranges nodes can call. This matters if the server can reach internal services or a cloud metadata endpoint.

Step 5: Secure your webhooks

Webhooks are public by design, so treat each one as a door.

  1. Use the Webhook node's authentication option (header auth or basic auth) wherever the sender supports adding a header.
  2. For services that sign requests, such as Stripe, verify the signature in the workflow before doing anything else.
  3. Use long, random webhook paths rather than names like /new-lead.
  4. Validate the payload early with an IF node and stop the run if required fields are missing.
  5. Never return sensitive data in the webhook response.

Step 6: Reduce your attack surface

  • Disable the public API if nothing uses it. n8n supports turning off its REST API entirely.
  • Opt out of telemetry if your clients' security reviews require it.
  • Redact execution data for workflows that handle personal information. Execution logs store input and output for every node, which can include names, phone numbers and emails. n8n lets you redact this, and you should also set an execution pruning window so old data does not pile up.
  • Keep the editor off the public internet entirely if you can. Putting it behind a VPN or Tailscale and exposing only the webhook path through the proxy is the strongest setup I use.

Step 7: Patch and audit on a schedule

n8n ships updates frequently, and some of them are security fixes. Pin a version tag in Docker, read the release notes, and update at least monthly.

n8n also has a built-in security audit. You can run it from the CLI with the n8n audit command, and it reports risks such as credentials not used in any workflow, abandoned workflows, risky nodes and instance settings. I run it after every update and fix anything it flags. Add it to your monthly checklist with:

  • Remove users who have left.
  • Delete unused credentials.
  • Rotate any API key that was shared in Slack or email.
  • Check the server's disk space and OS updates.

n8n's own security documentation lists every hardening option, and it is worth reading once end to end.

n8n security checklist

Here is the condensed version to copy into your SOPs:

  • n8n behind Caddy, Nginx or Traefik with HTTPS, port 5678 not public
  • N8N_HOST, N8N_PROTOCOL and WEBHOOK_URL set to the public https address
  • Owner account claimed, one account per person, MFA enforced
  • Encryption key set explicitly and backed up separately
  • Postgres on an internal network with nightly backups
  • Env access blocked in nodes, file access restricted, risky nodes blocked
  • Webhooks authenticated or signature-verified
  • Public API disabled if unused, execution data pruned
  • Monthly update plus n8n audit

How I build this

When I set up self-hosted n8n for an agency, I deliver the hardened stack, the backup job and a written runbook so your team is not dependent on me. If you already have an instance and are not sure it is safe, my Automation Rescue is a 48-hour review and fix of broken or risky setups. You can also start with a free 15-minute Loom teardown of your current automation stack, and I will point out the biggest risks I see.

FAQ

Does n8n still support basic auth?

No. n8n removed basic auth and external JWT auth in version 1.0 and made user management mandatory. Use individual accounts with MFA, and add proxy-level protection only if you exclude webhook paths.

Is self-hosted n8n secure?

It can be very secure, but only if you configure it. With HTTPS, user management, MFA, a protected encryption key, restricted Code node access and regular updates, it is a solid setup. Out of the box on a public IP, it is not.

How do I put n8n behind a reverse proxy with HTTPS?

Run Caddy, Nginx or Traefik in front of the n8n container, issue a certificate for your subdomain, forward traffic to n8n on the internal network with websockets enabled, and set N8N_HOST, N8N_PROTOCOL and WEBHOOK_URL to the public https address.

What happens if I lose the n8n encryption key?

n8n can no longer decrypt your saved credentials, so every connection has to be re-created. Persist the .n8n folder on a volume and keep a separate backup of the key.

How often should I update self-hosted n8n?

At least monthly, and sooner when a release mentions a security fix. Back up first and test the update on a staging copy if the instance runs client-critical workflows.

Show me the workflow you hate.

Send one workflow and get a free 15-minute Loom teardown, or book a call if you’d rather talk it through.