Docs Build from Source

Build from Source

Build sipnab from source: cargo, the feature-flag matrix, release profile, and cross-compilation.

On this page

Most users should install a binary. Build from source when you need a custom feature set or target.

Cargo (from source)

cargo install sipnab --features full

Building from source

Build prerequisites

  • Rust 1.97+
  • libpcap headers (libpcap-dev on Debian/Ubuntu, libpcap-devel on RHEL/Fedora)
  • pkg-config (for libpcap detection during build)

Install from a checkout, with capabilities

cargo install has no post-install hook, so a source install leaves you to run --setup-caps yourself. scripts/install-from-source.sh does both:

# Run all of these, in order.
git clone https://github.com/NormB/sipnab.git
cd sipnab
./scripts/install-from-source.sh --features full

It runs cargo install --path . --bin sipnab (forwarding any arguments), then on Linux invokes the binary’s own --setup-caps so live capture works without sudo. Non-Linux platforms skip the capability step and point you at sudo.

This is a source install and is distinct from the one-line installer at https://sipnab.com/install.sh, which downloads a prebuilt release binary and compiles nothing.

Basic build (TUI only, default features)

# Run all of these, in order.
git clone https://github.com/NormB/sipnab.git
cd sipnab
cargo build --release
sudo cp target/release/sipnab /usr/local/bin/

Full-features build

cargo build --release --features full

Debug build with logging

SIPNAB_LOG=trace cargo run -- -N -I test.pcap

Feature flags

sipnab uses Cargo feature flags to control optional capability. The default build includes native, tui, audio, and metrics.

FeatureDescriptionDependencies
nativeLive capture, file capture, output writers, signal handling, CLI parser. Required (directly or transitively) by tui, hep, metrics, api, mcp, mcp-http, and plugins; not required by tls, audio, or wasm. Included by default.pcap, clap, crossbeam-channel, libc, pcap-file, tracing-subscriber
tuiInteractive terminal UI (ratatui + crossterm). Included by default.native, ratatui, crossterm, unicode-width
audioRTP audio playback in the TUI + WAV export. Included by default. Builds the separate sipnab-audio plugin (libsipnab_audio.so) that the binary dlopens lazily; the binary itself does not link libasound.so.2.libloading, libc (plugin: rodio)
tlsTLS/DTLS decryption and SRTP key extraction (pure Rust)ring, rustls, aes, cbc, zeroize
hepHEP v3 send + v2/v3 receive (Homer Encapsulation Protocol)native
apiREST API + Prometheus metrics endpoint. Runs on a background thread in the sipnab process, sharing its address space — not a separate OS process, so treat the bind address and API key accordingly.native, axum, tokio
mcpModel Context Protocol server, stdio transport. Lets an AI agent (Claude Code, Claude Desktop, …) drive sipnab.native, tokio, rmcp
mcp-httpMCP server over HTTP (Streamable-HTTP). Adds the --mcp-transport http option.mcp, api, rmcp/transport-streamable-http-server
metricsStandalone Prometheus /metrics server: a raw TCP listener and plain threads, no axum/tokio, so scraping does not drag in the api feature or its async runtime. Included by default.native, base64
pluginsWASM plugin host (--plugin): sandboxed third-party dialog detectionsnative, wasmi
bpfeBPF uprobe backend for --uprobe-tls. The only backend that can report the peer address a TLS session went out to, because it pairs each write with its tcp_sendmsg; the default tracefs backend sees no socket and names a process instead. Outside full: the kernel half needs a nightly toolchain and bpf-linker. Linux only.native, aya
fullEverything: native + tui + audio + tls + hep + api + mcp + mcp-http + metrics + plugins. Not wasm, not bpf.all
wasmWebAssembly target for in-browser pcap analysiswasm-bindgen toolchain

Build with specific features. The TUI and TLS decryption only — no audio plugin, HEP, REST API or MCP compiled in:

cargo build --release --features tui,tls

A headless capture host — HEP listener, REST API and MCP over HTTP, with the TUI and audio left out because a server has no use for either:

cargo build --release --no-default-features --features native,hep,api,mcp,mcp-http

Everything — the feature set the official macOS releases ship:

cargo build --release --features full

The published *-linux-gnu binaries add one more. bpf is outside full because its kernel half needs a nightly toolchain and bpf-linker, and this project cannot demand either of a contributor — but the release runner installs both, so the Linux glibc tarballs, .deb and .rpm all ship it and --uprobe-tls --uprobe-backend bpf works on them out of the box:

Building it needs two things a stock toolchain does not have: a nightly toolchain carrying the rust-src component, installed with rustup, and bpf-linker on PATH — either cargo install bpf-linker or the prebuilt static tarball the release workflow uses. Pick the bpf-linker release that matches your LLVM: 0.9.13 pairs with LLVM 19, 0.11 with LLVM 23.1. Without either, the build still succeeds and prints a warning, and the resulting binary refuses --uprobe-backend bpf at run time rather than capturing nothing. Set SIPNAB_BPF_REQUIRED=1 to turn that warning into a build failure, which is what the release workflow does.

cargo build --release --features full,bpf

The musl tarballs and the macOS builds do not carry it: bpf costs about 576 KiB, which the static musl binary has no room for under the published size ceiling, and aya is a Linux-only dependency that would compile to nothing on macOS. sipnab --version lists every compiled feature, so it is how you tell which build you are holding.

What features do you need?

  • Most users (interactive analysis): cargo build --release – default features (native + tui + audio + metrics) give you interactive TUI, CLI mode, audio playback of captured RTP, and the standalone Prometheus endpoint.
  • CI/scripting only (no TUI): cargo build --release --no-default-features --features native – headless binary for automation pipelines.
  • MCP / AI-agent server: add mcp (stdio) or mcp,mcp-http (HTTP). See MCP Server for the runtime configuration.
  • Headless capture host with HEP + Prometheus + MCP: cargo build --release --no-default-features --features native,hep,api,mcp,mcp-http – the typical “fleet capture server” feature set, leaves out the TUI and audio playback you don’t need on a server.
  • Full installation: cargo build --release --features full – everything except wasm and bpf.
  • Peer addresses from a TLS uprobe: add bpf (cargo build --release --features full,bpf) – needs a nightly toolchain and bpf-linker at build time, and a kernel with CONFIG_DEBUG_INFO_BTF at run time. Already compiled into every published *-linux-gnu binary.
  • WASM/browser analysis: cargo build --release --features wasm – WebAssembly target for in-browser pcap analysis (see Analyze page).

Runtime dependencies

libasound.so.2 is an optional runtime dependency. The audio feature builds a separate plugin, libsipnab_audio.so, installed to /usr/lib/sipnab/ by the .deb (or placed next to the binary in dev builds). The sipnab binary dlopens this plugin only when you actually play a stream, so an audio-enabled binary starts fine on a host without libasound. If libasound (or the plugin) is missing, playback returns a clear error and you can still export the stream to a WAV file (F2). Only libpcap0.8 is a hard dependency:

apt-get install -y libpcap0.8

libasound is optional and only affects live playback. Skip it on a server: the binary still starts, and WAV export (F2) still works without it.

apt-get install -y libasound2

If you don’t need TUI audio playback on the host (typical for a --hep-listen / --api / --mcp server), install the -noaudio .deb, or build without the audio feature so the plugin is not built at all:

cargo build --release --no-default-features \
    --features native,tui,tls,hep,api,mcp,mcp-http

Audio on musl and Alpine

A statically linked musl build can never play audio, whatever features you compile in. The plugin arrives through dlopen, and static musl has no dynamic loader at all — dlopen returns NULL with “Dynamic loading not supported”. This is why the release builds the …-linux-musl tarballs without audio.

This matters because it fails quietly. cargo build --release --features full on Alpine succeeds, and the binary then reports:

sipnab <version> features: native,tui,audio,tls,hep,api,mcp,mcp-http,metrics,plugins

It advertises audio it cannot deliver. Nothing errors until you try to play a stream.

Two supported ways to build on Alpine, depending on what you want. Pick one — the two produce incompatible binaries.

Portable, no audio. This is what the release ships: static, zero runtime deps, runs on any Linux distro regardless of libc.

# Run all of these, in order.
apk add --no-cache musl-dev libpcap-dev pkgconf
cargo build --release --no-default-features \
    --features native,tui,tls,hep,api,mcp,mcp-http

Alpine-only, with audio. Dynamically linked, so dlopen works and the plugin loads. Needs alsa-lib at runtime and does NOT run on glibc hosts.

# Run all of these, in order.
apk add --no-cache musl-dev libpcap-dev pkgconf alsa-lib alsa-lib-dev
RUSTFLAGS="-C target-feature=-crt-static" cargo build --release --features full
RUSTFLAGS="-C target-feature=-crt-static" cargo build --release -p sipnab-audio

A CI job checks both paths on rust:1.97-alpine: the full test suite passes on Alpine with zero failures and the same test count as the glibc host, and in the dynamic build the plugin links libasound.so.2 and dlopens successfully while the sipnab binary itself still links only libpcap, libgcc and libc.

Cross-glibc compatibility

The release -gnu builds require glibc >= 2.36 (the floor the release workflow enforces on every gnu binary). On older hosts they refuse to start with version 'GLIBC_2.36' not found. The installer script handles this automatically — below the 2.36 floor it falls back to the static musl build.

The same applies to your own builds: if you build on a newer Debian/Ubuntu (e.g. Debian 13 / glibc 2.41) and deploy to an older one (Debian 12 / glibc 2.36), build inside a container matching the target’s glibc – for example, rust:1-bookworm for Debian 12 deploys, or use musl (the static --target x86_64-unknown-linux-musl builds the release CI publishes).

Release profile

The release build uses LTO, single codegen unit, and symbol stripping for a small binary:

[profile.release]
lto = true
codegen-units = 1
strip = true

Target binary size (musl, stripped): <= 16 MB. Enforced against the real artifact by the “Enforce published binary size” step in release.yml.

Cross-compilation

sipnab uses cross for cross-compilation. It runs each build in a container that already carries the target’s toolchain, so the host needs no cross-linker of its own. Install it once:

cargo install cross

Build for aarch64 Linux:

cross build --release --features full --target aarch64-unknown-linux-gnu

Build for x86_64 Linux:

cross build --release --features full --target x86_64-unknown-linux-gnu