# ── AgeniusDesk CE configuration ────────────────────────────────────────────── # Copy to .env and edit. Every value is optional unless noted. # Dashboard port on the host (container always listens on 3000). # PORT=3000 # Encrypted-secrets master key. Leave unset to auto-generate at data/.secret_key # (back it up: losing it makes stored secrets unrecoverable). # SECRET_KEY= # Local account login is ON by default. AGD_REQUIRE_AUTH is an extra hard gate # for token/edge-auth deployments, and keeps auth required even if # AGD_DISABLE_LOGIN=true. AGD_REQUIRE_AUTH=false # Admin bearer token accepted on internal API routes when set. # AGD_ADMIN_TOKEN= # Trust Cloudflare Access / reverse-proxy identity headers. Only enable when the # dashboard is reachable exclusively through that trusted proxy. # AGD_TRUST_EDGE_AUTH=false # Trust X-Forwarded-For for login throttling. Only enable behind a trusted proxy. # AGD_TRUST_FORWARDED_FOR=false # ── Local account login (accounts + sessions + optional 2FA) ────────────────── # On first run the browser forces you to create an owner account, then requires # login. An edge identity (Cloudflare Access) still satisfies the gate without a # local account. Set true to turn browser login OFF (dev/localhost only). # AGD_DISABLE_LOGIN=false # Session lifetime (sliding) and a hard absolute cap, in days. # AGD_SESSION_TTL_DAYS=14 # AGD_SESSION_ABSOLUTE_DAYS=30 # Failed-login lockout: attempts before lockout, and lockout duration (minutes). # AGD_LOGIN_MAX_ATTEMPTS=8 # AGD_LOGIN_LOCKOUT_MINUTES=15 # Password policy for new accounts, resets, and changes. Default: 12 chars with # an uppercase, a lowercase, a number, and a symbol. Relax any class by setting # it false (length always applies). # AGD_PASSWORD_MIN_LENGTH=12 # AGD_PASSWORD_REQUIRE_UPPER=true # AGD_PASSWORD_REQUIRE_LOWER=true # AGD_PASSWORD_REQUIRE_NUMBER=true # AGD_PASSWORD_REQUIRE_SYMBOL=true # Password-reset link lifetime (minutes). # AGD_PASSWORD_RESET_TTL_MINUTES=30 # ── Email (SMTP) — password reset ───────────────────────────────────────────── # Used to send the "forgot password" reset link. If AGD_SMTP_HOST is unset, the # reset link is written to the container log instead (self-hosted fallback). # AGD_SMTP_HOST=smtp.example.com # AGD_SMTP_PORT=587 # AGD_SMTP_USER=apikey-or-username # AGD_SMTP_PASSWORD=your-smtp-password # AGD_SMTP_FROM=ageniusdesk@example.com # defaults to AGD_SMTP_USER when blank # AGD_SMTP_STARTTLS=true # Public base URL used to build links in emails (else falls back to the request # origin). Set this for any non-localhost deployment behind a proxy. # AGD_PUBLIC_URL=https://app.example.com # Verify TLS on outbound calls to n8n / MCP servers. This is the fleet-wide # default. Prefer the per-instance "Verify TLS" setting for a single self-signed # n8n: turning it off here disables cert checks for EVERY outbound call, # including the ones to public HTTPS providers. AGD_TLS_VERIFY=true # Restrict server-side fetches of operator-supplied URLs to these CIDRs # (comma-separated). Empty (default) allows any private/LAN range, because # self-hosted n8n/Ollama/Qdrant live there. Cloud metadata, link-local, and # reserved ranges are always blocked regardless of this setting. # AGD_EGRESS_ALLOW_CIDRS=10.0.0.0/8,192.168.1.0/24 # ── Optional: security hardening ────────────────────────────────────────────── # CORS origins (comma-separated). Default is EMPTY = same-origin only, which is # all the bundled frontend needs. Set this only if a separate origin calls the # API. "*" allows any origin (credentials are never sent cross-origin either way). # AGD_CORS_ORIGINS=https://app.example.com # Optional token for the legacy /api/errors/webhook and /api/messages/webhook # ingest endpoints. New integrations should prefer X-API-Key protected /api/v1. # Unset = open (a startup warning says so); the endpoints are rate-limited either way. # AGD_WEBHOOK_TOKEN= # Optional bearer token for /api/mcp-dashboard, for external MCP clients. # DASHBOARD_MCP_TOKEN= # Max request body size in bytes (default 25 MiB). Requests over this get 413. # AGD_MAX_REQUEST_BYTES=26214400 # Per-key request budget for the public API (/api/v1), requests/min. 0 disables. # In-memory and per-process. Over budget gets 429 + Retry-After. # AGD_PUBLIC_API_RATE=120 # Per-IP budget for the machine-ingest endpoints (errors/messages webhooks, OTLP # traces), requests/min. 0 disables. These accept writes with no session, so the # limit is what stops a caller that can reach the port from filling SQLite. # AGD_INGEST_RATE=600 # ── Optional: assistant tool execution ──────────────────────────────────────── # The assistant reads content you do not control (n8n error/execution payloads, # RAG hits, MCP tool output). A prompt injection hiding in any of it can steer # the model into calling a state-changing tool you never asked for. By default # those calls are NOT executed: they surface in the chat as a proposal you # confirm with a click. Set true to restore unattended execution. # AGD_ASSISTANT_AUTORUN=false # Whether MCP tools take part in the gate at all. On by default. This is NOT an # all-or-nothing prompt: each MCP server carries its own "confirm" policy (set # when you add it) of writes / all / none, defaulting to writes-only. A tool is # classified using the server's own MCP annotations (readOnlyHint), falling back # to a known naming convention (n8n-mcp: the n8n_* tools are the live-instance # ones, everything else is the docs brain). Anything we cannot classify counts as # a write. So Code Lab's search_nodes/validate_workflow run freely while # n8n_create_workflow/n8n_delete_workflow raise a confirmation card. The built-in # docs-mode n8n-mcp is registered with confirm=none automatically, since without # instance credentials it has no write tools at all. # Set false to drop MCP from the gate entirely, keeping it on the built-in tools. # AGD_ASSISTANT_CONFIRM_MCP=true # Content-Security-Policy header (opt-in; empty = no CSP). The editors load from # CDNs (cdn.jsdelivr.net, esm.sh) and the music tab embeds arbitrary origins, so # a strict policy can break features. Recommended starting point if you want one: # AGD_CSP=default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://esm.sh; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; worker-src 'self' blob:; img-src 'self' data: https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self' # ── Optional: OpenTelemetry observability (embedded OTLP receiver) ──────────── # Receive per-execution, per-node spans from n8n and render them as a trace # waterfall in the Observability view. Off by default. The ingest endpoint is a # machine-ingest surface; set AGD_OTEL_TOKEN before exposing the port publicly. # AGD_OTEL_ENABLED=false # Bearer token n8n must send. Unset = open (trusted-LAN only). On the n8n side: # N8N_OTEL_ENABLED=true # N8N_OTEL_EXPORTER_OTLP_ENDPOINT=http://:/api/otel # n8n appends /v1/traces # N8N_OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer # AGD_OTEL_TOKEN= # Bounded retention (pruned on ingest): oldest spans dropped past either cap. # AGD_OTEL_RETENTION_HOURS=72 # AGD_OTEL_MAX_SPANS=500000 # Silent-failure detection (low-output anomaly classifier). Only a node that is # historically a reliable producer fires on a zero/low output; idle pollers and # cold-start stay quiet. All optional; defaults shown. # AGD_HEALTH_MIN_SAMPLES=20 # AGD_HEALTH_STEADY_ZERO_RATE=0.05 # AGD_HEALTH_DORMANT_ZERO_RATE=0.95 # AGD_HEALTH_DROP_FACTOR=0.1 # AGD_HEALTH_WINDOW=200 # ── Agent Fleet (LangGraph + PydanticAI agents) ─────────────────────────────── # Agents are opt-in; the default image is n8n-only. Build with the agent stack to # reveal the Agent Fleet view + Code Lab's Agent Builder, then run # `docker compose up -d --build`. The built-in agents run on Claude (set ANTHROPIC_KEY below). # AGD_EXTRAS=assistant,langgraph # Override the auto-detect: false = stay n8n-only even with the extra; true = force on. # AGD_AGENTS_ENABLED= # ── AI providers (set the one(s) you use) ───────────────────────────────────── # Any of these can also be added later in the UI (Settings > Secrets) instead of # here. Each is the convention secret the matching provider resolves by default. # ANTHROPIC_KEY= # OPEN_AI_KEY= # OPEN_ROUTER_KEY= # one key, hundreds of models (recommended starting point) # OLLAMA_URL=http://host.docker.internal:11434 # Additional OpenAI-compatible providers (native keys): # PERPLEXITY_KEY= # GROQ_KEY= # DEEPSEEK_KEY= # MISTRAL_KEY= # XAI_KEY= # TOGETHER_KEY= # Custom (OpenAI-compatible) provider: point at ANY OpenAI-compatible API root # (Azure OpenAI, LiteLLM, vLLM, LocalAI, Fireworks, ...). Set the base URL in # Models > "Custom OpenAI-compatible endpoint"; this key authenticates it. # CUSTOM_LLM_KEY= # ── Optional: knowledge RAG backend (point at your own Qdrant) ──────────────── # QDRANT_URL=http://localhost:6333 # QDRANT_API_KEY= # ── Optional: Docker / Containers tab ───────────────────────────────────────── # Comma-separated hostnames or IPs that THIS host is known by on your LAN. # Needed only when the dashboard runs in Docker and your n8n instance URLs use # the host's LAN IP, so the container can recognize a local instance. # AGD_HOST_ALIASES=myhost,myhost.local,192.0.2.10 # ── Optional: notification sinks (operator-supplied; no defaults) ───────────── # SLACK_WEBHOOK_URL= # DISCORD_WEBHOOK_URL=