# n8n behind Caddy with automatic HTTPS, set up so the Telegram Trigger can register its webhook.
# From unboxth.xyz: /ai-automation/n8n-telegram-trigger-not-working/  (checked on 4 Nov 2026)
#
# Before you start:
#   1. Point a DNS A record for n8n.example.com at this server's public IPv4 address
#      (Telegram webhooks need IPv4; IPv6-only will not work).
#   2. Open ports 80 and 443 in your firewall. Caddy uses 80 to get the certificate and
#      serves n8n on 443, which is one of the four ports Telegram accepts (443, 80, 88, 8443).
#   3. Replace every n8n.example.com and the timezone below, then run:  docker compose up -d
#   4. Open https://n8n.example.com, then publish your Telegram workflow again so n8n
#      registers the new https webhook URL with Telegram.
#
# Caddy gets and renews the TLS certificate on its own, passes WebSocket connections
# (which the editor's "Listen for test event" needs) and sets X-Forwarded-For/-Host/-Proto.

services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    command: caddy reverse-proxy --from n8n.example.com --to n8n:5678
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - n8n

  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    # Not published to the internet; only Caddy talks to it.
    expose:
      - "5678"
    environment:
      - N8N_HOST=n8n.example.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      # The public base URL n8n hands to Telegram in setWebhook. Must be https, no :5678.
      # N8N_WEBHOOK_URL is the current name; WEBHOOK_URL is the older name (deprecated from
      # n8n 2.35.0 but still read as an alias). Keeping both identical works on old and new versions;
      # newer versions log a deprecation warning for WEBHOOK_URL, which you can then delete.
      - N8N_WEBHOOK_URL=https://n8n.example.com/
      - WEBHOOK_URL=https://n8n.example.com/
      # One reverse proxy (Caddy) sits in front of n8n.
      - N8N_PROXY_HOPS=1
      - GENERIC_TIMEZONE=America/Toronto
      - TZ=America/Toronto
      - NODE_ENV=production
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  caddy_data:
  caddy_config:
  n8n_data:

# ---------------------------------------------------------------------------
# Prefer a Caddyfile? Replace the caddy "command:" line with a mount:
#     volumes:
#       - ./Caddyfile:/etc/caddy/Caddyfile
#       - caddy_data:/data
#       - caddy_config:/config
# and put this in ./Caddyfile:
#
#   n8n.example.com {
#       reverse_proxy n8n:5678
#   }
#
# Using Traefik or nginx instead? You need the same three things: TLS on 443 with a
# full certificate chain, WebSocket upgrade headers passed through, and the
# X-Forwarded-For / X-Forwarded-Host / X-Forwarded-Proto headers set on the last proxy.
# ---------------------------------------------------------------------------
