Fluxheim/Docs/WASM extensions

WASM extensions

Dedicated Wasm build based on the full production profile, with bounded policy hooks, ACME, metrics, and OpenTelemetry

What it gives you

Dedicated Wasm build based on the full production profile, with bounded policy hooks, ACME, metrics, and OpenTelemetry.

FeatureUse it for
Access decisionsLive native HTTP/1 access-decision hooks use priority ordering, first-deny-wins composition, and fail-closed behaviour.
Header hooksrequest-headers and response-headers hooks can set or remove only allow-listed synthetic headers such as the policy-tier example.
Route decisionsroute-decision hooks can continue, deny, or select only configured matching canary and mirror route branches.
Cache decisionscache-lookup hooks can continue, pass, bypass, or deny. cache-store hooks can continue, skip storage, or deny before memory/disk cache writes.

Run

Use the dedicated profile-wasm archive or image; the normal full build intentionally remains Wasm-free.

The official Wasm image contains the runtime but no operator plugins. Mount reviewed modules read-only and pin every module by SHA-256.

podman pull ghcr.io/valkyoth/fluxheim:v1.8.0-wasm

podman run --rm \
  -v ./fluxheim.toml:/etc/fluxheim/fluxheim.toml:ro,Z \
  -v /srv/infra/fluxheim/plugins:/etc/fluxheim/plugins:ro,Z \
  ghcr.io/valkyoth/fluxheim:v1.8.0-wasm

Approved plugin roots

Plugin files must be absolute, regular files below approved roots, without symlinked files or parent paths.

[wasm]
enabled = true
plugin_roots = ["/etc/fluxheim/plugins"]
max_total_concurrent_executions = 256
max_total_preview_concurrent_executions = 32
max_total_cache_concurrent_executions = 256

[[wasm.plugins]]
name = "security_headers"
path = "/etc/fluxheim/plugins/security_headers.wasm"
sha256 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
abi = "fluxheim-policy-v1"
host_call_namespace = "fluxheim-policy-v1"
phases = ["response-headers"]
fail_mode = "fail-closed"

[[wasm.attachments]]
plugin = "security_headers"
vhost = "example"
priority = 100
phases = ["response-headers"]

Bounded execution

Fuel, memory, table, instance, compile-timeout, compile-worker, and per-call watchdog limits keep the sandbox bounded.

[wasm.plugins.limits]
max_module_bytes = "1MiB"
max_compiled_artifact_bytes = "32MiB"
max_memory_bytes = "16MiB"
max_table_elements = 10000
fuel = 5000000
timeout_ms = 50
compile_timeout_ms = 500

Production notes

A read-only container mount does not protect its host files. Keep the host config and plugin directory under trusted, non-writable ownership.

  • Public plugin manifests must include a fixed SHA-256 digest. At most two modules compile at once across the process. Compiled output defaults to a 32 MiB limit and cannot exceed 256 MiB.
  • Keep config files and every existing parent directory under trusted ownership and not writable by group or other users.
  • Pin release versions or image digests.
  • Keep secrets in files, environment, or container secrets, not in public docs.

Full docs on GitHub

English (EU)