WASM checks
Fork-per-check works, but it isn’t free, and a check plugin is still arbitrary code running with whatever the process’s ambient permissions happen to be. WASM checks give you a third option: a single portable module, sandboxed by default, that runs without spawning a process at all.
The sandbox
Section titled “The sandbox”jaque runs WASM modules on wazero, a pure-Go runtime — no CGo, consistent with the single-binary invariant. By default a module gets:
- No filesystem, no network.
#WASMCheck— the CUE shape awasmcheck is written against — accepts onlymoduleandargs; there is no config field for a directory mount or a network grant. Those grants exist only as Go-API options (WithDirMount,WithReadOnlyDirMount) on the runner a Go embedder constructs directly, not as anything a CUE config file can reach. So today, every check written in config gets no filesystem and no network, full stop. - A memory cap. WASM’s own linear-memory pages are bounded so a runaway allocation can’t OOM the host process.
- A hard deadline, enforced via context — a module that hangs is
killed like anything else that exceeds
timeout.
services: custom: check: { type: "wasm" module: "checks/disk-usage.wasm" args: ["/", "80", "95"]}module is a path to a .wasm file, compiled once at startup.
ABI and limits
Section titled “ABI and limits”A check module is a WASI (wasip1) command module — it exports _start
and is instantiated fresh per run — speaking the same protocol as legacy
exec plugins: exit code 0-3 maps to OK/WARNING/CRITICAL/UNKNOWN
(state.NewStatus), and stdout is check output text with an optional |
splitting off perfdata, same convention as everywhere else. Any language
that compiles to wasip1 writes a jaque plugin with zero jaque-specific
code.
Guest linear memory is capped at 128 MiB (2048 wasm pages of 64 KiB each)
by default; growth beyond the cap fails inside the guest, never outside
it. A Go embedder can raise or lower this per runner, but nothing in
#WASMCheck exposes the cap to a CUE config.
Why this exists alongside legacy exec
Section titled “Why this exists alongside legacy exec”WASM checks aren’t a replacement for the Nagios exec protocol — see Legacy exec plugins, which stays supported forever. They’re the option when you’re writing something new and want it distributable as one file, sandboxed from the host by construction rather than by convention, and runnable without a subprocess fork.