Skilder
Reference

Configuration

Environment variables and configuration options for Skilder deployments — backend, frontend, runtime, and infrastructure.

This reference covers the environment variables for each Skilder component.

Backend

The backend runs a Fastify server with Apollo GraphQL.

VariableDescriptionDefault
PORTHTTP port3000
PRIVATE_DGRAPH_URLDgraph database endpoint (internal network)localhost:8080
NATS_SERVERSNATS server address (this service's own bus connection target)localhost:4222
PUBLIC_NATS_SERVERSNATS server list advertised to external runtimes--
ENCRYPTION_KEYKey for encrypting secrets (API keys, OAuth tokens, MCP server configs). Required.--
JWT_PRIVATE_KEY_PATHPath to Ed25519 private key for signing JWTs--
JWT_PUBLIC_KEY_PATHPath to Ed25519 public key for verifying JWTs--
JWT_ISSUERIssuer claim for JWT tokensskilder-platform
JWT_ACCESS_TOKEN_TTLAccess token TTL in seconds900 (15 min)
JWT_REFRESH_TOKEN_TTLRefresh token TTL in seconds604800 (7 days)
IDENTITY_KEY_USAGE_THROTTLE_SECONDSHow long an identity key's recorded "last used" timestamp counts as fresh before it is written again60 (1 minute)
LOG_LEVELLogging verbosity: trace, debug, info, warn, errorinfo
CORS_ORIGINSAllowed CORS origins (comma-separated)http://localhost:8888,http://localhost:3000
PRIVATE_MCP_URLRemote MCP server endpoint reached over the internal networkhttp://localhost:3001/mcp
PUBLIC_BACKEND_URLExternally-reachable backend base URL (OAuth issuer/endpoints, MCP server URLs, signed file URLs). Must never be an internal service name. Required in production.http://localhost:3000
PUBLIC_FRONTEND_URLPublic frontend URL (used for email links, OAuth callbacks)http://localhost:8888
PUBLIC_MCP_URLPublic, externally-reachable MCP URL of the remote MCP server (RFC 8707 resource identifier advertised in OAuth metadata)http://localhost:3001/mcp
EMAIL_PROVIDEREmail provider: log (console), brevo (EU), or resend (US)log
BREVO_API_KEYBrevo API key (when EMAIL_PROVIDER=brevo)--
RESEND_API_KEYResend API key (when EMAIL_PROVIDER=resend)--
EMAIL_FROMSender email (when EMAIL_PROVIDER=brevo or resend)--
EMAIL_FROM_NAMESender display name (used by Brevo)The Skilder Team
BREVO_TIMEOUT_SECONDSPer-request timeout for the Brevo API, in seconds10

Example

PORT=3000
PRIVATE_DGRAPH_URL=localhost:8080
NATS_SERVERS=localhost:4222
ENCRYPTION_KEY=your-64-char-hex-encryption-key
JWT_PRIVATE_KEY_PATH=./keys/private.pem
JWT_PUBLIC_KEY_PATH=./keys/public.pem
JWT_ISSUER=skilder-platform
LOG_LEVEL=info
CORS_ORIGINS=https://app.yourdomain.com
PRIVATE_MCP_URL=http://localhost:3001/mcp
PUBLIC_BACKEND_URL=https://app.yourdomain.com
PUBLIC_FRONTEND_URL=https://app.yourdomain.com
EMAIL_PROVIDER=brevo
BREVO_API_KEY=xkeysib-your_api_key_here
EMAIL_FROM=noreply@mail.skilder.ai
EMAIL_FROM_NAME=The Skilder Team

Frontend

The frontend is a React + Vite application.

VariableDescriptionDefault
VITE_PUBLIC_BACKEND_URLExternally-reachable backend base URL (build-time). Full URL including scheme.http://localhost:3000
PUBLIC_BACKEND_URLBackend base URL (runtime, Docker). Injected into the served HTML via window.__ENV__; overrides VITE_PUBLIC_BACKEND_URL.--

The frontend derives HTTP and WebSocket URLs from the backend URL automatically.

Example

# Build-time
VITE_PUBLIC_BACKEND_URL=https://api.yourdomain.com

# Runtime (Docker)
PUBLIC_BACKEND_URL=https://api.yourdomain.com

Runtime

The runtime executes MCP servers and routes tool calls. Its mode is determined by which environment variables are set.

Identity

A runtime needs RUNTIME_KEY, or SYSTEM_KEY together with RUNTIME_NAME. There are no modes left to select — a runtime executes tools, and the public MCP endpoint is its own service.

Two variables are rejected at boot rather than ignored:

  • USER_KEY — the former stdio single-agent mode. Connect agents to the Streamable HTTP endpoint instead.
  • MCP_REMOTE_ENABLED — the former fused MCP mode. Run the remote MCP server for that.

REMOTE_PORT controls the web service (GET /health for liveness, GET /ready for readiness) and nothing else.

Core Configuration

VariableDescriptionDefault
NATS_SERVERSNATS cluster addresslocalhost:4222
REMOTE_PORTPort for the web service — GET /health and GET /ready-- (no web service; container images default to 3003)
RUNTIME_NAMEHuman-readable name (required with SYSTEM_KEY)--
LOG_LEVELLogging verbosityinfo
LOG_LEVELSPattern-based log levels (e.g., mcp.*=debug,tool.*=trace)--
FORWARD_STDERRForward child process stderr to runtime logfalse
HEARTBEAT_INTERVALHealth heartbeat interval in ms5000
PRIVATE_MCP_URLRemote MCP server address (internal network) the delegate tool dials back. Optional: unset, the runtime uses the public MCP URL the backend advertises at handshakehttp://localhost:3001/mcp

File Service

VariableDescriptionDefault
SKILDER_WORKING_DIRWorking directory for temp files and assets/tmp/skilder
SKILDER_ALLOWED_PATHSColon-separated path safelist for file access--
SKILDER_MAX_FILE_SIZE_MBMax file size for operations10
SKILDER_GC_INTERVAL_MSGarbage collection check interval60000 (1 min)
SKILDER_GC_MAX_AGE_MSMax age for temp files before cleanup300000 (5 min)
SKILDER_ASSET_CACHE_MAX_AGE_MSAsset cache TTL3600000 (1 hour)

Example

RUNTIME_KEY=RTK_your_runtime_key
NATS_SERVERS=nats://nats.yourdomain.com:4222
REMOTE_PORT=3003
PRIVATE_MCP_URL=http://remote-mcp:3001/mcp
LOG_LEVEL=info
SKILDER_WORKING_DIR=/tmp/skilder

Remote MCP Server

The public Streamable HTTP surface agents connect to. It terminates agent HTTP and OAuth, holds MCP sessions, and fans every tool call out to runtimes over NATS — it executes nothing itself.

Identity

SYSTEM_KEY, and only SYSTEM_KEY. It handshakes as a remote-mcp-server identity: no Runtime row, no heartbeat, no workspace of its own (each session carries one). RUNTIME_KEY and RUNTIME_NAME are rejected at boot — accepting them would register a phantom runtime the backend would then route work to.

Core Configuration

VariableDescriptionDefault
NATS_SERVERSNATS cluster addresslocalhost:4222
REMOTE_PORTPort for /mcp, /health, /ready and the OAuth metadata. Required-- (container images default to 3001)
PRIVATE_BACKEND_URLBackend HTTP base for catalog pulls and transient uploadshandshake-advertised URL
PUBLIC_MCP_URLThis server's public, externally-reachable MCP URL (RFC 8707 resource identifier)http://localhost:3001/mcp
PUBLIC_BACKEND_URLPublic base URL of the Authorization Server, advertised in the resource metadatahttp://localhost:3000
LOG_LEVEL / LOG_LEVELSLogging verbosityinfo

Preloading

Preloading is per MCP session, not per process: append ?skillIds=<id,id> or ?roleIds=<id,id> to the /mcp endpoint URL to auto-disclose those skills or roles to that connection. The SKILL_IDS / ROLE_IDS environment variables belonged to the removed stdio mode and are no longer read (SKI-605).

Security

VariableDescriptionDefault
SKILDER_ALLOWED_ORIGINSAllowed origins for the HTTP transport--
SKILDER_PREVENT_DNS_REBINDINGEnable origin validation against DNS rebindingtrue
SKILDER_SESSION_IDLE_TIMEOUT_MSSession cleanup timeout300000 (5 min)

Example

SYSTEM_KEY=SYK_your_system_key
NATS_SERVERS=nats://nats.yourdomain.com:4222
REMOTE_PORT=3001
PUBLIC_MCP_URL=https://mcp.yourdomain.com/mcp
PUBLIC_BACKEND_URL=https://api.yourdomain.com
SKILDER_ALLOWED_ORIGINS=https://app.yourdomain.com

Infrastructure Services

Dgraph (Graph Database)

Deploy with at least one Zero node and one Alpha node.

PortDescriptionDefault
Alpha HTTPQuery and mutation endpoint8080
Alpha gRPCInternal replication9080
Zero gRPCCluster coordination5080

NATS (Message Bus)

VariableDescriptionDefault
NATS_PORTClient connection port4222
NATS_HTTP_PORTHTTP monitoring port8222
NATS_JETSTREAMEnable JetStream for persistent messagingtrue

Security Notes

  • Never commit secrets to version control. Use a secrets manager or .env files.
  • Change the default ENCRYPTION_KEY immediately. The default key is for development only — using it in production compromises all encrypted data.
  • Generate a strong ENCRYPTION_KEY: 64-character hex string (32 random bytes).
  • Set up JWT keys: Generate an Ed25519 key pair for JWT signing. See agent_docs/key-management.md for details.
  • Restrict CORS_ORIGINS in production to your exact frontend domain.
  • Use TLS for NATS and Dgraph connections in production.