version: '1.0' volumes: sandbox-tls: driver: local driver_opts: type: none o: bind device: /media/truenas/n8n/sandbox-tls services: postgres: image: postgres:16 restart: always environment: - POSTGRES_USER - POSTGRES_PASSWORD - POSTGRES_DB - POSTGRES_NON_ROOT_USER - POSTGRES_NON_ROOT_PASSWORD volumes: - /media/truenas/postgres/data:/var/lib/postgresql/data - /media/truenas/postgres/init-data.sh:/docker-entrypoint-initdb.d/init-data.sh healthcheck: test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}'] interval: 5s timeout: 5s retries: 10 sandbox-certs: image: ghcr.io/n8n-io/n8n-sandbox-service-api:latest user: '0:0' entrypoint: ['sh', '-c'] command: - > bootstrap-mtls.sh --out-dir /tls --api-san sandbox-api --control-san-prefix sandbox-runner && chown -R sandbox-api:sandbox-api /tls/api environment: NUM_RUNNERS: '1' volumes: - sandbox-tls:/tls sandbox-api: image: ghcr.io/n8n-io/n8n-sandbox-service-api:latest depends_on: sandbox-certs: condition: service_completed_successfully environment: SANDBOX_API_KEYS: ${SANDBOX_API_KEYS} SANDBOX_API_RUNNER_REGISTRATION_TOKEN: ${SANDBOX_API_RUNNER_REGISTRATION_TOKEN} SANDBOX_API_RUNNER_API_KEY: ${SANDBOX_API_RUNNER_API_KEY} SANDBOX_API_GRPC_TLS_CERT_FILE: /tls/api/grpc-server.crt SANDBOX_API_GRPC_TLS_KEY_FILE: /tls/api/grpc-server.key SANDBOX_API_GRPC_TLS_CLIENT_CA_FILE: /tls/api/ca.crt SANDBOX_API_RUNNER_CONTROL_GRPC_TLS_CA_FILE: /tls/api/ca.crt SANDBOX_API_RUNNER_CONTROL_GRPC_TLS_CERT_FILE: /tls/api/control-grpc-api-client.crt SANDBOX_API_RUNNER_CONTROL_GRPC_TLS_KEY_FILE: /tls/api/control-grpc-api-client.key SANDBOX_API_RUNNER_CONTROL_GRPC_TLS_SERVER_NAME: sandbox-runner-1 volumes: - sandbox-tls:/tls:ro healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:8080/healthz"] interval: 5s timeout: 3s retries: 5 start_period: 10s # Never publish 8080/9090 to the host on an internet-facing server. # n8n reaches this container by service name over the default Compose network. sandbox-runner-1: image: ghcr.io/n8n-io/n8n-sandbox-service-runner-dind:latest privileged: true depends_on: sandbox-api: condition: service_healthy environment: SANDBOX_RUNNER_API_KEYS: ${SANDBOX_API_RUNNER_API_KEY} SANDBOX_RUNNER_REGISTRATION_TOKEN: ${SANDBOX_API_RUNNER_REGISTRATION_TOKEN} SANDBOX_RUNNER_API_GRPC_ADDR: sandbox-api:9090 SANDBOX_RUNNER_HTTP_BASE_URL: http://sandbox-runner-1:8080 SANDBOX_RUNNER_CONTROL_GRPC_LISTEN_ADDR: ':9091' SANDBOX_RUNNER_CONTROL_GRPC_ADVERTISE_ADDR: sandbox-runner-1:9091 SANDBOX_RUNNER_ID: runner-1 SANDBOX_RUNNER_DOCKER_SANDBOX_IMAGE: ghcr.io/n8n-io/n8n-sandbox-service-sandbox:latest SANDBOX_RUNNER_REGISTRATION_GRPC_CA_FILE: /tls/runner/ca.crt SANDBOX_RUNNER_REGISTRATION_GRPC_CERT_FILE: /tls/runner/grpc-client.crt SANDBOX_RUNNER_REGISTRATION_GRPC_KEY_FILE: /tls/runner/grpc-client.key SANDBOX_RUNNER_REGISTRATION_GRPC_SERVER_NAME: sandbox-api SANDBOX_RUNNER_CONTROL_GRPC_TLS_CERT_FILE: /tls/runner/control-grpc-server.crt SANDBOX_RUNNER_CONTROL_GRPC_TLS_KEY_FILE: /tls/runner/control-grpc-server.key SANDBOX_RUNNER_CONTROL_GRPC_TLS_CLIENT_CA_FILE: /tls/runner/ca.crt volumes: - sandbox-tls:/tls:ro # Never expose this container's ports publicly — it runs privileged Docker-in-Docker. searxng: image: ghcr.io/searxng/searxng:latest environment: SEARXNG_SECRET: ${SEARXNG_SECRET} volumes: - /media/truenas/n8n/searxng/searxng-settings.yml:/etc/searxng/settings.yml:ro # Internal-only: n8n reaches it by service name. Never publish its port. n8n: image: docker.n8n.io/n8nio/n8n:${N8N_VERSION} restart: always environment: - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=${POSTGRES_DB} - DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER} - DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD} - N8N_RUNNERS_MODE=external - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN} - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0 # ----use sandbox - N8N_ENABLED_MODULES=instance-ai - N8N_INSTANCE_AI_SANDBOX_ENABLED=true - N8N_INSTANCE_AI_SANDBOX_IMAGE=ghcr.io/n8n-io/n8n-sandbox-service-sandbox:latest - N8N_SANDBOX_SERVICE_URL=http://sandbox-api:8080 - N8N_SANDBOX_SERVICE_API_KEY=${N8N_SANDBOX_SERVICE_API_KEY} - N8N_HOST=https://n8n.yudongli.net # - N8N_PORT=5678 # - N8N_PROTOCOL=https - WEBHOOK_URL=https://n8n.yudongli.net # - N8N_PROXY_HOPS=1 ports: - 5678:5678 links: - postgres volumes: - /media/truenas/n8n/n8n:/home/node/.n8n depends_on: postgres: condition: service_healthy sandbox-api: condition: service_healthy n8n-runner: image: n8nio/runners:${N8N_VERSION} restart: always environment: - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN} - N8N_RUNNERS_TASK_BROKER_URI=https://n8n.yudongli.net:5679 depends_on: - n8n