Running through Proxy in Sub Folder

Describe the problem/error/question:

I’m trying to run the official N8N Docker container on my unraid machine, behind the SWAG reverse proxy.

I’ve spent a few days researching this and have a mess of environment variables defined, and I have no idea what’s valid, deprecated, or just plain wrong anymore:

docker run
  -d
  --name='n8n'
  --net='proxynet'
  --privileged=true
  -e TZ="America/New_York"
  -e HOST_OS="Unraid"
  -e HOST_HOSTNAME="unRAID-OS"
  -e HOST_CONTAINERNAME="n8n"
  -e 'N8N_SECURE_COOKIE'='false'
  -e 'N8N_PATH2'='/n8n/'
  -e 'VUE_APP_URL_BASE_API'='https://home.mydomain.com/n8n/'
  -e 'GENERIC_TIMEZONE'='America/Toronto'
  -e 'WEBHOOK_URL'='https://home.mydomain.com/n8n/'
  -e 'SUBFOLDER'='n8n'
  -e 'N8N_EDITOR_BASE_URL'='https://home.mydomain.com/n8n/'
  -e 'VUE_APP_PUBLIC_PATH'='https://home.mydomain.com/n8n/'
  -e 'N8N_HOST'='home.mydomain.com'
  -l net.unraid.docker.managed=dockerman
  -p '5678:5678/tcp'
  -v '/mnt/user/appdata/n8n/':'/home/node/.n8n':'rw' 'n8nio/n8n'
0bdfab55df0a3160fa26883e099b84569e06114d1e6f5e66647368ff0dfafcec

The command finished successfully!

If I disable the N8N_PATH variable, the GUI loads in private address space:
http://192.168.1.2:5678/workflows

On the public address side, the page loads blank:
https://home.mydomain.com/n8n/

Looking at the Chrome Dev Tools, I can see that resources are trying to load from the root sub domain:
https://home.mydomain.com/assets/index-4C1AxeXk.js

Enabling the N8N_PATH variable to /n8n/ breaks my internal address access (it just loads blank), and doesn’t change the behaviour on the public side.

I should note that when I listen for a webhook event, it has the right URL pre-populated:
https://home.mydomain.com/n8n/webhook-test/dca9a5cc-012b-4dc5-ace2-3c39f5004a21

Here’s a copy of some configs in SWAG:

    • /swag/nginx/proxy-confs/n8n.subfolder.conf
## Version 2023/02/05
# Make sure that your n8n container is named appropriately (e.g., n8n).
# Ensure n8n is set to work with the base URL /n8n/.

location /n8n {
    return 301 $scheme://$host/n8n/;
}

location ^~ /n8n/ {
    # enable the next two lines for http auth
    #auth_basic "Restricted";
    #auth_basic_user_file /config/nginx/.htpasswd;

    # enable for ldap auth (requires ldap-server.conf in the server block)
    #include /config/nginx/ldap-location.conf;

    # enable for Authelia (requires authelia-server.conf in the server block)
    #include /config/nginx/authelia-location.conf;

    # enable for Authentik (requires authentik-server.conf in the server block)
    #include /config/nginx/authentik-location.conf;

    include /config/nginx/proxy.conf;
    include /config/nginx/resolver.conf;
    set $upstream_app n8n;
    set $upstream_port 5678;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    # Additional proxy settings such as headers go below this line, leave the blank line above.
}

# REMOVE THIS LINE BEFORE SUBMITTING: Some proxies require one or more additional location blocks for things like API or RPC endpoints.
# REMOVE THIS LINE BEFORE SUBMITTING: If the proxy you are making a sample for does not require an additional location block please remove the commented out section below.
location ^~ /n8n/api {
     include /config/nginx/proxy.conf;
     include /config/nginx/resolver.conf;
     set $upstream_app n8n;
     set $upstream_port 5678;
     set $upstream_proto http;
     proxy_pass $upstream_proto://$upstream_app:$upstream_port;

     # REMOVE THIS LINE BEFORE SUBMITTING: Additional proxy settings such as headers go below this line, leave the blank line above.
}

  • /swag/nginx/proxy.conf
## Version 2020/10/04 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/proxy.conf

# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

# Proxy Connection Settings
proxy_buffers 32 4k;
proxy_connect_timeout 240;
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 1024;
proxy_http_version 1.1;
proxy_read_timeout 240;
proxy_redirect  http://  $scheme://;
proxy_send_timeout 240;

# Proxy Cache and Cookie Settings
proxy_cache_bypass $cookie_session;
#proxy_cookie_path / "/; Secure"; # enable at your own risk, may break certain apps
proxy_no_cache $cookie_session;

# Proxy Header Settings
proxy_set_header Connection $connection_upgrade;
proxy_set_header Early-Data $ssl_early_data;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Real-IP $remote_addr;
  • /swag/nginx/nginx.conf
## Version 2022/08/16 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/nginx.conf.sample

### Based on alpine defaults
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.conf?h=3.15-stable

user abc;

# Set number of worker processes automatically based on number of CPU cores.
include /config/nginx/worker_processes.conf;

# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;

# Configures default error logger.
error_log /config/log/nginx/error.log;

# Includes files with directives to load dynamic modules.
include /etc/nginx/modules/*.conf;

# Include files with config snippets into the root context.
include /etc/nginx/conf.d/*.conf;

events {
    # The maximum number of simultaneous connections that can be opened by
    # a worker process.
    worker_connections 1024;
}

http {
    # Includes mapping of file name extensions to MIME types of responses
    # and defines the default type.
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Name servers used to resolve names of upstream servers into addresses.
    # It's also needed when using tcpsocket and udpsocket in Lua modules.
    #resolver 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001;
    include /config/nginx/resolver.conf;

    # Don't tell nginx version to the clients. Default is 'on'.
    server_tokens off;

    # Specifies the maximum accepted body size of a client request, as
    # indicated by the request header Content-Length. If the stated content
    # length is greater than this size, then the client receives the HTTP
    # error code 413. Set to 0 to disable. Default is '1m'.
    client_max_body_size 0;

    # Sendfile copies data between one FD and other from within the kernel,
    # which is more efficient than read() + write(). Default is off.
    sendfile on;

    # Causes nginx to attempt to send its HTTP response head in one packet,
    # instead of using partial frames. Default is 'off'.
    tcp_nopush on;

    # all ssl related config moved to ssl.conf
    include /config/nginx/ssl.conf;

    # Enable gzipping of responses.
    #gzip on;

    # Set the Vary HTTP header as defined in the RFC 2616. Default is 'off'.
    gzip_vary on;

    # Helper variable for proxying websockets.
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    # Sets the path, format, and configuration for a buffered log write.
    access_log /config/log/nginx/access.log;

    # Includes virtual hosts configs.
    include /etc/nginx/http.d/*.conf;
    include /config/nginx/site-confs/*.conf;
}

daemon off;
pid /run/nginx.pid;

I should mention that I have other Docker containers running successfully behind the proxy.

Information on your n8n setup

  • n8n version:1.34.2
  • Database: SQLite
  • n8n EXECUTIONS_PROCESS setting: Default
  • Running n8n via: Docker
  • Operating system:Unraid 6.12.8

THANKS FOR ANY HELP!

It looks like your topic is missing some important information. Could you provide the following if applicable.

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

hello @rayray14

Well, seems the N8N_PATH is not applied to some resources, but I don’t know if that is the intended behavior or not.

@Jon can you please look into it?

1 Like