# yaml-language-server: $schema=https://schema.zeabur.app/template.json
apiVersion: zeabur.com/v1
kind: Template
metadata:
    name: N8N v2 with Worker & Task Runners
spec:
    description: N8N v2 workflow automation with worker and external task runners for secure code execution
    coverImage: https://i.imgur.com/Hm4GdsP.png
    icon: https://i.imgur.com/KUcP61Z.png
    variables:
        - key: PUBLIC_DOMAIN
          type: DOMAIN
          name: Domain
          description: What is the domain you want for your N8N instance?
    tags:
        - Automation
        - Workflow
        - N8N v2
        - Task Runners
        - Code Execution
    readme: "# N8N v2 with Worker & Task Runners (create by SEAFOODHOLDHAND)\n\n[![N8N with Worker](https://i.imgur.com/gi4FDrn.png)](https://www.youtube.com/@seafoodholdhand)\n\n**N8N v2** is a powerful workflow automation platform that helps you connect different services and automate tasks. This template includes:\n\n- **N8N v2 main instance** for workflow management (latest version)\n- **N8N worker** for processing background tasks\n- **External Task Runners** for secure Code node execution (production-ready setup)\n- **PostgreSQL** database for data storage\n- **Redis** for queue management\n\n## Why External Task Runners?\n\nThis template uses **external task runners** - N8N's recommended production setup for executing code in Code nodes:\n\n- **\U0001F512 Enhanced Security**: Code runs in isolated containers, separate from your main N8N instance\n- **⚡ Better Performance**: Task runners can scale independently based on workload\n- **\U0001F6E1️ Sandboxed Execution**: JavaScript and Python code execute in controlled environments\n- **\U0001F504 Auto-Shutdown**: Idle runners automatically shut down after 15 seconds to save resources\n- **\U0001F4CA Production Ready**: Follows N8N's best practices for production deployments\n\nWith N8N v2, you can:\n- Create automated workflows with the visual editor\n- Connect to hundreds of services and APIs\n- Execute custom JavaScript and Python code securely in Code nodes\n- Process data and automate tasks with reliable background workers\n- Handle webhook-triggered workflows efficiently\n\nThe worker + task runner setup ensures your automation tasks are processed reliably and securely.\n\n## Update Log\n\n### 2026-08-02\n- **Removed N8N-Runners service**: With `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true` + queue mode, the main N8N instance never starts a task broker on port 5679 — all executions (manual and production) are offloaded to the Worker. N8N-Runners was permanently stuck on \"Waiting for task broker to be ready\" and served no purpose. Also removed the `taskbroker` port (5679) and `N8N_RUNNERS_BROKER_LISTEN_ADDRESS` from the N8N service. Only Worker-Runners remains (the Worker does run a broker).\n- **Fixed Code node execution (Worker-Runners)**: Changed Worker-Runners `N8N_RUNNERS_TASK_BROKER_URI` from `http://Worker:5679` to `http://${WORKER_BROKER_HOST}:5679`. Zeabur's in-cluster DNS resolves `service-<id>` hostnames, not bare service names like `Worker` — runners were stuck on \"Waiting for task broker to be ready\" indefinitely, and Code nodes timed out after 60 seconds. The Worker service now exposes its internal hostname (`WORKER_BROKER_HOST`) via `${CONTAINER_HOSTNAME}` for the runner to consume. (`N8N_RUNNERS_ENABLED` is deprecated in n8n v2 and intentionally not set — see [docs](https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners).)\n- **Fixed \"Invalid URL\" error on every node execution**: Added `N8N_PROTOCOL=https` to both N8N and Worker. n8n builds `$execution.resumeUrl` from `${N8N_PROTOCOL}://${N8N_HOST}/...`; without the protocol, the URL is malformed and every node (Set, Switch, Code, etc.) throws `TypeError: Invalid URL`.\n- **Fixed Worker webhook URL resolution**: The Worker service has no domain binding of its own, so `${ZEABUR_WEB_DOMAIN}` / `${ZEABUR_WEB_URL}` are unset in its container. Now consumes `${N8N_WEBHOOK_HOST}` / `${N8N_WEBHOOK_URL}` (newly exposed by the N8N service) for `N8N_HOST` and `WEBHOOK_URL`.\n\n### 2026-07-31\n- Added healthChecks to PostgreSQL, Redis, N8N, and Worker so services wait for their dependencies before starting (no more startup race)\n- Upgraded PostgreSQL to 18 (`postgres:18` — volume now mounts at `/var/lib/postgresql` for the new data-dir layout)\n- The N8N encryption key is no longer shown in the deploy instructions (kept secret — anyone holding it can decrypt all workflow credentials; find it under the N8N service's environment variables if you ever need it)\n- Removed the stale `TASK_RUNNERS_AUTH_TOKEN` variable from the localized setup screens (the token is auto-generated and shared between services automatically)\n\n### 2026-03-23\n- Fixed service dependencies placement to comply with Zeabur template schema (moved from inside `spec` to service level), ensuring correct startup ordering\n- Removed deprecated `N8N_RUNNERS_ENABLED` environment variable (task runners are enabled by default in N8N v2)\n- **Fixed task runner architecture**: Split single `Runners` into `N8N-Runners` (connects to `http://N8N:5679`) and `Worker-Runners` (connects to `http://Worker:5679`), matching the official n8n docker-compose setup where each n8n instance needs its own dedicated runner\n\n### 2025-12-28\n- **IMPORTANT**: Template updated for N8N v2 compatibility\n- Upgraded to external task runners (production-recommended setup)\n- Added separate `task-runners` service as a sidecar to n8n-worker\n- Configured `N8N_RUNNERS_MODE=external` for better security and performance\n- Task runners now execute Code node JavaScript/Python code in isolated containers\n- Added `TASK_RUNNERS_AUTH_TOKEN` variable for secure broker-runner authentication\n\nThis update ensures your N8N v2 workflows run securely with external task runners, following N8N's best practices for production deployments.\n\n### 2025-03-17\n- Fixed N8N_ENCRYPTION_KEY mismatch between n8n main instance and worker\n- Ensured worker uses the same encryption key as main instance for improved system stability\n- Added ability to manually set `N8N_ENCRYPTION_KEY` for both main instance and workers\n\n⚠️ Important: If you're using a previous version of this template, please update to this version to avoid potential encryption key synchronization issues.\n\nNote: This template enables critical environment variables to prevent future compatibility issues:\n\n- `N8N_RUNNERS_MODE=external`: Uses external task runner containers (recommended for production) instead of internal child processes.\n\n- `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true`: Running manual executions in the main instance in scaling mode is deprecated. Manual executions will be routed to workers in a future version. This setting prepares your deployment for this change.\n\nLearn more about task runners: https://docs.n8n.io/hosting/configuration/task-runners/\n\nThis template has been logically designed and tested to work successfully. As a nocode user, I welcome any suggestions or improvements on GitHub. I'll do my best to update the template (with AI's help) since I'm not very familiar with GitHub.\n\nIf you encounter any issues during deployment, please let me know via GitHub issues:\n[https://github.com/glasschan/seafoodholdhand-zeabur-templates](https://github.com/glasschan/seafoodholdhand-zeabur-templates)"
    services:
        - name: PostgreSQL
          icon: https://raw.githubusercontent.com/zeabur/service-icons/main/marketplace/postgresql.svg
          template: PREBUILT_V2
          spec:
            id: postgresql
            source:
                image: postgres:18
                command:
                    - docker-entrypoint.sh
                    - -c
                    - config_file=/etc/postgresql/postgresql.conf
            ports:
                - id: database
                  port: 5432
                  type: TCP
            volumes:
                - id: data
                  dir: /var/lib/postgresql
            instructions:
                - title: Connection String
                  content: postgresql://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/${POSTGRES_DATABASE}
                - title: PostgreSQL Connect Command
                  content: psql "postgresql://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/${POSTGRES_DATABASE}"
                - title: PostgreSQL username
                  content: ${POSTGRES_USERNAME}
                - title: PostgresSQL password
                  content: ${POSTGRES_PASSWORD}
                - title: PostgresSQL database
                  content: ${POSTGRES_DATABASE}
                - title: PostgreSQL host
                  content: ${PORT_FORWARDED_HOSTNAME}
                - title: PostgreSQL port
                  content: ${DATABASE_PORT_FORWARDED_PORT}
            env:
                POSTGRES_CONNECTION_STRING:
                    default: postgresql://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DATABASE}
                    expose: false
                POSTGRES_DATABASE:
                    default: ${POSTGRES_DB}
                    expose: true
                POSTGRES_DB:
                    default: zeabur
                    expose: true
                POSTGRES_HOST:
                    default: ${CONTAINER_HOSTNAME}
                    expose: true
                POSTGRES_PASSWORD:
                    default: ${PASSWORD}
                    expose: true
                POSTGRES_PORT:
                    default: ${DATABASE_PORT}
                    expose: true
                POSTGRES_URI:
                    default: ${POSTGRES_CONNECTION_STRING}
                    expose: true
                POSTGRES_USER:
                    default: root
                    expose: false
                POSTGRES_USERNAME:
                    default: ${POSTGRES_USER}
                    expose: true
            configs:
                - path: /etc/postgresql/postgresql.conf
                  template: |
                    # https://github.com/postgres/postgres/blob/master/src/backend/utils/misc/postgresql.conf.sample
                    listen_addresses = '*'
                    max_connections = 100
                    shared_buffers = 128MB
                    dynamic_shared_memory_type = posix
                    max_wal_size = 1GB
                    min_wal_size = 80MB
                    log_timezone = 'Etc/UTC'
                    datestyle = 'iso, mdy'
                    timezone = 'Etc/UTC'
                    lc_messages = 'en_US.utf8'
                    lc_monetary = 'en_US.utf8'
                    lc_numeric = 'en_US.utf8'
                    lc_time = 'en_US.utf8'
                    default_text_search_config = 'pg_catalog.english'
                  permission: null
                  envsubst: null
            healthCheck:
                type: TCP
                port: database
        - name: N8N
          icon: https://i.imgur.com/KUcP61Z.png
          dependencies:
            - PostgreSQL
            - Redis
          template: PREBUILT_V2
          spec:
            id: n8n
            source:
                image: n8nio/n8n:stable
            ports:
                - id: web
                  port: 5678
                  type: HTTP
            volumes:
                - id: data
                  dir: /root/.n8n
            instructions:
                - title: N8N ENCRYPTION KEY (auto-generated, kept secret)
                  content: '***'
                - title: N8N RUNNERS AUTH TOKEN
                  content: ${N8N_RUNNERS_AUTH_TOKEN}
            env:
                DB_POSTGRESDB_DATABASE:
                    default: ${POSTGRES_DB}
                    expose: false
                DB_POSTGRESDB_HOST:
                    default: ${POSTGRES_HOST}
                    expose: false
                DB_POSTGRESDB_PASSWORD:
                    default: ${POSTGRES_PASSWORD}
                    expose: false
                DB_POSTGRESDB_PORT:
                    default: ${POSTGRES_PORT}
                    expose: false
                DB_POSTGRESDB_USER:
                    default: ${POSTGRES_USERNAME}
                    expose: false
                DB_TYPE:
                    default: postgresdb
                    expose: false
                EXECUTIONS_MODE:
                    default: queue
                    expose: false
                N8N_ENCRYPTION_KEY:
                    default: ${PASSWORD}
                    expose: false
                N8N_ENCRYPTION_KEY_WORKER:
                    default: ${N8N_ENCRYPTION_KEY}
                    expose: true
                N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS:
                    default: "true"
                    expose: false
                N8N_HOST:
                    default: ${ZEABUR_WEB_DOMAIN}
                    expose: false
                N8N_PROTOCOL:
                    default: https
                    expose: false
                N8N_RUNNERS_AUTH_TOKEN:
                    default: ${PASSWORD}
                    expose: false
                N8N_RUNNERS_MODE:
                    default: external
                    expose: false
                N8N_WEBHOOK_HOST:
                    default: ${ZEABUR_WEB_DOMAIN}
                    expose: true
                N8N_WEBHOOK_URL:
                    default: ${ZEABUR_WEB_URL}
                    expose: true
                NODE_ENV:
                    default: production
                    expose: false
                OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS:
                    default: "true"
                    expose: false
                QUEUE_BULL_REDIS_HOST:
                    default: ${REDIS_HOST}
                    expose: false
                QUEUE_BULL_REDIS_PASSWORD:
                    default: ${REDIS_PASSWORD}
                    expose: false
                QUEUE_BULL_REDIS_PORT:
                    default: ${REDIS_PORT}
                    expose: false
                TASK_RUNNERS_AUTH_TOKEN:
                    default: ${N8N_RUNNERS_AUTH_TOKEN}
                    expose: true
            configs: []
            healthCheck:
                type: TCP
                port: web
          domainKey: PUBLIC_DOMAIN
        - name: Redis
          icon: https://raw.githubusercontent.com/zeabur/service-icons/main/marketplace/redis.svg
          template: PREBUILT_V2
          spec:
            id: redis
            source:
                image: redis:7-alpine
            ports:
                - id: database
                  port: 6379
                  type: TCP
            volumes:
                - id: data
                  dir: /data
            instructions:
                - title: Command to connect to your Redis
                  content: redis-cli -h ${PORT_FORWARDED_HOSTNAME} -p ${DATABASE_PORT_FORWARDED_PORT} -a ${REDIS_PASSWORD}
                - title: Redis Connection String
                  content: redis://:${REDIS_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}
                - title: Redis password
                  content: ${REDIS_PASSWORD}
                - title: Redis host
                  content: ${PORT_FORWARDED_HOSTNAME}
                - title: Redis port
                  content: ${DATABASE_PORT_FORWARDED_PORT}
            env:
                REDIS_ARGS:
                    default: --requirepass ${REDIS_PASSWORD}
                    expose: false
                REDIS_CONNECTION_STRING:
                    default: redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}
                    expose: true
                REDIS_HOST:
                    default: ${CONTAINER_HOSTNAME}
                    expose: true
                REDIS_PASSWORD:
                    default: ${PASSWORD}
                    expose: true
                REDIS_PORT:
                    default: ${DATABASE_PORT}
                    expose: true
                REDIS_URI:
                    default: ${REDIS_CONNECTION_STRING}
                    expose: true
            configs: []
            healthCheck:
                type: TCP
                port: database
        - name: Worker
          icon: https://i.imgur.com/KUcP61Z.png
          dependencies:
            - N8N
            - PostgreSQL
            - Redis
          template: PREBUILT_V2
          spec:
            id: worker
            source:
                image: n8nio/n8n:stable
                command:
                    - /bin/sh
                args:
                    - -c
                    - n8n worker
            ports:
                - id: taskbroker
                  port: 5679
                  type: TCP
            volumes:
                - id: data
                  dir: /root/.n8n
            env:
                DB_POSTGRESDB_DATABASE:
                    default: ${POSTGRES_DB}
                    expose: false
                DB_POSTGRESDB_HOST:
                    default: ${POSTGRES_HOST}
                    expose: false
                DB_POSTGRESDB_PASSWORD:
                    default: ${POSTGRES_PASSWORD}
                    expose: false
                DB_POSTGRESDB_PORT:
                    default: ${POSTGRES_PORT}
                    expose: false
                DB_POSTGRESDB_USER:
                    default: ${POSTGRES_USERNAME}
                    expose: false
                DB_TYPE:
                    default: postgresdb
                    expose: false
                EXECUTIONS_MODE:
                    default: queue
                    expose: false
                N8N_ENCRYPTION_KEY:
                    default: ${N8N_ENCRYPTION_KEY_WORKER}
                    expose: false
                N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS:
                    default: "true"
                    expose: false
                N8N_HOST:
                    default: ${N8N_WEBHOOK_HOST}
                    expose: false
                N8N_PROTOCOL:
                    default: https
                    expose: false
                N8N_RUNNERS_AUTH_TOKEN:
                    default: ${TASK_RUNNERS_AUTH_TOKEN}
                    expose: false
                N8N_RUNNERS_BROKER_LISTEN_ADDRESS:
                    default: 0.0.0.0
                    expose: false
                N8N_RUNNERS_MODE:
                    default: external
                    expose: false
                N8N_WEBHOOK_URL:
                    default: ${N8N_WEBHOOK_URL}
                    expose: false
                NODE_ENV:
                    default: production
                    expose: false
                OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS:
                    default: "true"
                    expose: false
                QUEUE_BULL_REDIS_HOST:
                    default: ${REDIS_HOST}
                    expose: false
                QUEUE_BULL_REDIS_PASSWORD:
                    default: ${REDIS_PASSWORD}
                    expose: false
                QUEUE_BULL_REDIS_PORT:
                    default: ${REDIS_PORT}
                    expose: false
                WORKER_BROKER_HOST:
                    default: ${CONTAINER_HOSTNAME}
                    expose: true
            configs: []
            healthCheck:
                type: TCP
                port: taskbroker
        - name: Worker-Runners
          icon: https://i.imgur.com/KUcP61Z.png
          dependencies:
            - Worker
          template: PREBUILT_V2
          spec:
            id: worker-runners
            source:
                image: n8nio/runners:stable
            env:
                N8N_RUNNERS_AUTH_TOKEN:
                    default: ${TASK_RUNNERS_AUTH_TOKEN}
                    expose: false
                N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT:
                    default: "15"
                    expose: false
                N8N_RUNNERS_TASK_BROKER_URI:
                    default: http://${WORKER_BROKER_HOST}:5679
                    expose: false
            configs: []
localization:
    ja-JP:
        description: N8N v2 ワークフロー自動化プラットフォーム。ワーカーと外部タスクランナーによる安全なコード実行を搭載
        variables:
            - key: PUBLIC_DOMAIN
              type: DOMAIN
              name: ドメイン
              description: N8N インスタンスに使用したいドメインは何ですか？
        readme: "# N8N v2 with Worker & Task Runners (create by SEAFOODHOLDHAND)\n\n[![N8N with Worker](https://i.imgur.com/gi4FDrn.png)](https://www.youtube.com/@seafoodholdhand)\n\n**N8N v2**は、異なるサービスを接続してタスクを自動化するのに役立つ強力なワークフロー自動化プラットフォームです。このテンプレートには以下が含まれます：\n\n- **N8N v2 メインインスタンス**（ワークフロー管理用、最新バージョン）\n- **N8N ワーカー**（バックグラウンドタスク処理用）\n- **外部タスクランナー**（Codeノードの安全な実行用、本番環境対応設定）\n- **PostgreSQL**（データストレージ用）\n- **Redis**（キュー管理用）\n\n## 外部タスクランナーを使用する理由\n\nこのテンプレートでは**外部タスクランナー**を使用しています - これはCodeノードでコードを実行するためのN8N推奨の本番環境設定です：\n\n- **\U0001F512 セキュリティ強化**：コードはメインのN8Nインスタンスから分離されたコンテナで実行されます\n- **⚡ パフォーマンス向上**：タスクランナーはワークロードに応じて独立してスケールできます\n- **\U0001F6E1️ サンドボックス実行**：JavaScriptとPythonコードは制御された環境で実行されます\n- **\U0001F504 自動シャットダウン**：アイドル状態のランナーは15秒後に自動的にシャットダウンしてリソースを節約\n- **\U0001F4CA 本番環境対応**：N8Nの本番デプロイのベストプラクティスに従っています\n\nN8N v2を使用すると、以下のことが可能です：\n- ビジュアルエディタで自動化されたワークフローを作成\n- 数百のサービスやAPIに接続\n- CodeノードでカスタムJavaScriptとPythonコードを安全に実行\n- 信頼性の高いバックグラウンドワーカーでデータを処理してタスクを自動化\n- Webhookトリガーのワークフローを効率的に処理\n\nワーカーとタスクランナーのセットアップにより、自動化タスクが確実かつ安全に処理されます。\n\n## アップデート履歴\n\n### 2026-08-02\n- **N8N-Runnersサービスを削除**：`OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true` + queueモードでは、メインN8Nインスタンスはポート5679のタスクブローカーを起動しません——全実行（手動・本番）はWorkerにオフロードされます。N8N-Runnersは「Waiting for task broker to be ready」で永久に停止し、無意味でした。N8Nサービスから `taskbroker` ポート（5679）と `N8N_RUNNERS_BROKER_LISTEN_ADDRESS` も削除しました。Worker-Runnersのみ残存（Workerはブローカーを実行します）。\n- **Codeノードの実行を修正（Worker-Runners）**：Worker-Runnersの `N8N_RUNNERS_TASK_BROKER_URI` を `http://Worker:5679` から `http://${WORKER_BROKER_HOST}:5679` に変更。Zeaburのクラスタ内DNSは `Worker` のようなベアサービス名ではなく `service-<id>` ホスト名を解決します——ランナーは「Waiting for task broker to be ready」で無限に停止し、Codeノードが60秒でタイムアウトしていました。Workerサービスは `${CONTAINER_HOSTNAME}` で内部ホスト名（`WORKER_BROKER_HOST`）を公開するようになりました。（`N8N_RUNNERS_ENABLED` はn8n v2で非推奨のため設定しません——[公式ドキュメント](https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners)を参照。）\n- **全ノード実行時の「Invalid URL」エラーを修正**：N8NとWorkerに `N8N_PROTOCOL=https` を追加。n8nは `${N8N_PROTOCOL}://${N8N_HOST}/...` から `$execution.resumeUrl` を構築します。プロトコルがないとURLが不正になり、全ノード（Set、Switch、Code等）が `TypeError: Invalid URL` をスローします。\n- **Workerのwebhook URL解決を修正**：Workerサービスには独自のドメインバインディングがないため、`${ZEABUR_WEB_DOMAIN}` / `${ZEABUR_WEB_URL}` がコンテナ内で未設定です。`N8N_HOST` と `WEBHOOK_URL` に `${N8N_WEBHOOK_HOST}` / `${N8N_WEBHOOK_URL}`（N8Nサービスで新しく公開）を使用するよう変更しました。\n\n### 2026-07-31\n- PostgreSQL、Redis、N8N、ワーカーに healthCheck を追加し、依存サービスが起動するまで待機するよう修正（起動時の競合を防止）\n- PostgreSQL を 18 にアップグレード（`postgres:18` — 新しい data-dir 構成のため、ボリュームは `/var/lib/postgresql` にマウント）\n- N8N 暗号化キーはデプロイ時の説明に表示されなくなりました（秘匿保持 — このキーがあればワークフロー内の認証情報を復号できます。必要な場合は N8N サービスの環境変数で確認できます）\n- ローカライズ設定画面から古い `TASK_RUNNERS_AUTH_TOKEN` 変数を削除（トークンは自動生成され、サービス間で自動共有されます）\n\n### 2026-03-23\n- サービス依存関係の配置を Zeabur テンプレートスキーマに準拠するよう修正（`spec` 内部からサービスレベルに移動）、正しい起動順序を確保\n- 非推奨の `N8N_RUNNERS_ENABLED` 環境変数を削除（N8N v2 ではタスクランナーがデフォルトで有効）\n- **タスクランナーアーキテクチャを修正**：単一の `Runners` を `N8N-Runners`（`http://N8N:5679` に接続）と `Worker-Runners`（`http://Worker:5679` に接続）に分割。公式 n8n docker-compose に準拠し、各 n8n インスタンスに専用の Runner を配備\n\n### 2025-12-28\n- **重要**：テンプレートをN8N v2対応に更新\n- 外部タスクランナーにアップグレード（本番環境推奨設定）\n- n8n-workerのサイドカーとして独立した `task-runners` サービスを追加\n- より良いセキュリティとパフォーマンスのために `N8N_RUNNERS_MODE=external` を設定\n- タスクランナーは、CodeノードのJavaScript/Pythonコードを分離されたコンテナで実行するようになりました\n- 安全なブローカー-ランナー認証のために `TASK_RUNNERS_AUTH_TOKEN` 変数を追加\n\nこのアップデートにより、N8N v2ワークフローが外部タスクランナーで安全に実行され、N8Nの本番デプロイのベストプラクティスに従うようになります。\n\n### 2025-03-17\n- n8nメインインスタンスとワーカー間のN8N_ENCRYPTION_KEYの不一致を修正\n- システムの安定性向上のため、ワーカーがメインインスタンスと同じ暗号化キーを使用するように確保\n- 手動設置 `N8N_ENCRYPTION_KEY` 的能力を追加し、主インスタンスとワーカーの暗号化キーを確保\n\n⚠️ 重要：このテンプレートの以前のバージョンをご使用の場合は、暗号化キーの同期の問題を避けるため、このバージョンへの更新をお願いします。\n\n注：このテンプレートは、将来の互換性の問題を防ぐために、重要な環境変数を有効化しています：\n\n- `N8N_RUNNERS_MODE=external`：内部子プロセスの代わりに外部タスクランナーコンテナを使用します（本番環境推奨）。\n\n- `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true`：スケーリングモードでのメインインスタンスでの手動実行は非推奨となっています。将来のバージョンでは、手動実行はワーカーにルーティングされます。この設定は、この変更に備えるものです。\n\nタスクランナーについて詳しく：https://docs.n8n.io/hosting/configuration/task-runners/\n\nデプロイ中に問題が発生した場合は、Github issue で教えてください。できる限り解決します：\n[https://github.com/glasschan/seafoodholdhand-zeabur-templates](https://github.com/glasschan/seafoodholdhand-zeabur-templates)"
    zh-CN:
        description: N8N v2 工作流自动化平台，配备工作进程和外部任务运行器以实现安全代码执行
        variables:
            - key: PUBLIC_DOMAIN
              type: DOMAIN
              name: 域名
              description: 你想将 N8N 绑定在哪个域名上？
        readme: "# N8N v2 搭配工作进程与任务运行器 (create by SEAFOODHOLDHAND)\n\n[![N8N with Worker](https://i.imgur.com/gi4FDrn.png)](https://www.youtube.com/@seafoodholdhand)\n\n**N8N v2** 是一个强大的工作流程自动化平台，可以帮助你连接不同的服务并自动化任务。此模板包含：\n\n- **N8N v2 主实例**用于工作流程管理（最新版本）\n- **N8N 工作进程**用于处理后台任务\n- **外部任务运行器**用于安全执行 Code 节点（生产环境就绪设置）\n- **PostgreSQL** 数据库用于数据存储\n- **Redis** 用于队列管理\n\n## 为什么使用外部任务运行器？\n\n此模板使用**外部任务运行器** - N8N 推荐的生产环境设置，用于在 Code 节点中执行代码：\n\n- **\U0001F512 增强安全性**：代码在隔离容器中运行，与主 N8N 实例分开\n- **⚡ 更佳性能**：任务运行器可以根据工作负载独立扩展\n- **\U0001F6E1️ 沙盒执行**：JavaScript 和 Python 代码在受控环境中执行\n- **\U0001F504 自动关闭**：闲置的运行器会在 15 秒后自动关闭以节省资源\n- **\U0001F4CA 生产就绪**：遵循 N8N 生产部署的最佳实践\n\n使用 N8N v2，你可以：\n- 使用可视化编辑器创建自动化工作流程\n- 连接数百种服务和 API\n- 在 Code 节点中安全地执行自定义 JavaScript 和 Python 代码\n- 使用可靠的后台工作进程处理数据并自动化任务\n- 高效处理 Webhook 触发的工作流程\n\n工作进程 + 任务运行器设置确保您的自动化任务得到可靠且安全的处理。\n\n## 更新日志\n\n### 2026-08-02\n- **移除 N8N-Runners 服务**：设置了 `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true` + queue 模式后，主 N8N 实例永不启动 5679 端口的任务代理——所有执行（手动和生产）都卸载至 Worker。N8N-Runners 一直卡在「Waiting for task broker to be ready」，毫无作用。同时从 N8N 服务移除了 `taskbroker` 端口（5679）和 `N8N_RUNNERS_BROKER_LISTEN_ADDRESS`。仅保留 Worker-Runners（Worker 确实运行代理）。\n- **修正 Code 节点执行（Worker-Runners）**：将 Worker-Runners 的 `N8N_RUNNERS_TASK_BROKER_URI` 从 `http://Worker:5679` 改为 `http://${WORKER_BROKER_HOST}:5679`。Zeabur 的集群内 DNS 解析的是 `service-<id>` 主机名，而非 `Worker` 这样的裸服务名——运行器一直卡在「Waiting for task broker to be ready」，Code 节点超时 60 秒。Worker 服务现在通过 `${CONTAINER_HOSTNAME}` 公开内部主机名（`WORKER_BROKER_HOST`）供运行器使用。（`N8N_RUNNERS_ENABLED` 在 n8n v2 已弃用，故不设置——见[官方文档](https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners)。）\n- **修正每个节点执行的「Invalid URL」错误**：为 N8N 和 Worker 新增 `N8N_PROTOCOL=https`。n8n 从 `${N8N_PROTOCOL}://${N8N_HOST}/...` 构建 `$execution.resumeUrl`；缺少协议时 URL 格式错误，每个节点（Set、Switch、Code 等）都会抛出 `TypeError: Invalid URL`。\n- **修正 Worker webhook URL 解析**：Worker 服务没有自己的域名绑定，因此 `${ZEABUR_WEB_DOMAIN}` / `${ZEABUR_WEB_URL}` 在其容器中未设置。现在改用 `${N8N_WEBHOOK_HOST}` / `${N8N_WEBHOOK_URL}`（由 N8N 服务新公开）作为 `N8N_HOST` 和 `WEBHOOK_URL`。\n\n### 2026-07-31\n- 为 PostgreSQL、Redis、N8N 和工作进程新增 healthCheck，确保服务会先等待依赖服务就绪再启动（不再有启动竞态）\n- 升级 PostgreSQL 至 18（`postgres:18` — 因应新版 data-dir 结构，volume 改挂载于 `/var/lib/postgresql`）\n- N8N 加密密钥不再显示于部署说明（保持隐秘 — 持有它即可解密工作流中的所有凭据；如有需要，可在 N8N 服务的环境变量中找到）\n- 从本地化设置画面移除过时的 `TASK_RUNNERS_AUTH_TOKEN` 变量（此令牌会自动生成，并在服务之间自动共享）\n\n### 2026-03-23\n- 修正服务依赖项位置，符合 Zeabur 模板规范（从 `spec` 内部移至服务层级），确保正确的启动顺序\n- 移除已弃用的 `N8N_RUNNERS_ENABLED` 环境变量（N8N v2 默认已启用任务运行器）\n- **修正任务运行器架构**：将单一 `Runners` 拆分为 `N8N-Runners`（连接 `http://N8N:5679`）和 `Worker-Runners`（连接 `http://Worker:5679`），符合官方 n8n docker-compose 架构，每个 n8n 实例配备独立的 Runner\n\n### 2025-12-28\n- **重要**：模板已更新以支持 N8N v2\n- 升级到外部任务运行器（生产环境推荐设置）\n- 添加了独立的 `task-runners` 服务作为 n8n-worker 的 sidecar 容器\n- 配置了 `N8N_RUNNERS_MODE=external` 以提供更好的安全性和性能\n- 任务运行器现在在隔离容器中执行 Code 节点的 JavaScript/Python 代码\n- 添加了 `TASK_RUNNERS_AUTH_TOKEN` 变量用于安全的代理-运行器认证\n\n此更新确保您的 N8N v2 工作流程使用外部任务运行器安全运行，遵循 N8N 生产部署的最佳实践。\n\n### 2025-03-17\n- 修复了 n8n 主实例和工作进程之间的 N8N_ENCRYPTION_KEY 不匹配问题\n- 确保工作进程使用与主实例相同的加密密钥，提高系统稳定性\n- 添加了手動設置 `N8N_ENCRYPTION_KEY` 的能力，以確保主實例和工作程序的加密密鑰同步\n\n⚠️ 重要：如果您正在使用此模板的旧版本，请更新到此版本以避免可能的加密密钥同步问题。\n\n注意：此模板启用了关键的环境变量以防止未来的兼容性问题：\n\n- `N8N_RUNNERS_MODE=external`：使用外部任务运行器容器（生产环境推荐）而非内部子进程。\n\n- `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true`：在扩展模式下于主实例执行手动工作流程的方式已被弃用。未来版本中，手动执行将转由工作进程处理。此设置为此变更做好准备。\n\n了解更多关于任务执行器的信息：https://docs.n8n.io/hosting/configuration/task-runners/\n\n如在 Deploy 时遇到任何问题，可以到 Github issue 告诉我，我会尽力解决：\n[https://github.com/glasschan/seafoodholdhand-zeabur-templates](https://github.com/glasschan/seafoodholdhand-zeabur-templates)"
    zh-TW:
        description: N8N v2 工作流程自動化平台，配備工作程序和外部任務執行器以實現安全代碼執行
        variables:
            - key: PUBLIC_DOMAIN
              type: DOMAIN
              name: 網域
              description: 你想將 N8N 綁在哪個網域上？
        readme: "# N8N v2 搭配工作程序與任務執行器 (create by SEAFOODHOLDHAND)\n\n[![N8N with Worker](https://i.imgur.com/gi4FDrn.png)](https://www.youtube.com/@seafoodholdhand)\n\n**N8N v2** 是一個強大的工作流程自動化平台，可以幫助你連接不同的服務並自動化任務。此模板包含：\n\n- **N8N v2 主實例**用於工作流程管理（最新版本）\n- **N8N 工作程序**用於處理背景任務\n- **外部任務執行器**用於安全執行 Code 節點（生產環境就緒設置）\n- **PostgreSQL** 資料庫用於數據存儲\n- **Redis** 用於隊列管理\n\n## 為什麼使用外部任務執行器？\n\n此模板使用**外部任務執行器** - N8N 推薦的生產環境設置，用於在 Code 節點中執行代碼：\n\n- **\U0001F512 增強安全性**：代碼在隔離容器中運行，與主 N8N 實例分開\n- **⚡ 更佳性能**：任務執行器可以根據工作負載獨立擴展\n- **\U0001F6E1️ 沙盒執行**：JavaScript 和 Python 代碼在受控環境中執行\n- **\U0001F504 自動關閉**：閒置的執行器會在 15 秒後自動關閉以節省資源\n- **\U0001F4CA 生產就緒**：遵循 N8N 生產部署的最佳實踐\n\n使用 N8N v2，你可以：\n- 使用可視化編輯器創建自動化工作流程\n- 連接數百種服務和 API\n- 在 Code 節點中安全地執行自定義 JavaScript 和 Python 代碼\n- 使用可靠的背景工作程序處理數據並自動化任務\n- 高效處理 Webhook 觸發的工作流程\n\n工作程序 + 任務執行器設置確保您的自動化任務得到可靠且安全的處理。\n\n## 更新日誌\n\n### 2026-08-02\n- **移除 N8N-Runners 服務**：設定了 `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true` + queue 模式後，主 N8N 實例永不啟動 5679 連接埠的任務代理——所有執行（手動和生產）都卸載至 Worker。N8N-Runners 一直卡在「Waiting for task broker to be ready」，毫無作用。同時從 N8N 服務移除了 `taskbroker` 連接埠（5679）和 `N8N_RUNNERS_BROKER_LISTEN_ADDRESS`。僅保留 Worker-Runners（Worker 確實執行代理）。\n- **修正 Code 節點執行（Worker-Runners）**：將 Worker-Runners 的 `N8N_RUNNERS_TASK_BROKER_URI` 從 `http://Worker:5679` 改為 `http://${WORKER_BROKER_HOST}:5679`。Zeabur 的叢集內 DNS 解析的是 `service-<id>` 主機名稱，而非 `Worker` 這樣的裸服務名稱——執行器一直卡在「Waiting for task broker to be ready」，Code 節點逾時 60 秒。Worker 服務現在透過 `${CONTAINER_HOSTNAME}` 公開內部主機名稱（`WORKER_BROKER_HOST`）供執行器使用。（`N8N_RUNNERS_ENABLED` 在 n8n v2 已棄用，故不設定——見[官方文件](https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners)。）\n- **修正每個節點執行的「Invalid URL」錯誤**：為 N8N 和 Worker 新增 `N8N_PROTOCOL=https`。n8n 從 `${N8N_PROTOCOL}://${N8N_HOST}/...` 建構 `$execution.resumeUrl`；缺少通訊協定時 URL 格式錯誤，每個節點（Set、Switch、Code 等）都會拋出 `TypeError: Invalid URL`。\n- **修正 Worker webhook URL 解析**：Worker 服務沒有自己的網域綁定，因此 `${ZEABUR_WEB_DOMAIN}` / `${ZEABUR_WEB_URL}` 在其容器中未設定。現在改用 `${N8N_WEBHOOK_HOST}` / `${N8N_WEBHOOK_URL}`（由 N8N 服務新公開）作為 `N8N_HOST` 和 `WEBHOOK_URL`。\n\n### 2026-07-31\n- 為 PostgreSQL、Redis、N8N 和工作程序新增 healthCheck，確保服務會先等待相依服務就緒再啟動（不再有啟動競態）\n- 升級 PostgreSQL 至 18（`postgres:18` — 因應新版 data-dir 結構，volume 改掛載於 `/var/lib/postgresql`）\n- N8N 加密金鑰不再顯示於部署說明（保持隱密 — 持有它即可解密工作流程中的所有憑證；如有需要，可在 N8N 服務的環境變數中找到）\n- 從本地化設定畫面移除過時的 `TASK_RUNNERS_AUTH_TOKEN` 變數（此令牌會自動產生，並在服務之間自動共用）\n\n### 2026-03-23\n- 修正服務依賴項位置，符合 Zeabur 模板規範（從 `spec` 內部移至服務層級），確保正確的啟動順序\n- 移除已棄用的 `N8N_RUNNERS_ENABLED` 環境變數（N8N v2 預設已啟用任務執行器）\n- **修正任務執行器架構**：將單一 `Runners` 拆分為 `N8N-Runners`（連接 `http://N8N:5679`）和 `Worker-Runners`（連接 `http://Worker:5679`），符合官方 n8n docker-compose 架構，每個 n8n 實例配備獨立的 Runner\n\n### 2025-12-28\n- **重要**：模板已更新以支援 N8N v2\n- 升級至外部任務執行器（生產環境推薦設置）\n- 添加了獨立的 `task-runners` 服務作為 n8n-worker 的 sidecar 容器\n- 配置了 `N8N_RUNNERS_MODE=external` 以提供更好的安全性和性能\n- 任務執行器現在在隔離容器中執行 Code 節點的 JavaScript/Python 代碼\n- 添加了 `TASK_RUNNERS_AUTH_TOKEN` 變數用於安全的中介-執行器認證\n\n此更新確保您的 N8N v2 工作流程使用外部任務執行器安全運行，遵循 N8N 生產部署的最佳實踐。\n\n### 2025-03-17\n- 修復了 n8n 主實例和工作程序之間的 N8N_ENCRYPTION_KEY 不匹配問題\n- 確保工作程序使用與主實例相同的加密密鑰，提高系統穩定性\n- 添加了手動設置 `N8N_ENCRYPTION_KEY` 的能力，以確保主實例和工作程序的加密密鑰同步\n\n⚠️ 重要：如果您正在使用此模板的舊版本，請更新到此版本以避免可能的加密密鑰同步問題。\n\n注意：此模板啟用了關鍵的環境變數以防止未來的相容性問題：\n\n- `N8N_RUNNERS_MODE=external`：使用外部任務執行器容器（生產環境推薦）而非內部子進程。\n\n- `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true`：在擴展模式下於主實例執行手動工作流程的方式已被棄用。未來版本中，手動執行將轉由工作程序處理。此設定為此變更做好準備。\n\n了解更多關於任務執行器的信息：https://docs.n8n.io/hosting/configuration/task-runners/\n\n如在 Deploy 時遇到任何問題，可以到 Github issue 告訴我，我會盡力解決：\n[https://github.com/glasschan/seafoodholdhand-zeabur-templates](https://github.com/glasschan/seafoodholdhand-zeabur-templates)"
