I have a self-hosted n8n instance running in a Docker container behind an Nginx reverse proxy, managed with Portainer.
My setup works almost perfectly, but I’m encountering an issue with URL generation. When I click to access a workflow folder or any subfolder, the n8n UI duplicates the subpath in the URL.
For example, when I click on a folder, the URL becomes:
https://clinify.testex.org/n8n/n8n/projects/iaG2RtvsvYUbBhgq/folders/W8OIEkj6B2YQnVoY/workflows
The correct path should be:
https://clinify.testex.org/n8n/projects/iaG2RtvsvYUbBhgq/folders/W8OIEkj6B2YQnVoY/workflows
This only happens in the URLs of folders and subfolders. Other links seem to work fine.
What am I doing wrong in my configuration?
Nginx Configuration (nginx/default.conf)
server {
listen 80;
listen [::]:80;
server_name clinify.testex.org;
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
try_files $uri =404;
}
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name clinify.testex.org;
ssl_certificate /etc/letsencrypt/live/clinify.testex.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/clinify.testex.org/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# --- Configuração n8n ---
location /n8n/ {
# 'proxy_pass' para a porta interna do contêiner do n8n
proxy_pass http://n8n:5678/;
# Headers essenciais para proxy de WebSocket e informações do cliente
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
# Esta nova regra é crucial para rotear requisições como /rest/config.js para o n8n
# O `location` com regex `~ ^/n8n/(.*)$` é uma opção, mas o bloco anterior já é suficiente para as rotas da UI.
# Vamos adicionar uma regra mais específica para a API e os ativos estáticos que não usam o prefixo /n8n
location ~ ^/(rest|webhook|icons|js|css|img|fonts|templates|files)/ {
proxy_pass http://n8n: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;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Redirect para garantir que /n8n sempre vá para /n8n/
location = /n8n {
return 301 /n8n/;
}
}
Portainer Stack (docker-compose.yml)
# --- Definição dos Serviços ---
services:
# --- Redis Service (Cache e Fila) ---
# --- n8n Service (Automação de Workflows) ---
n8n:
image: n8nio/n8n
container_name: app_n8n
restart: always
ports:
- "5678:5678"
environment:
# --- Configurações Gerais e de Performance ---
N8N_TELEMETRY_ENABLED: false
NODE_ENV: production
GENERIC_TIMEZONE: America/Sao_Paulo
TZ: America/Sao_Paulo
N8N_PAYLOAD_SIZE_MAX: 16384
N8N_FORMDATA_FILE_SIZE_MAX: 16384
# NODE_FUNCTION_ALLOW_EXTERNAL: luxon
NODE_FUNCTION_ALLOW_EXTERNAL: luxon, moment,lodash,moment-with-locales
N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE: true
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: true
# --- Configurações de Acesso e URL (ESSENCIAL) ---
N8N_HOST: clinify.testex.org
N8N_PORT: 5678
N8N_PROTOCOL: https
N8N_PATH: /n8n/
N8N_EDITOR_BASE_URL: https://clinify.testex.org/n8n/
WEBHOOK_URL: https://clinify.testex.org/n8n/
N8N_SECURE_COOKIE: false # Mantenha 'false' se o Nginx gerencia o SSL e o n8n está em HTTP internamente
VUE_APP_URL_BASE_API: https://clinify.testex.org/n8n/
# --- Autenticação (ATENÇÃO: Login duplo ativado) ---
N8N_USER_MANAGEMENT_ENABLED: true
N8N_BASIC_AUTH_ACTIVE: true # Isso ativa um popup de login ANTES da tela de login do n8n. Considere desativar (false).
N8N_BASIC_AUTH_USER: admin
N8N_BASIC_AUTH_PASSWORD: 12345678 # <<<< MUDE ESTA SENHA!
# --- Conexão com Banco de Dados PostgreSQL ---
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: clinify_db
DB_POSTGRESDB_USER: clinify_user
DB_POSTGRESDB_PASSWORD: 123456 # <<<< USE A MESMA SENHA DO POSTGRES!
# --- Conexão com Redis para Filas (Modo Produção) ---
QUEUE_HEALTH_CHECK_ACTIVE: 'true'
QUEUE_REDIS_HOST: redis
QUEUE_REDIS_PORT: 6379
QUEUE_REDIS_PASSWORD: 1234 # <<<< USE A MESMA SENHA DO REDIS!
# --- Integração Langsmith (Opcional) ---
LANGSMITH_TRACING: 'true'
LANGSMITH_ENDPOINT: "https://api.smith.langchain.com"
LANGSMITH_API_KEY: "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"
LANGSMITH_PROJECT: "pr-puzzled-macrame-100"
volumes:
- n8n_data:/home/node/.n8n
networks:
- clinify_network
depends_on:
- redis
- postgres
# --- Nginx Service (Proxy Reverso e Servidor Web) ---
nginx:
image: nginx:latest
container_name: app_nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Mapeamento dos arquivos de configuração e certificados do Nginx
- /home/ubuntu/clinify-stack/nginx_config:/etc/nginx/conf.d
- /home/ubuntu/clinify-stack/nginx_html:/usr/share/nginx/html
- /etc/letsencrypt:/etc/letsencrypt:ro
networks:
- clinify_network
depends_on:
- n8n
- evolution-api
Information on your n8n setup
- n8n version: 1.104.2
- Database: Postgres
- Running n8n via: docker with portainer
- Operating system: Ubuntu 24.04