Skip to content

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)

  1. Environment variables — highest priority, always win
  2. Runtime YAML files — loaded from CLI args (e.g., wanaku-server --pipeline-config praxis.yaml --wanaku-config wanaku.yaml)
  3. Embedded defaults — compiled into the binary

Core Environment Variables

These control core server behavior:

VariableDefaultPurpose
WANAKU_MGMT_LISTEN0.0.0.0:8080Management API listen address (host:port)
WANAKU_INFERENCE_UPSTREAM127.0.0.1:11434Upstream for the inference-proxy pipeline (port 8083), an OpenAI-compatible passthrough. Clients call this port directly and supply their own bearer token.
WANAKU_PERSIST_BACKENDfileFile-based registry persistence. Set to "none" to disable persistence.
WANAKU_PERSIST_PATH$HOME/.wanaku/serverDirectory 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_INTERVAL30Interval, 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:

bash
export WANAKU_MGMT_LISTEN=0.0.0.0:9091
export WANAKU_PERSIST_BACKEND=file
export WANAKU_PERSIST_PATH=/var/lib/wanaku/registry
wanaku-server

Management API Listen Address

The WANAKU_MGMT_LISTEN variable controls where the management API binds. Format: host:port.

Bind to all interfaces (default):

bash
export WANAKU_MGMT_LISTEN=0.0.0.0:8080

Bind to localhost only:

bash
export WANAKU_MGMT_LISTEN=127.0.0.1:8080

Useful when running Wanaku behind a reverse proxy (nginx, Envoy) that handles external traffic.

Bind to specific IP:

bash
export WANAKU_MGMT_LISTEN=10.0.1.42:8080

Registry 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:

bash
export WANAKU_PERSIST_BACKEND=file
export WANAKU_PERSIST_PATH=/data/registry

On startup, the server loads registry.json from WANAKU_PERSIST_PATH. On shutdown (SIGTERM, SIGINT), it writes back.

Format:

json
{
  "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:

bash
export WANAKU_PERSIST_BACKEND=none

Evaluator 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:

json
{
  "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:

bash
export WANAKU_UI_PATH=/absolute/path/to/ui/dist
wanaku-server

The 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:

bash
export WANAKU_FORWARD_HEADERS=Authorization,DPoP

Per-tool override — set the wanaku.forward_headers label on a ToolEntry:

json
{
  "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:

json
{
  "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 Authorization forwarding 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:

VariableDefaultPurpose
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.

VariableDefaultPurpose
WANAKU_INTERACTION_CAPACITY1000Maximum 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:

bash
export WANAKU_INFERENCE_UPSTREAM=127.0.0.1:11434

The 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:

bash
wanaku-server --pipeline-config /path/to/custom-praxis.yaml

Format:

yaml
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_response

Listener Configuration

Change MCP port:

yaml
listeners:
  - name: mcp
    address: "0.0.0.0:8083"  # Bind to all interfaces, port 8083
    filter_chains: [mcp_router]

Add TLS:

yaml
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:

yaml
- 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):

yaml
- filter: mcp
  on_invalid: continue  # REQUIRED for OPTIONS preflight
  max_body_bytes: 1048576  # 1MB limit

The on_invalid: continue setting allows OPTIONS requests (which have no body) to pass through without failing validation. Without it, CORS preflight fails.

Custom filter:

yaml
- filter: wanaku_custom_feature
  enabled: true
  config:
    some_option: value

Feature 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:

  1. Put CORS first. Otherwise, error responses do not contain CORS headers.
  2. MCP must be before wanaku_namespace — namespace filter reads mcp.method metadata
  3. wanaku_namespace must be before tool/resource/prompt filters — they all read wanaku.namespace
  4. 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:

bash
wanaku-server --pipeline-config /path/to/praxis.yaml --wanaku-config /path/to/wanaku.yaml

Format:

yaml
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 configuration
  • llm_connections — named LLM connections (model/url/api_key) for evaluators; config-only, never exposed via the management API
  • evaluators — evaluator feature configuration
  • action_policy — declarative action-policy rules
  • governance — global governance posture and namespace overrides
  • plugins — 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):

yaml
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)

bash
# No persistence, embedded UI, inference backend for LLMs
export WANAKU_PERSIST_BACKEND=none
export WANAKU_INFERENCE_UPSTREAM=http://localhost:11434
wanaku-server

Kubernetes

ConfigMap:

yaml
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:

yaml
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-registry

Debugging Configuration

Enable Trace Logs

bash
RUST_LOG=trace wanaku-server

This logs all filter decisions, metadata reads/writes, and registry operations. Output is verbose — use sparingly.

Filter-specific logs:

bash
RUST_LOG=wanaku_filters=trace wanaku-server

Verify 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.

  • 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