Self-hosted n8n with native Login with Chutes, bundled n8n-nodes-chutes, local e2ee-local-proxy.chutes.dev mode, and public-domain mode with ACME.
This repo supports two packaging shapes:
- a single-container standalone image built from
Dockerfile.local-repo - a Docker Compose deployment driven by
deploy.sh
Build workflows with Chutes-native auth, multi-modal capabilities, and node integrations on top of n8n's orchestration, scheduling, webhooks, and automation runtime.
docker run --rm -it \
--pull always \
--platform linux/amd64 \
-p 443:443 \
ghcr.io/chutesai/chutes-n8n-local:latestSee Standalone Image for non-interactive runs, domain mode, runtime flags, persisted state layout, and building from source.
macOS/Linux/WSL:
bash <(curl -fsSL -H 'Cache-Control: no-cache' \
"https://raw.githubusercontent.com/chutesai/chutes-n8n-local/main/deploy.sh?$(date +%s)")The deploy script:
- clones or refreshes
chutesai/chutes-n8n-local - runs
deploy.sh - auto-clones
sirouk/n8n-nodes-chutesbeside it if missing - fast-forwards
n8n-nodes-chuteson clean reruns so the embedded nodes do not drift stale
When launched from a terminal, the deploy script prompts for install mode and the required Chutes OAuth settings even when invoked via curl ... | bash.
For headless or CI usage, preseed the required environment variables:
curl -fsSL https://raw.githubusercontent.com/chutesai/chutes-n8n-local/main/deploy.sh | \
INSTALL_MODE=local \
CHUTES_OAUTH_CLIENT_ID=... \
CHUTES_OAUTH_CLIENT_SECRET=... \
bashManual clone:
git clone https://github.com/chutesai/chutes-n8n-local.git
cd chutes-n8n-local
./deploy.shIf ../n8n-nodes-chutes is missing, deploy will clone:
https://github.com/sirouk/n8n-nodes-chutes.git
You can override that source if needed (fork) with:
CHUTES_N8N_NODES_GIT_URL=git@github.com:sirouk/n8n-nodes-chutes.git ./deploy.sh./deploy.sh
./deploy.sh --force
./deploy.sh --wipe
./deploy.sh --reset-owner-password
./deploy.sh --downDeploy asks for, when a terminal is attached:
- install mode:
localordomain - existing-install action:
updateorwipe - Chutes traffic mode:
directore2ee-proxy - if you pick
e2ee-proxy, deploy also asks whether to keep it strict TEE-only for text models - Chutes OAuth client ID and secret
- ACME email for
domaininstalls
Mode behavior:
local: serves n8n athttps://e2ee-local-proxy.chutes.devusing the embedded e2ee-proxy certificate pathdomain: serves n8n on your real domain through Caddy with Let's Encrypt
Existing install behavior:
updateis the default and preserves Postgres and n8n data volumeswiperemoves containers, volumes, and encrypted n8n state, then recreates everything cleanly
Chutes traffic mode:
direct: the Chutes nodes use native Chutes endpoints and keep Chutes routing and failover behaviore2ee-proxy: OpenAI-compatible LLM text traffic uses the locale2ee-proxypath By default this followse2ee-proxy's TEE-only behavior. Deploy asks whether to keep that strict mode, and it writesALLOW_NON_CONFIDENTIALaccordingly. While the backend/e2e/*SSO auth fix is rolling out, deploy also keepsCHUTES_SSO_PROXY_BYPASS=trueso SSO-backed text execution stays direct. Once that backend fix is live, set it tofalseto send SSO text execution throughe2ee-proxytoo.
Traffic-mode scope:
local/domaincontrols how n8n itself is exposeddirect/e2ee-proxycontrols how text-based Chutes LLM requests are executed- chute discovery and non-text Chutes traffic stay on native Chutes endpoints
Dockerfile.local-repo packages n8n, OpenResty, Caddy, s6-overlay, bundled Chutes nodes, and starter workflows into a single image.
Published image:
ghcr.io/chutesai/chutes-n8n-local:latest- release tags are also published as semver tags when releases are cut
Releases are published for linux/amd64.
Persistent standalone state lives under /data:
/data/.n8n: n8n user data and SQLite database/data/caddy: Caddy certificate and state storage/data/.env: standalone runtime configuration written after first boot/data/.configured: initialization sentinel
Build from source locally:
The examples below tag the image as chutes-n8n-local:local-repo to make it clear that it was built from your current checkout, not pulled from GHCR.
docker buildx build --load \
-t chutes-n8n-local:local-repo \
-f Dockerfile.local-repo .Run it interactively and let the container prompt for settings:
docker run --rm -it \
-p 80:80 -p 443:443 \
chutes-n8n-local:local-repoRun it non-interactively in local mode:
docker run --rm -it \
-p 80:80 -p 443:443 \
-e INSTALL_MODE=local \
-e CHUTES_TRAFFIC_MODE=direct \
-e CHUTES_OAUTH_CLIENT_ID=... \
-e CHUTES_OAUTH_CLIENT_SECRET=... \
chutes-n8n-local:local-repoRun it non-interactively in domain mode:
docker run --rm -it \
-p 80:80 -p 443:443 \
-e INSTALL_MODE=domain \
-e N8N_HOST=n8n.example.com \
-e ACME_EMAIL=you@example.com \
-e CHUTES_TRAFFIC_MODE=e2ee-proxy \
-e CHUTES_OAUTH_CLIENT_ID=... \
-e CHUTES_OAUTH_CLIENT_SECRET=... \
chutes-n8n-local:local-repoIf you want the standalone container to keep its config, workflows, and SQLite database between runs, add:
-v chutes_n8n_data:/dataStandalone runtime knobs:
INSTALL_MODE:localordomainCHUTES_TRAFFIC_MODE:directore2ee-proxyN8N_HOSTandACME_EMAIL: required fordomain--reconfigure: rerun setup prompts while preserving existing data--wipe: delete persisted n8n and Caddy state, then initialize again
In local mode, the container serves n8n on https://e2ee-local-proxy.chutes.dev. To test it without editing your hosts file:
curl -sk \
--resolve e2ee-local-proxy.chutes.dev:443:127.0.0.1 \
https://e2ee-local-proxy.chutes.dev/- Community n8n with native Chutes SSO
- baked-in
n8n-nodes-chutes n8nbuilt fromDockerfile.local-repopostgres- one edge service:
local-proxyfor local installscaddyfor public-domain installs
- optional
e2ee-proxysidecar for domain installs whenCHUTES_TRAFFIC_MODE=e2ee-proxy
./scripts/smoke-test.sh --syntax
./scripts/smoke-test.sh
./scripts/e2e-test.shsmoke-test.sh --syntaxis safe anywheresmoke-test.shvalidates the compose stack afterdeploy.she2e-test.shis destructive and rebuilds the local test stack
CI runs syntax smoke checks plus the local test-IdP end-to-end path.
Before publishing the standalone image, validate both the existing compose path and the standalone package path:
./scripts/smoke-test.sh --syntax
./scripts/e2e-test.sh
docker buildx build --load \
-t chutes-n8n-local:standalone-test \
-f Dockerfile.local-repo .
mkdir -p .tmp/standalone-data
docker run --rm -it \
-p 80:80 -p 443:443 \
-v "$PWD/.tmp/standalone-data:/data" \
-e INSTALL_MODE=local \
-e CHUTES_TRAFFIC_MODE=direct \
-e CHUTES_OAUTH_CLIENT_ID=... \
-e CHUTES_OAUTH_CLIENT_SECRET=... \
chutes-n8n-local:standalone-testFor the standalone image, check at least:
- first boot initializes cleanly with an empty
/datavolume - second boot reuses the saved config without prompting again
--reconfigureupdates settings without deleting data--wipeclears persisted state and starts from scratch- local mode responds on
https://e2ee-local-proxy.chutes.dev - domain mode obtains certificates and serves the expected hostname
deploy.sh: consolidated quick-start, install, and update entrypointdocker-compose*.yml: base, local, domain, and test stacksDockerfile.local-repo: standalone package image with n8n, OpenResty, Caddy, and s6-overlayDockerfile.n8n: n8n-focused build recipe retained alongside the standalone imagen8n-overlays/: native n8n backend and UI changesstandalone/: standalone entrypoint, proxy templates, post-start setup, and s6 service definitionsscripts/: deploy helpers, smoke tests, and E2E coveragetests/test-chutes-idp/: local test IdP for CI and destructive local E2E
This project builds on the self-hosted n8n Community Edition and adds Chutes-specific packaging, local/domain deployment, and native Chutes integrations.
Use of upstream n8n remains subject to n8n’s licensing terms, including the Sustainable Use License and any applicable Enterprise licensing. This repository does not modify or replace those upstream license obligations.
Before using this project in a commercial, embedded, hosted-for-others, or customer-facing offering, review the official n8n licensing and Community Edition documentation: