Deploy and test scheduler and HTTP features on NixOS¶
Use a flake revision containing the features you need. The status page identifies this documentation's integrated scheduler hardening boundary. The examples are configuration guidance, not evidence of passing combined-stack VM validation.
Enable HTTP functions in the server module¶
Import the flake module and choose its server package:
{ inputs, ... }: {
imports = [ inputs.mcp-js.nixosModules.mcp-js ];
services.mcp-js = {
enable = true;
package = inputs.mcp-js.packages.x86_64-linux.default;
settings = {
http_port = 8080;
bind_host = "127.0.0.1";
heap_store = "none";
jwks_url = "https://identity.example.com/.well-known/jwks.json";
};
};
systemd.services.mcp-js.environment.MCP_V8_HTTP_FUNCTIONS_DIR =
"/var/lib/mcp-js/http-functions";
}
Replace the JWKS URL with your existing issuer and use your existing TLS ingress.
The module creates /var/lib/mcp-js through StateDirectory and runs as a dynamic
user. Its generated settings are server config keys. HTTP function enablement is
an environment variable, not an invented Nix module option. Definitions persist
in the service state directory in single-node mode.
The module opens configured HTTP/SSE/cluster ports in the NixOS firewall. Check actual listener reachability and ingress policy for your deployment. The ordinary server uses legacy dynamic cluster networking; do not infer the scheduler runner's fixed-voter bearer protection applies to those ports. Keep them private. Cluster HTTP functions use replicated registry state, accept admission on the leader, and require quorum; setting the directory alone does not configure Raft. See clustering setup.
Deploy a dedicated scheduled worker separately¶
The server module can also run the dedicated worker using
MCP_SCHEDULED_WORKER_CONFIG, HTTP mode, and heap_store = "none". That mode
replaces ordinary MCP/REST/HTTP-function routes, so use a separate service if you
need both surfaces. Put nonsecret worker JSON in an operator-managed file and set
its namespace/worker ID to match the runner. Preserve its dedicated admission
store across restarts.
Provide the existing bearer credentials through a protected systemd
EnvironmentFile; do not embed secrets in Nix strings or the world-readable Nix
store. Keep only environment-variable names in JSON. Keep worker, callback,
and Raft network boundaries distinct; remote callback listeners need existing TLS
termination. The runner is packaged separately as
packages.x86_64-linux.scheduler-runner; there is no automatic scheduler runner
NixOS service or scheduling option in services.mcp-js. Operators must supply
runner units/configuration and either managed stdin or the optional loopback
HTTP/MCP management listener themselves. For the listener, supply distinct
operator and optional recovery credentials through the protected environment
file; the worker and admission credentials cannot authorize management. The
management listener adds no firewall opening or NixOS module option.
See runner configuration.
Do not clone active worker stores, reset identity-bound state, or restore stale consensus snapshots as a fresh authoritative cluster. Retain stores on uncertainty. There is no automatic schema migration or log compaction.
Run the actual VM checks¶
On a Linux host with Nix and usable KVM, run checks separately to limit memory:
nix build .#checks.x86_64-linux.http-functions-test --no-link -L
nix build .#checks.x86_64-linux.http-functions-cluster-test --no-link -L
nix build .#checks.x86_64-linux.scheduler-disable-test --no-link -L
nix build .#checks.x86_64-linux.scheduler-cancellation-test --no-link -L
nix build .#checks.x86_64-linux.scheduler-disabled-cancellation-test --no-link -L
| Check | Observes |
|---|---|
http-functions-test |
NixOS service, JWKS, opt-in/isolation, CRUD/ETags, imports, policy header injection, bounds/timeouts, fresh globals, restart and VM reboot |
http-functions-cluster-test |
Three nodes, leader crash, revision recovery, quorum loss, restore/full restart, tombstone/ABA protection |
scheduler-disable-test |
Accepted work finishes; next scheduled occurrence is suppressed |
scheduler-cancellation-test |
Actual Engine heartbeat stops, durable Cancelled, schedule stays enabled and next run succeeds |
scheduler-disabled-cancellation-test |
Disable and cancellation remain independent |
The scheduler checks boot three actual runner processes and an actual Engine in each VM; the HTTP probe observes effects rather than replacing the worker. The harness advances wall time to real cron boundaries inside the guest while keeping monotonic deadlines. The tests do not establish external-effect rollback, power- loss durability, tenant isolation, or every cancellation/takeover race.
Check native behavior and documentation¶
cargo test --locked -p server --lib http_functions -- --test-threads=1
cargo test --locked -p server --lib scheduled_runtime_tests
cargo test --locked -p server --test http_function_management_e2e --test jwks_auth_e2e -- --test-threads=1
cargo test --locked --manifest-path scheduler-core/Cargo.toml
cargo test --locked --manifest-path scheduler-runner/Cargo.toml
nix build .#packages.x86_64-linux.docs --no-link -L
nix build .#checks.x86_64-linux.docs-generated-check --no-link -L
The docs package regenerates API/CLI/config/tool references before a strict MkDocs build; the drift check compares generated artifacts to their checked-in sources. Follow the repository's Docs Check workflow for OAuth contract, compatibility, link, and browser checks. Keep generated reference pages generated; feature explanations and recipes belong in the hand-written pages.