|
|
|
@@ -0,0 +1,77 @@
|
|
|
|
|
# Managed by Ansible — do not edit manually
|
|
|
|
|
services:
|
|
|
|
|
n8n:
|
|
|
|
|
image: n8nio/n8n:{{ n8n_version }}
|
|
|
|
|
container_name: n8n
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
environment:
|
|
|
|
|
N8N_HOST: "{{ domain_n8n }}"
|
|
|
|
|
N8N_PROTOCOL: "https"
|
|
|
|
|
N8N_PORT: "5678"
|
|
|
|
|
# Public URL used to build webhook / chat links behind Traefik
|
|
|
|
|
WEBHOOK_URL: "https://{{ domain_n8n }}/"
|
|
|
|
|
N8N_PROXY_HOPS: "1"
|
|
|
|
|
N8N_ENCRYPTION_KEY: "{{ n8n_encryption_key }}"
|
|
|
|
|
GENERIC_TIMEZONE: "{{ n8n_timezone }}"
|
|
|
|
|
TZ: "{{ n8n_timezone }}"
|
|
|
|
|
N8N_DIAGNOSTICS_ENABLED: "false"
|
|
|
|
|
N8N_VERSION_NOTIFICATIONS_ENABLED: "false"
|
|
|
|
|
N8N_TEMPLATES_ENABLED: "false"
|
|
|
|
|
# Keep the SQLite database small: drop execution history after 7 days
|
|
|
|
|
EXECUTIONS_DATA_PRUNE: "true"
|
|
|
|
|
EXECUTIONS_DATA_MAX_AGE: "168"
|
|
|
|
|
volumes:
|
|
|
|
|
- {{ n8n_data_dir }}/data:/home/node/.n8n
|
|
|
|
|
# Workflows and credentials imported by Ansible (see roles/n8n/tasks/main.yml)
|
|
|
|
|
- {{ n8n_data_dir }}/import:/import:ro
|
|
|
|
|
mem_limit: {{ n8n_mem_limit }}
|
|
|
|
|
networks:
|
|
|
|
|
- traefik_public
|
|
|
|
|
- ollama_internal
|
|
|
|
|
- browserless_internal
|
|
|
|
|
- searxng_internal
|
|
|
|
|
labels:
|
|
|
|
|
- "traefik.enable=true"
|
|
|
|
|
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
|
|
|
|
|
# Editor, webhooks and chat page — all behind basic auth
|
|
|
|
|
- "traefik.http.routers.n8n.rule=Host(`{{ domain_n8n }}`)"
|
|
|
|
|
- "traefik.http.routers.n8n.entrypoints=websecure"
|
|
|
|
|
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
|
|
|
|
|
- "traefik.http.routers.n8n.service=n8n"
|
|
|
|
|
- "traefik.http.routers.n8n.middlewares=n8n-auth"
|
|
|
|
|
# Short link: /chat redirects to the hosted chat page of the chat workflow
|
|
|
|
|
- "traefik.http.routers.n8n-chat.rule=Host(`{{ domain_n8n }}`) && Path(`/chat`)"
|
|
|
|
|
- "traefik.http.routers.n8n-chat.priority=100"
|
|
|
|
|
- "traefik.http.routers.n8n-chat.entrypoints=websecure"
|
|
|
|
|
- "traefik.http.routers.n8n-chat.tls.certresolver=letsencrypt"
|
|
|
|
|
- "traefik.http.routers.n8n-chat.service=n8n"
|
|
|
|
|
- "traefik.http.routers.n8n-chat.middlewares=n8n-auth,n8n-chat-redirect"
|
|
|
|
|
- "traefik.http.middlewares.n8n-chat-redirect.redirectregex.regex=^https://{{ domain_n8n | replace('.', '\\\\.') }}/chat/?$$"
|
|
|
|
|
- "traefik.http.middlewares.n8n-chat-redirect.redirectregex.replacement=https://{{ domain_n8n }}/webhook/{{ n8n_chat_webhook_id }}/chat"
|
|
|
|
|
# Telegram bot webhook: called by Telegram's servers, so no basic auth. Restricted to Telegram's
|
|
|
|
|
# address ranges; n8n additionally checks Telegram's secret token header and the workflow
|
|
|
|
|
# only answers the user id in telegram_user_id.
|
|
|
|
|
- "traefik.http.routers.n8n-telegram.rule=Host(`{{ domain_n8n }}`) && Path(`/webhook/{{ n8n_telegram_webhook_id }}/webhook`) && Method(`POST`)"
|
|
|
|
|
- "traefik.http.routers.n8n-telegram.priority=200"
|
|
|
|
|
- "traefik.http.routers.n8n-telegram.entrypoints=websecure"
|
|
|
|
|
- "traefik.http.routers.n8n-telegram.tls.certresolver=letsencrypt"
|
|
|
|
|
- "traefik.http.routers.n8n-telegram.service=n8n"
|
|
|
|
|
{% if telegram_webhook_source_ranges | length > 0 %}
|
|
|
|
|
- "traefik.http.routers.n8n-telegram.middlewares=n8n-telegram-ips"
|
|
|
|
|
- "traefik.http.middlewares.n8n-telegram-ips.ipallowlist.sourcerange={{ telegram_webhook_source_ranges | join(',') }}"
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% set ns = namespace(entries=[]) %}
|
|
|
|
|
{% for user in n8n_users %}
|
|
|
|
|
{% set ns.entries = ns.entries + [user.username + ':' + (user.password | password_hash('bcrypt', (user.username | hash('md5'))[:22]) | replace('$', '$$'))] %}
|
|
|
|
|
{% endfor %}
|
|
|
|
|
- "traefik.http.middlewares.n8n-auth.basicauth.users={{ ns.entries | join(',') }}"
|
|
|
|
|
|
|
|
|
|
networks:
|
|
|
|
|
traefik_public:
|
|
|
|
|
external: true
|
|
|
|
|
ollama_internal:
|
|
|
|
|
external: true
|
|
|
|
|
browserless_internal:
|
|
|
|
|
external: true
|
|
|
|
|
searxng_internal:
|
|
|
|
|
external: true
|