Describe the problem/error/question
I am trying to run two task runner one for JS and one for Py and I could manage to write this compose file but there are some issue
- I am not able to run any JS code as node inside of any workflow. No matter what JS code is. IT just loading and loading
- Despite I define N8N_RUNNERS_AUTH_TOKEN_FILE in my secrets, it is not picking it up and log shows key not found, generating a new key….
- When I had one external task runner, I has first two error but when I seperate JS and Py , I cant even run it. container crashes
I am using ubuntu server 24 and portainer CE to manage. also nginx for reverse proxy.
When I use task runner mode internal, I have absolutely no issue which means my server and docker and nginx is totally ok and there is an issue with the compose file
Please share your workflow
version: "3.9" # Compose schema version (Swarm-compatible)
###############################################################################
# Overlay network (attachable so future services/containers can join)
###############################################################################
networks:
ap_net: # Name of the overlay network for this stack
driver: overlay # Use Swarm overlay networking
attachable: true # Allow other services/containers to attach later
###############################################################################
# Persistent named volumes (Swarm will create these on the node)
###############################################################################
volumes:
n8n_data: # n8n user data, binaries, credentials, etc.
pg_data: # PostgreSQL database cluster (data directory)
shared_files: # Shared “drive” mounted into n8n at /data/share
###############################################################################
# External Docker Secrets (create these in Portainer before deploying)
# Keep real values OUT of Git. Marked external so the stack references them.
###############################################################################
secrets:
n8n_encryption_key: { external: true } # Symmetric key for encrypting creds in n8n
n8n_runners_auth_token: { external: true } # Shared token for broker<->runner auth
db_database: { external: true } # Database name (e.g., n8n)
db_user: { external: true } # Database user (e.g., n8n)
db_password: { external: true } # Database password (strong)
###############################################################################
# Services
###############################################################################
services:
###########################################################################
# PostgreSQL (database)
###########################################################################
postgres:
image: postgres:18-alpine # Lightweight Postgres
networks: [ap_net] # Internal overlay net
volumes:
- pg_data:/var/lib/postgresql/data # Persist DB files
environment: # Use *_FILE to read secrets at runtime
POSTGRES_DB_FILE: /run/secrets/db_database
POSTGRES_USER_FILE: /run/secrets/db_user
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets: # Mount only needed secrets
- db_database
- db_user
- db_password
ports: # Optional: publish DB for pgAdmin
- target: 5432 # Container port (Postgres default)
published: 15432 # Host port (adjust as desired)
protocol: tcp
mode: host # Bind on this node only (no ingress mesh)
deploy:
restart_policy: { condition: on-failure }
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$(cat /run/secrets/db_user)"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
###########################################################################
# n8n (editor + API + broker for task runners)
###########################################################################
n8n:
image: n8nio/n8n:1.117.3 # Fixed n8n version
networks: [ap_net] # Internal overlay net
volumes:
- n8n_data:/home/node/.n8n # Persist n8n home (workflows, creds)
- shared_files:/data/share # Shared “drive” for users
ports: # Publish editor/API to host for Nginx
- target: 5678 # Container port (n8n HTTP)
published: 5678 # Host port for Nginx proxy_pass
protocol: tcp
mode: host # Bind on this node (no ingress mesh)
environment:
# -------------------- URLs (TLS terminated by Nginx) -------------------
N8N_HOST: n8n.example.com # Public host used in generated links
N8N_PORT: 5678 # Container’s HTTP port
N8N_PROTOCOL: https # Generate https:// links
N8N_LISTEN_ADDRESS: 0.0.0.0 # Listen on all interfaces
WEBHOOK_URL: https://n8n.example.com/
N8N_EDITOR_BASE_URL: https://n8n.example.com/
VUE_APP_URL_BASE_API: https://n8n.example.com/
# --------------------------- Security ----------------------------------
N8N_TRUST_PROXY: "true"
N8N_PROXY_HOPS: "1"
NODE_ENV: production
TZ: UTC
N8N_BLOCK_ENV_ACCESS_IN_NODE: "true"
N8N_SECURE_COOKIE: "false"
N8N_SESSION_COOKIE_SAMESITE: lax
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: "true" # Enforce secure perms for config file
N8N_DIAGNOSTICS_ENABLED: "false"
N8N_GIT_NODE_DISABLE_BARE_REPOS: "true"
N8N_ENCRYPTION_KEY_FILE: /run/secrets/n8n_encryption_key
# --------------------------- Task Runners (broker) ---------------------
N8N_RUNNERS_ENABLED: "true" # Enable task runners [2]
N8N_RUNNERS_MODE: external # External runner processes [2]
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0 # Broker bind address [1][2]
N8N_RUNNERS_BROKER_PORT: 5679 # Broker WebSocket port [1][2]
N8N_RUNNERS_AUTH_TOKEN_FILE: /run/secrets/n8n_runners_auth_token # Broker<->runner token [2]
N8N_PUSH_BACKEND: websocket # Enable realtime collaboration via WS [1]
N8N_NATIVE_PYTHON_RUNNER: "true"
# ----------------------------- Database --------------------------------
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE_FILE: /run/secrets/db_database
DB_POSTGRESDB_USER_FILE: /run/secrets/db_user
DB_POSTGRESDB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- n8n_encryption_key
- n8n_runners_auth_token
- db_database
- db_user
- db_password
depends_on: [postgres]
deploy:
restart_policy: { condition: on-failure }
healthcheck:
test: ["CMD-SHELL", "node -e \"require('http').get('http://localhost:5678/healthz',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))\""]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
###########################################################################
# n8n runner (JavaScript) – executes JS tasks, connects to the broker
# This image tag has no 'task-runner' CLI; start the process script directly.
###########################################################################
n8n_runner_js:
image: n8nio/n8n:1.117.3 # Same version for compatibility
networks: [ap_net]
entrypoint: ["/usr/local/bin/node", "/usr/local/lib/node_modules/n8n/dist/task-runners/task-runner-process-js.js"] # JS runner process
environment:
N8N_RUNNERS_ENABLED: "true" # Enable runner mode [2]
N8N_RUNNERS_MODE: external # External runner connects to broker [2]
N8N_RUNNERS_TASK_BROKER_URI: ws://n8n:5679 # Runner connects here (WS URI) [2]
N8N_RUNNERS_AUTH_TOKEN_FILE: /run/secrets/n8n_runners_auth_token
N8N_LOG_LEVEL: debug
# ----------------------------- Database (same as main) -----------------
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE_FILE: /run/secrets/db_database
DB_POSTGRESDB_USER_FILE: /run/secrets/db_user
DB_POSTGRESDB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- n8n_runners_auth_token
- db_database
- db_user
- db_password
depends_on: [n8n]
deploy:
restart_policy: { condition: on-failure }
###########################################################################
# Optional: n8n runner (Python) – executes Python tasks
# Enable only if you want a dedicated Python runner alongside JS.
###########################################################################
n8n_runner_py:
image: n8nio/n8n:1.117.3
networks: [ap_net]
entrypoint: ["/usr/local/bin/node", "/usr/local/lib/node_modules/n8n/dist/task-runners/task-runner-process-py.js"] # Python runner process
environment:
N8N_RUNNERS_ENABLED: "true"
N8N_RUNNERS_MODE: external
N8N_RUNNERS_TASK_BROKER_URI: ws://n8n:5679
N8N_RUNNERS_AUTH_TOKEN_FILE: /run/secrets/n8n_runners_auth_token
N8N_LOG_LEVEL: debug
# # Database
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE_FILE: /run/secrets/db_database
DB_POSTGRESDB_USER_FILE: /run/secrets/db_user
DB_POSTGRESDB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- n8n_runners_auth_token
- db_database
- db_user
- db_password
depends_on: [n8n]
deploy:
restart_policy: { condition: on-failure }
Information on your n8n setup
- n8n version: 1.117.3
- Database (default: SQLite): Postgres
- n8n EXECUTIONS_PROCESS setting (default: own, main): default
- Running n8n via (Docker, npm, n8n cloud, desktop app): Portainer, docker swarm
- Operating system: Ubuntu server 24
