Journal indexDockup / field note
Note / self-host-n8n

How to Self-Host n8n in 2026: Deploy, TLS, Webhooks and Backups

Self-host n8n with correct ports, persistent storage, HTTPS, secrets, backups and upgrade checks. Learn how to fix when webhook links still point to localhost.

An n8n container can be green while the job users care about is broken. For n8n, that hidden failure is usually that webhook links still point to localhost or proxy headers report HTTP. This guide treats “activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node” as the acceptance test and builds the deployment backward from that result.

n8n has a specific role in the stack: workflow automation with 400+ integrations and an extensible node system. The production question is therefore not whether port 5678 answers once, but whether state, dependencies and the public address continue to agree after a restart, update and restore.

Separate replaceable containers from lasting data

Define recovery point and recovery time for n8n in terms of the database plus the .n8n encryption and configuration data. Mount /home/node/.n8n before bootstrap, write harmless sample data and replace the container to prove that path is actually persistent. A named volume solves redeploy persistence; it does not solve compromise or server loss.

Build a clean restore environment, use the same pinned application version and prove that restored credentials still decrypt and a restored workflow receives the same public webhook URL. Record commands, ownership fixes and elapsed time. The backup guide is a useful standard: a backup is trusted after restoration, not after upload.

Make n8n startup reproducible

A minimal command is useful when it reveals what the platform will later manage.

docker run -d \
  --name n8n \
  --restart unless-stopped \
  -p 127.0.0.1:5678:5678 \
  -v n8n-data:/home/node/.n8n \
  -e N8N_ENCRYPTION_KEY=replace-with-a-long-random-value \
  docker.n8n.io/n8nio/n8n

Here port 5678 remains host-private and every required path is explicit. Add the reviewed connection settings for Postgres for a durable multi-user production setup; use private names for private services. Verify startup with both logs and the application-specific proof: activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node. Once verified, lock the image version so a routine replacement does not silently change behavior.

Ports, processes and private services

Start with the n8n network namespace: its web listener is port 5678, not a host port copied from a laptop tutorial. The network contract for n8n is Postgres for a durable multi-user production setup. Keep private endpoints on internal DNS, permit only required outbound calls and give n8n a scoped service credential.

After the requirement is satisfied, run the complete scenario — activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node. Record logs and measurements for execution concurrency, queue depth, binary payload size and long-running nodes rather than editor page views. That evidence becomes the first known-good architecture and makes later moves between Dockup compute and an attached server testable.

Prevent proxy success from masking application failure

The public boundary for n8n should be one canonical hostname, automatic TLS and one internal target on 5678. Set WEBHOOK_URL to the exact external HTTPS URL so clients return to an address the service recognizes.

If the acceptance transaction fails, classify the first error. DNS, certificate and 502 problems belong to the TLS validation checklist. The condition “webhook links still point to localhost or proxy headers report HTTP” belongs to the application side after a request has successfully reached n8n.

What must pass before real n8n data arrives

Convert the n8n smoke test into a repeatable release command or short runbook. Its output must demonstrate this outcome: activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node. Record the application version, container digest, route hostname and test-data identifier with the result.

Run the same check after a routine container swap and after restoring the database plus the .n8n encryption and configuration data elsewhere. The restore has succeeded when restored credentials still decrypt and a restored workflow receives the same public webhook URL. Compare timing and consumption related to execution concurrency, queue depth, binary payload size and long-running nodes rather than editor page views; a large change is worth investigation even when the final action still passes.

Then exercise a safe failure: temporarily deny the test identity access to Postgres for a durable multi-user production setup. Confirm that n8n surfaces the fault and returns to normal without destructive manual edits. Preserve only the necessary, redacted log excerpt. This four-part gate covers startup, persistence, recovery and failure handling.

Capacity and upgrade checks

Build dashboards around execution concurrency, queue depth, binary payload size and long-running nodes rather than editor page views. A CPU graph without that workload context cannot explain why n8n is slow. Add a synthetic or scheduled check that tries to activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node using harmless test data.

Before upgrading, account for this application-specific hazard: database migrations, credential encryption and installed community nodes must remain compatible with the target n8n release. Restore a recent backup into an isolated deployment, run migrations there and compare behavior. If webhook links still point to localhost or proxy headers report HTTP, inspect the boundary involved — public origin, storage or dependency — before touching unrelated settings.

Lock down n8n after bootstrap

Do not inherit security assumptions from a local tutorial. n8n's specific concern is rotating N8N_ENCRYPTION_KEY after credentials have been saved. Production should therefore keep the editor authenticated while exposing only the webhook paths that integrations genuinely need.

Generate N8N_ENCRYPTION_KEY once, keep it out of Git and preserve it with the recovery manifest because changing it can invalidate encrypted or signed application state. Scope filesystem and network access, protect setup endpoints and define upload, request or execution limits around execution concurrency, queue depth, binary payload size and long-running nodes rather than editor page views.

Keep n8n explicit while Dockup handles routing

Dockup's one-click n8n deployment should make replacement safe: the route continues to target 5678, secrets are not baked into the image and persistent paths return on the new container. The same deployment can run on Dockup compute or an attached machine.

Complete the app-specific work by connecting and testing Postgres for a durable multi-user production setup, applying the canonical public address and running this acceptance check: activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node. Add the restore result to the runbook before real users arrive.

Frequently asked questions

What does n8n need for a production deployment?

Route the n8n container on port 5678 through one HTTPS origin. The supporting network requirement is Postgres for a durable multi-user production setup. Do not call n8n ready until you can activate a workflow with a production webhook, call that webhook from outside the server and confirm the execution reaches its final node.

Which n8n data belongs in a backup?

Persist /home/node/.n8n and include the database plus the .n8n encryption and configuration data in the same recovery manifest. A clean n8n restore passes only when restored credentials still decrypt and a restored workflow receives the same public webhook URL.

Does n8n require HTTPS behind a reverse proxy?

Use HTTPS for the public n8n origin and keep port 5678 on the internal route. Apply the n8n setting correctly: set WEBHOOK_URL to the exact external HTTPS URL. For n8n, HTTPS protects credentials or user content in transit and keeps origin-sensitive client behavior consistent.

How should an n8n upgrade be tested?

Restore current n8n state into an isolated deployment, apply the candidate version and repeat its acceptance transaction. Pay particular attention because database migrations, credential encryption and installed community nodes must remain compatible with the target n8n release. Keep the previous n8n image until its data-migration and rollback boundary are understood.