In this section
Operations / evidence first

Runbook

Build eBPF before userspace, install one binary, authorize only its setup worker, and verify the foreground contract rather than trusting a successful compile.

Build

The single binary embeds the eBPF ELF, so eBPF must be built first. Enter the pinned development environment before running project commands.

nix develop .#ebpf -c bash -c \
  'cd heimdall-ebpf && cargo-nightly build --locked --release'
nix develop -c just verify

Run the current and Linux 6.6 LTS disposable real-eBPF VMs when changing cgroups, DNS, relay correlation, routing, or kernel programs. Both execute the same static binary and full daemonless acceptance suite:

nix develop -c just test-vm

Install

For a tagged static release, verify the checksum and use the bundled atomic installer. See Install and upgrade for download and rollback commands. For a source build:

sudo install -Dm755 target/release/heimdall /usr/local/bin/heimdall
heimdall init

# Add with visudo after replacing USERNAME:
# USERNAME ALL=(root) NOPASSWD: /usr/local/bin/heimdall __setup-worker
sudo chmod 0440 /etc/sudoers.d/heimdall
sudo visudo -cf /etc/sudoers.d/heimdall

Replace USERNAME. The worker receives one strict request over stdin, transfers map/link FDs, and drops privilege before the command starts. Runtime TLS retains that unprivileged helper only for the run lifetime. No service is required.

Smoke test

heimdall agent | jq .
heimdall config validate
heimdall run -- curl -fsS https://example.com
Exit status is part of the contract. The wrapped command's exit status is Heimdall's exit status. Owner-addressed SIGHUP, SIGINT, SIGQUIT, and SIGTERM are forwarded to the child while Heimdall remains alive to finalize evidence. Setup authorization is non-interactive and fails before execution.

Acceptance coverage

The VM exercises real eBPF attachment, fake/system DNS, SOCKS5 TCP/UDP, QUIC, descendants, signals, concurrent isolated runs, runtime and relay TLS, provenance-linked HTTP/1 header evidence and credential masking, log rotation, orphan recovery, exact preview/apply retention, fail-closed errors, parent-death cgroup cleanup, and link cleanup.

Local release verification is authoritative. From a clean main checkout that exactly matches origin/main, run just release-github. It validates curated highlights, the structured version changelog and known limitations before running source verification, the current and Linux 6.6 LTS real-eBPF guests sequentially, and both package checks. Only then does it create the tag and publish the generated release notes, archives, and checksums. GitHub Pages or Actions status is not release evidence.

The same local transaction builds and checksums the npm tarball and x86_64/aarch64 PyPI wheels. Publishing the GitHub Release triggers thin npm and PyPI OIDC workflows that upload only those immutable assets; Actions does not rebuild Heimdall and routine publication needs no registry login, write token, 2FA link, or second dispatch.

EvidenceWhat it proves
just verifyBuild, format, lint, dependency, unit, and userspace gates.
just test-packagex86_64/aarch64 static linkage, architecture and checksum integrity, npm/PyPI installation, aarch64 emulated CLI, and x86_64 native install/upgrade/rollback.
just test-vmThe static release binary on the real kernel daemonless data path.
heimdall agentConfig, execution ownership, capabilities, and repair actions.
heimdall logs summaryLow-cardinality run health, sequence loss, active flows, failures, and protocol counters.
heimdall logs verifyPer-run JSONL sequence, schema, segment, and blob integrity.

Performance baseline

nix develop -c just benchmark-vm

The current and Linux 6.6 LTS disposable real-eBPF VMs each emit one heimdall.benchmark/v1 document after measuring cold start, direct TCP, proxied TCP/UDP, relay TLS, maximum RSS, 1/10/50 concurrent starts, event integrity, and sustained direct/proxied TCP, proxied UDP, transport-capture, and relay-plaintext-capture throughput. Each throughput record includes bytes, elapsed time, bytes per second, and its capture/decrypt boundary. Event integrity requires zero incomplete runs, sequence gaps, out-of-order records, active or failed flows, and error events. Results are specific to the reported VM, architecture, kernel, and CPU count; they are environment baselines, not universal performance claims.

Diagnose failures

  1. Run heimdall agent and preserve its JSON even when it exits 1.
  2. Follow actions.validate as an argv array.
  3. Check the exact sudoers path if foreground setup is denied.
  4. Preview with config explain, then reproduce with a minimal command and the same policy.

Before relay trust, compare the DER SHA-256 in tls init-ca ca_cert_sha256 with agent.config.decrypt.ca_cert_sha256. Trust only that public certificate in the explicitly wrapped client; never expose the signing key.

For relay TLS, tls_upstream_certificate_invalid means Heimdall rejected the remote peer and upstream verification must not be weakened. tls_upstream_client_auth_required means the verified upstream requires a client certificate relay mode cannot forward, so use runtime mode or disable decryption. tls_downstream_certificate_rejected is an explicit client certificate alert. tls_downstream_closed_without_close_notify is ambiguous; preserve the wrapped command's stderr and exit status before diagnosing trust.

Do not equate config validity with connectivity. A real acceptance check must exercise the selected policy through heimdall run.