Configuration
Wanaku uses environment variables and two optional YAML files. It does not use a properties file. Set environment variables in the container orchestrator or systemd unit. Specify configuration files only when you need custom settings.
Configuration Sources (Precedence Order)
- Environment variables — highest priority, always win
- Runtime YAML files — loaded from CLI args (e.g.,
wanaku-server --pipeline-config praxis.yaml --wanaku-config wanaku.yaml) - Embedded defaults — compiled into the binary
Core Environment Variables
These control core server behavior:
| Variable | Default | Purpose |
|---|---|---|
WANAKU_MGMT_LISTEN | 0.0.0.0:8080 | Management API listen address (host:port) |
WANAKU_INFERENCE_UPSTREAM | 127.0.0.1:11434 | Upstream for the inference-proxy pipeline (port 8083), an OpenAI-compatible passthrough. Clients call this port directly and supply their own bearer token. |
WANAKU_PERSIST_BACKEND | file | File-based registry persistence. Set to "none" to disable persistence. |
WANAKU_PERSIST_PATH | $HOME/.wanaku/server | Directory where Wanaku reads and writes registry.json |
WANAKU_UI_PATH | (unset = embedded) | Filesystem path to admin UI override (use for local dev) |
WANAKU_CORS_ORIGIN | * | Value for Access-Control-Allow-Origin on all HTTP responses (management API, MCP endpoint, inference proxy, and CORS preflight) |
WANAKU_AUTH_ISSUER | (unset = disabled) | OIDC issuer URL for RFC 9728 metadata endpoint |
WANAKU_FORWARD_HEADERS | (unset = none) | Comma-separated list of HTTP header names to forward from incoming MCP requests to downstream tool invocations (e.g., Authorization,DPoP). Per-tool overrides via the wanaku.forward_headers label. |
WANAKU_FORWARD_HEALTHCHECK_INTERVAL | 30 | Interval, in seconds, of the background loop that re-probes forwards currently marked unavailable and flips them back to available once they recover — no manual refresh required. Set to 0 to disable the loop. |
Example:
export WANAKU_MGMT_LISTEN=0.0.0.0:9091
export WANAKU_PERSIST_BACKEND=file
export WANAKU_PERSIST_PATH=/var/lib/wanaku/registry
wanaku-serverManagement API Listen Address
The WANAKU_MGMT_LISTEN variable controls where the management API binds. Format: host:port.
Bind to all interfaces (default):
export WANAKU_MGMT_LISTEN=0.0.0.0:8080Bind to localhost only:
export WANAKU_MGMT_LISTEN=127.0.0.1:8080Useful when running Wanaku behind a reverse proxy (nginx, Envoy) that handles external traffic.
Bind to specific IP:
export WANAKU_MGMT_LISTEN=10.0.1.42:8080Registry Persistence
File persistence is enabled by default. Wanaku reads and writes $HOME/.wanaku/server/registry.json. Set a different directory when the default location is not suitable:
export WANAKU_PERSIST_BACKEND=file
export WANAKU_PERSIST_PATH=/data/registryOn startup, the server loads registry.json from WANAKU_PERSIST_PATH. On shutdown (SIGTERM, SIGINT), it writes back.
Format:
{
"tools": [],
"resources": [],
"prompts": [],
"namespaces": [],
"forwards": []
}Limitation: Wanaku writes the snapshot during an orderly shutdown. If the process stops because of SIGKILL, an out-of-memory error, or a panic, changes since the last snapshot are lost. File persistence supports one writer. Use a shared external persistence implementation before you run multiple replicas.
To disable persistence:
export WANAKU_PERSIST_BACKEND=noneEvaluator Revision Persistence
Evaluator revision history uses the same persistence configuration as the registry. When WANAKU_PERSIST_BACKEND=file, the server reads and writes evaluator-revisions.json in WANAKU_PERSIST_PATH. When persistence is disabled, revision history stays in memory and is lost on restart.
The server writes the file after every revision change, not only at shutdown. A revision created or activated through the management API therefore survives an abrupt stop.
On startup the server loads the persisted history. The wanaku.yaml configuration is the source of truth for the live runtime. If the startup configuration matches the persisted active revision, the server re-validates and recompiles that revision and installs it, without recording a new revision. If the startup configuration differs, the server activates it as a new revision.
When the server re-applies an existing active revision, it re-validates the evaluator names, triggers, and LLM connection references and recompiles the WASM processors and result schemas. If the revision no longer validates or compiles on the current host, the server leaves the runtime configuration empty and logs the error. The server does not append a revision in this case, so a repeatedly failing host does not churn the bounded history.
The server keeps a bounded history of the most recent 50 revisions. Older revisions are dropped. Rejected revisions are also persisted, so a failed activation stays visible in the history.
If the startup wanaku.yaml evaluator configuration is identical to the persisted active revision, the server keeps that revision active and creates no new revision. A restart with an unchanged configuration does not grow the history.
Format:
{
"revisions": [],
"active_id": null,
"next_id": 1
}Limitation: File persistence supports one writer. Use a shared external persistence implementation before you run multiple replicas.
Action Policy Revision Persistence
Action-policy revision history uses the same persistence settings. Wanaku writes action-policy-revisions.json in WANAKU_PERSIST_PATH. The action-policy stream is independent from the evaluator stream.
Wanaku writes the file after each revision change. Wanaku validates and installs the persisted active policy during startup. See Action Policies for the policy schema and lifecycle.
Admin UI Override
The admin UI is embedded in the binary. To serve UI files from a directory on disk instead of the embedded bundle:
export WANAKU_UI_PATH=/absolute/path/to/ui/dist
wanaku-serverThe server serves files from the specified directory instead of the embedded bundle.
Warning: Relative paths do not work. Use an absolute path.
Header Forwarding
By default, Wanaku does not forward any HTTP headers from incoming MCP requests to downstream tool invocations. To enable header forwarding (e.g., for gateway-mediated token exchange), configure an allowlist of header names.
Global allowlist — applies to all tool calls:
export WANAKU_FORWARD_HEADERS=Authorization,DPoPPer-tool override — set the wanaku.forward_headers label on a ToolEntry:
{
"name": "github-api",
"uri": "http://mcp-gateway:8080/mcp",
"type": "mcp-forward",
"labels": {
"wanaku.forward_headers": "Authorization,X-Third-Party-Token"
}
}Both lists are merged at runtime — a header is forwarded if it appears in either the global allowlist or the per-tool label. Header names are case-insensitive.
SEP-2243 argument injection — When a tool's input schema has properties annotated with x-mcp-header (SEP-2243), Wanaku automatically injects matching forwarded header values as tool arguments before forwarding. This ensures downstream MCP servers using @McpParamHeader receive the value correctly. This behavior is enabled by default and can be disabled per-tool:
{
"labels": {
"wanaku.forward_headers": "Authorization",
"wanaku.inject_header_args": "false"
}
}When disabled, headers are forwarded only as raw HTTP headers on the downstream connection — suitable for gateway scenarios where the gateway reads headers directly.
Use case: A gateway (Envoy ExtProc, IBM ContextForge) sits between Wanaku and a protected downstream API. The gateway performs token exchange (e.g., Keycloak STS) using the Authorization header from the original request. Wanaku forwards the header so the gateway has a subject_token to exchange.
Security considerations:
- Headers that would corrupt the downstream HTTP request (
host,content-type,content-length,transfer-encoding,connection) and rmcp-reserved headers (accept,mcp-session-id,last-event-id) are always blocked, even if they appear in the allowlist. - When
Authorizationforwarding is enabled, anyone with management API access can register a tool pointing to an arbitrary URL — the caller's bearer token would then be forwarded to that URL. Secure the management API (authentication, network isolation) before enabling credential forwarding in production.
Feature-Specific Environment Variables
Features (mcp-metadata, evaluator, etc.) define their own environment variables.
Authentication with oauth2-proxy
Wanaku uses oauth2-proxy for authentication. The only auth-related configuration in Wanaku itself is the OIDC issuer URL:
| Variable | Default | Purpose |
|---|---|---|
WANAKU_AUTH_ISSUER | (unset = disabled) | OIDC issuer URL (e.g., http://localhost:8543/realms/wanaku) |
When set, the endpoint /.well-known/oauth-protected-resource/{namespace}/mcp returns OAuth server metadata. When unset, the endpoint returns 404.
See Authentication for full oauth2-proxy setup instructions.
Intercept Feature
The intercept feature records request/response interactions for conversation tracking. Evaluators use this history to provide context to LLM operations.
| Variable | Default | Purpose |
|---|---|---|
WANAKU_INTERACTION_CAPACITY | 1000 | Maximum number of interactions kept in the in-memory store |
Inference Proxy
The inference proxy is a raw, transparent reverse proxy (port 8083) to an OpenAI-compatible backend. It forwards requests as-is, including the caller's own Authorization header — Wanaku does not inject or store a credential for it. Point it at a backend with WANAKU_INFERENCE_UPSTREAM:
export WANAKU_INFERENCE_UPSTREAM=127.0.0.1:11434The Admin UI's LLM Chat page calls this port directly with a key you supply in the browser. See Management API for the endpoint shape.
Because the proxy forwards the Origin header unchanged, the backend's own origin policy still applies. Ollama, for example, rejects browser-origin requests by default — set OLLAMA_ORIGINS on the Ollama side to allow the Admin UI's origin. Wanaku's own CORS filter on port 8083 controls only the response back to the browser; it does not affect what the backend accepts.
Wanaku also rewrites the outgoing Host header to match WANAKU_INFERENCE_UPSTREAM, instead of forwarding the browser's original Host. Backends that route by hostname (for example, a TLS-terminating ingress in front of a hosted LLM API) reject a mismatched Host. Note: like WANAKU_CORS_ORIGIN, this override applies only to the embedded default pipeline config. A custom --pipeline-config must define its own headers filter with request_set on the inference_proxy chain to get this behavior.
WANAKU_INFERENCE_UPSTREAM may include a path, for example https://openrouter.ai/api. Wanaku prepends that path to every request it forwards — a request to /v1/chat/completions on port 8083 reaches https://openrouter.ai/api/v1/chat/completions upstream. The same custom---pipeline-config caveat applies: this requires a path_rewrite filter with add_prefix on the inference_proxy chain.
Pipeline Config File (praxis.yaml)
The pipeline configuration defines listeners, filter chains, and filter-specific settings. This YAML file uses the native Praxis configuration format.
Override: Pass with --pipeline-config:
wanaku-server --pipeline-config /path/to/custom-praxis.yamlFormat:
listeners:
- name: mcp
address: "127.0.0.1:8081"
filter_chains: [mcp_router]
filter_chains:
- name: mcp_router
filters:
- filter: cors
allow_origins: ["*"]
- filter: mcp
on_invalid: continue
- filter: wanaku_namespace
- filter: wanaku_well_known
- filter: wanaku_mcp_init
- filter: wanaku_action_policy
- filter: wanaku_evaluator
- filter: wanaku_tool_list
- filter: wanaku_tool_call
- filter: wanaku_resource_list
- filter: wanaku_resource_read
- filter: wanaku_prompt_list
- filter: wanaku_prompt_get
- filter: static_responseListener Configuration
Change MCP port:
listeners:
- name: mcp
address: "0.0.0.0:8083" # Bind to all interfaces, port 8083
filter_chains: [mcp_router]Add TLS:
listeners:
- name: mcp
address: "0.0.0.0:8081"
tls:
cert_path: /etc/wanaku/cert.pem
key_path: /etc/wanaku/key.pem
filter_chains: [mcp_router](Note: TLS support depends on Praxis version. Check praxis-proxy-core docs.)
Filter Configuration
CORS filter:
- filter: cors
allow_origins: ["http://localhost:3000", "https://app.example.com"]
allow_methods: ["GET", "POST", "OPTIONS"]
allow_headers: ["Content-Type", "Authorization"]Note: The WANAKU_CORS_ORIGIN env var overrides allow_origins in the embedded default pipeline config at startup. If you provide a custom pipeline config via --pipeline-config, allow_origins in that file is used as-is — the env var only applies to the embedded default.
MCP filter (praxis-ai):
- filter: mcp
on_invalid: continue # REQUIRED for OPTIONS preflight
max_body_bytes: 1048576 # 1MB limitThe on_invalid: continue setting allows OPTIONS requests (which have no body) to pass through without failing validation. Without it, CORS preflight fails.
Custom filter:
- filter: wanaku_custom_feature
enabled: true
config:
some_option: valueFeature filters read their config from this section. The exact schema depends on the feature.
Filter Ordering
The order in filters: matters. The pipeline executes filters top-to-bottom.
Critical rules:
- Put CORS first. Otherwise, error responses do not contain CORS headers.
- MCP must be before wanaku_namespace — namespace filter reads
mcp.methodmetadata - wanaku_namespace must be before tool/resource/prompt filters — they all read
wanaku.namespace - static_response must be last — catch-all for unhandled requests
If you reorder filters and requests start failing, check the logs. The filter that needed metadata will error with "missing metadata key".
Wanaku Config File (wanaku.yaml)
The Wanaku configuration bootstraps core registry entries and feature settings at startup. This file is optional. If you omit it, Wanaku can still restore the registry from the default file snapshot. If no snapshot exists, the registry starts empty.
Location: Pass with --wanaku-config:
wanaku-server --pipeline-config /path/to/praxis.yaml --wanaku-config /path/to/wanaku.yamlFormat:
forwards:
- name: "upstream-mcp"
address: "http://upstream:8080/mcp"
plugins:
- id: "customer-management"
services:
customer-api:
target: "http://customer-service:8080"Wanaku loads these top-level sections from wanaku.yaml:
forwards— core forward bootstrap configurationllm_connections— named LLM connections (model/url/api_key) for evaluators; config-only, never exposed via the management APIevaluators— evaluator feature configurationaction_policy— declarative action-policy rulesgovernance— global governance posture and namespace overridesplugins— plugin service mappings owned by the plugins feature
The Governance Posture model defines fail-safe defaults and namespace overrides. Wanaku validates the section during startup. Invalid governance configuration stops startup.
Wanaku discovers tools, resources, and prompts from the configured forwards.
Evaluator configuration (see Evaluator Engine for full details):
llm_connections:
- name: "local-llama"
model: "llama3.2"
url: "http://localhost:11434/v1"
evaluators:
- name: "safety-gate"
trigger:
method: "tools/call"
llm:
operation: classify
prompt: "Classify this tool call..."
connection: "local-llama"
result_schema: # Optional JSON Schema for LLM output validation
type: object
properties:
level: { type: string }
reason: { type: string }
required: ["level", "reason"]
processor:
path: "/wasm/safety-gate.wasm"When result_schema is set, the host validates LLM output against the schema and retries once with a correction prompt on mismatch.
Common Configuration Patterns
Development (Local Machine)
# No persistence, embedded UI, inference backend for LLMs
export WANAKU_PERSIST_BACKEND=none
export WANAKU_INFERENCE_UPSTREAM=http://localhost:11434
wanaku-serverKubernetes
ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: wanaku-config
data:
praxis.yaml: |
listeners:
- name: mcp
address: "0.0.0.0:8081"
filter_chains: [mcp_router]
filter_chains:
- name: mcp_router
filters:
- filter: cors
- filter: mcp
on_invalid: continue
# ... rest of pipeline
wanaku.yaml: |
forwards:
- name: "upstream-mcp"
address: "http://upstream:8080/mcp"Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: wanaku-server
spec:
replicas: 1 # File snapshots support one writer. Do not share this volume across replicas.
selector:
matchLabels:
app: wanaku-server
template:
metadata:
labels:
app: wanaku-server
spec:
containers:
- name: wanaku
image: wanaku-server:latest
env:
- name: WANAKU_MGMT_LISTEN
value: "0.0.0.0:8080"
- name: WANAKU_PERSIST_BACKEND
value: "file"
- name: WANAKU_PERSIST_PATH
value: "/data/registry"
volumeMounts:
- name: config
mountPath: /etc/wanaku
- name: data
mountPath: /data
volumes:
- name: config
configMap:
name: wanaku-config
- name: data
persistentVolumeClaim:
claimName: wanaku-registryDebugging Configuration
Enable Trace Logs
RUST_LOG=trace wanaku-serverThis logs all filter decisions, metadata reads/writes, and registry operations. Output is verbose — use sparingly.
Filter-specific logs:
RUST_LOG=wanaku_filters=trace wanaku-serverVerify Environment Variables
The server does not reject unknown environment variable names. A misspelled name has no effect, and the server uses the default value. Enable trace logs to verify the values that the server uses.
Related Docs
- Architecture — understand the filter pipeline and registry
- Authentication — oauth2-proxy setup and Keycloak configuration
- Features — enable evaluators and create custom features
- Management API — API routes that respect configuration
- FAQ — troubleshooting common issues