Automation

Why Does n8n Fail to Load Behind an Nginx Reverse Proxy?

The first check for n8n behind Nginx is the N8N_HOST environment variable and WebSocket headers. Verify these to resolve 404 errors and connection drops in workflows.

Updated 14 September 20267 min read

At Hostna we run a variety of automation workloads on our internal infrastructure, and we frequently encounter the specific configuration challenges that arise when placing n8n behind an Nginx reverse proxy. The primary cause of failure is almost always a mismatch between the environment variables defined in the n8n container and the header directives defined in the Nginx configuration file. When these two layers do not communicate correctly, the browser is unable to establish a persistent connection, resulting in the dreaded Connection Lost message or a blank dashboard.

Symptom Cause Fix
404 Not Found on assets Incorrect N8N_HOST or N8N_PATH Set N8N_HOST to your domain and N8N_PROTOCOL to https.
Connection Lost in UI Missing WebSocket upgrade headers Add proxy_set_header Upgrade $http_upgrade; and Connection headers.
504 Gateway Timeout proxy_read_timeout is too low Increase proxy_read_timeout to 3600 in the location block.
Invalid Redirect URI WEBHOOK_URL mismatch Ensure WEBHOOK_URL includes the full protocol and domain.

The Role of Environment Variables in Workflow Routing

The first mechanism to investigate is how n8n perceives its own network location. Unlike simpler web applications, n8n generates URLs for webhooks and internal assets based on environment variables rather than the Host header sent by the client. If you are running n8n on our platform, you must explicitly set the N8N_HOST variable to match the public-facing domain name. If this variable is left at its default or set to a local IP address, the application will attempt to load JavaScript and CSS files from an unreachable internal address, causing the browser to return a 404 error.

Furthermore, the N8N_PROTOCOL must be set to https if you are terminating SSL at the proxy level. Failure to do this will cause the application to generate http links, which most modern browsers will block as mixed content. When you check your account for the specific deployment details, ensure that the WEBHOOK_URL variable is also populated, as this is used by external services to send data back to your workflows. Without a correctly defined WEBHOOK_URL, any automation triggered by an external HTTP request will fail to find the correct execution path.

Configuring Nginx for Persistent WebSocket Connections

A common issue with the reverse proxy mechanism when applied to n8n is the failure to handle WebSockets. The n8n editor relies on a persistent connection to receive real-time updates from the server. By default, Nginx does not pass the Upgrade and Connection headers required for the WebSocket handshake. This results in the UI appearing to work for a few seconds before displaying a connection error.

To fix this, you must modify your server block to include specific hop-by-hop headers. This ensures that the HTTP/1.1 connection is correctly upgraded. On our German-hosted stack, we recommend using a map block in the main nginx.conf to handle these headers dynamically, though they can also be hardcoded within the location block of your site configuration. This prevents the connection from being dropped prematurely by the proxy layer.

# Inside the location block for n8n
proxy_pass http://127.0.0.1:5678;
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;

# Essential WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

Managing Timeouts for Long-Running Workflows

Automation tasks often involve processing large datasets or waiting for slow external APIs. If your Nginx configuration uses the default timeout values, which are usually set to 60 seconds, your workflows may be interrupted. When configuring Nginx for n8n, set proxy_read_timeout 3600; and proxy_send_timeout 3600; to ensure that long-running workflows, such as those fetching thousands of rows from a database, do not result in a 504 Gateway Timeout. This is particularly important for vds-hosting users who may be running resource-intensive data migrations that take several minutes to complete.

In addition to the read and send timeouts, consider the client_max_body_size. If your workflows involve uploading large files—such as images for processing or large CSV files—Nginx will block any request that exceeds its default limit, which is often as low as 1 MB. Setting client_max_body_size 0; removes this limit entirely, allowing n8n to handle files based on the memory limits of the container rather than the proxy’s constraints. This adjustment is accessible via the control panel for those using our managed Nginx templates.

Resource Isolation and the OOM Killer

The stability of n8n is also dependent on the underlying virtualization technology. A KVM (Kernel-based Virtual Machine) environment provides a strict abstraction layer that prevents memory ballooning from impacting the Node.js heap, which is vital when n8n processes high-concurrency webhooks. In contrast, OpenVZ environments share a kernel and can sometimes lead to unpredictable behavior if other containers on the same host spike in usage. If the cgroup memory limits of your container are exceeded, the Linux kernel will trigger the OOM killer to terminate the Node.js process to protect the host system.

While pm.max_children is a metric primarily used in our shared-hosting tier for PHP-FPM, the logic of process limits is universal. In a Node.js environment like n8n, you must ensure that your memory limit is high enough to accommodate the peak memory usage of your largest workflow. A single execution that parses a massive JSON file can easily consume several gigabytes of RAM. If your machine only has 4 GB of RAM and you do not have a swap file configured, the process will be killed during the peak of the execution, leaving no error logs in n8n itself, only in the system dmesg output.

DNS Propagation and SSL Termination

When you first set up your domain for n8n, DNS TTL and propagation play a significant role. A DNS TTL (Time to Live) of 3600 seconds is a standard default, but reducing this to 60 seconds before a migration ensures that the reverse proxy points to the new IP address without significant delay. This is a critical step when you move the site across for you or reconfigure your routing. If the DNS is pointing to the wrong IP, Nginx will never receive the request, and you will see a generic browser error rather than an n8n-specific one.

For SSL, most users rely on Let’s Encrypt. When using ACME HTTP-01 for certificate issuance, ensure the Nginx configuration allows access to the /.well-known/acme-challenge/ directory before any global rewrite or return 301 directives are processed. If Nginx redirects the validation request from http to https before the certificate is actually installed, the validation will fail. This is a common hurdle when managing server security and setting up automated renewals through the dashboard.

Diagnostics and Verification Commands

To verify that your Nginx configuration is correctly passing headers, you can use the curl command from a remote machine. By inspecting the response headers, you can confirm if the X-Frame-Options or Content-Security-Policy headers are interfering with the n8n UI. Furthermore, checking the Nginx logs is the most effective way to see if a request is even reaching the proxy. Within the Hostna platform, you have full access to these logs to debug real-time traffic.

You should also consult the official n8n server documentation for the latest recommended header configurations. If you are still seeing errors, use the following commands to check the status of your Nginx service and its configuration integrity:

# Test the Nginx configuration for syntax errors
nginx -t

# Reload Nginx to apply changes without dropping connections
systemctl reload nginx

# Monitor the error log in real-time to catch upstream connection failures
tail -f /var/log/nginx/error.log

If your proxy is correctly configured but the dashboard still fails to load, the issue may lie with the application’s internal database. If you use a PostgreSQL backend, ensure that your shared_buffers are set to roughly one quarter of your total system RAM to handle the indexing of large execution histories. You can find more details on performance tuning in our technical documentation library. For further assistance, you can always reach out to support with the output of your nginx -t command and your docker-compose.yml file. Our team can help you verify if your high-performance virtual servers are configured for optimal automation throughput.

This article was drafted with AI assistance from Hostna’s own research pipeline and published without individual review. Tell us if anything here is wrong.