Docs Install sipnab
Install sipnab
Install sipnab from a pre-built binary, a package, Homebrew or cargo, then check the download is genuine.
On this page
- I want to
- Install in one command
- Download a release binary yourself
- Install with cargo
- Install with your package manager
- Build it from source
- Verify a download is genuine
- Capture live traffic without root
- Feature flags
- Turn on the MCP server
- Release profile
- Cross-compilation
- Run it in Docker
- Platform notes
- Check it worked
- Upgrade sipnab
- Uninstall it
- Next steps
sipnab is a single binary.
- The static Linux musl build needs nothing else.
- The other builds load the system’s libpcap. macOS always has it, and a Linux package manager installs it.
- You do not need Rust, a compiler, or a toolchain to run it. Those are only for the build-it-yourself path near the end of this page.
Most people should run the one-line installer and be reading a capture inside a minute.
I want to
| Your goal | Go to |
|---|---|
| Install it and get working | Install in one command |
| Confirm the install actually worked | Check it worked |
| Avoid piping a script from the internet into a shell | Download a release binary yourself |
Use apt, dnf, or Homebrew | Install with your package manager |
| Compile it myself | Build it from source |
| Capture live traffic without running as root | Capture live traffic without root |
| Prove a download is genuine before trusting it | Verify a download is genuine |
| Run it in a container | Run it in Docker |
| Drive it from an AI agent | Turn on the MCP server |
| Move to a newer release | Upgrade sipnab |
| Take it off this machine | Uninstall it |
Install in one command
One command on Linux (x86_64/aarch64) or macOS:
curl -fsSL https://sipnab.com/install.sh | sh
The install script:
- detects your OS, CPU architecture, and glibc version,
- downloads the matching versioned release tarball
(
sipnab-<version>-<target-triple>.tar.gz) together with its.sha256file, - verifies the checksum,
- installs the binary to
/usr/local/bin(usingsudoonly if that directory isn’t writable).
Prefer to read it first: https://sipnab.com/install.sh.
Two environment variables tune it. To pin a specific version instead of taking whatever the latest release is:
curl -fsSL https://sipnab.com/install.sh | SIPNAB_VERSION=0.5.233 sh
To install somewhere other than /usr/local/bin, use a directory you already
own. Then root never enters into it:
curl -fsSL https://sipnab.com/install.sh | SIPNAB_INSTALL_DIR="$HOME/.local/bin" sh
Then confirm it landed. It is one command, and the answer is the version plus the features compiled in:
sipnab --version
If that prints a version, the install worked.
When the installer stops, its last line names the reason:
| The installer prints | Cause | Fix |
|---|---|---|
sipnab-install: error: could not determine the latest version (set SIPNAB_VERSION to pin one) | It could not reach api.github.com, or GitHub refused the request, for example for its rate limit | Pin the release: SIPNAB_VERSION=0.5.233 |
sipnab-install: error: download failed: https://github.com/NormB/sipnab/releases/download/v9.9.9/sipnab-9.9.9-aarch64-unknown-linux-gnu.tar.gz | No release has that version, or github.com is unreachable | Check the version on the releases page |
sipnab-install: error: sha256 mismatch for <file> — download corrupted or tampered, aborting | The tarball does not match its .sha256 file | Run it again. If it repeats, download by hand and verify the download |
sipnab-install: error: neither sha256sum nor shasum found; refusing to install unverified binary | The host has no checksum tool | Install coreutils (Linux) |
sipnab-install: /tmp/bin is not writable — using sudo, then sudo: not found and sipnab-install: error: install to /tmp/bin failed | SIPNAB_INSTALL_DIR names a directory you cannot write, and there is no sudo | Create the directory as your user first, or run as root |
Each of these exits with status 1 and installs nothing.
The installer does not install libpcap. On a glibc host it installs the
-gnu build, which loads libpcap at startup. Without it, the first run
fails:
sipnab: error while loading shared libraries: libpcap.so.0.8: cannot open shared object file: No such file or directory
Install libpcap0.8 (Debian, Ubuntu) or libpcap (Fedora, RHEL) and run it
again.
- Go to Check it worked for the fuller checks, or Next steps to start reading captures.
- If the shell cannot find
sipnab, the install directory is not on yourPATH. See Check it worked.
On Linux the installer chooses between two builds.
- Hosts with glibc 2.36 or newer (Debian 12+, Ubuntu 23.04+) get the
dynamically linked
-gnubuild. That build needs libpcap from your package manager. - Older hosts, and hosts with no glibc, get the static musl build. It
needs nothing else.
- It lacks TUI audio playback, WASM plugins, vCon export and the eBPF uprobe backend.
- It reads password-protected ZIP and 7z archives like every other release build (Read captures from tar, ZIP and 7z archives).
Download a release binary yourself
Every GitHub release ships the artifacts below. This table is the reference. The download page carries the same files as ready-made links for the current release.
Release artifacts
Substitute the release version for <version> throughout.
SHA256SUMS.txtcovers every file.- The tarballs additionally ship an individual
.sha256sidecar.
| File | CPU | Runs on | Notes |
|---|---|---|---|
sipnab_<version>_amd64.deb | x86_64 / amd64 | Debian 12+, Ubuntu 23.04+ | apt-managed, full features |
sipnab_<version>_arm64.deb | aarch64 / arm64 | Debian 12+, Ubuntu 23.04+ | apt-managed, full features |
sipnab_<version>_amd64-noaudio.deb | x86_64 / amd64 | Debian 12+, Ubuntu 23.04+ | no ALSA dependency — headless servers |
sipnab_<version>_arm64-noaudio.deb | aarch64 / arm64 | Debian 12+, Ubuntu 23.04+ | no ALSA dependency — headless servers |
sipnab-<version>-1.x86_64.rpm | x86_64 / amd64 | RHEL/Fedora, glibc >= 2.36 | dnf/rpm-managed, full features |
sipnab-<version>-1.aarch64.rpm | aarch64 / arm64 | RHEL/Fedora, glibc >= 2.36 | dnf/rpm-managed, full features |
sipnab-<version>-1.x86_64-noaudio.rpm | x86_64 / amd64 | RHEL/Fedora, glibc >= 2.36 | no ALSA weak dependency |
sipnab-<version>-1.aarch64-noaudio.rpm | aarch64 / arm64 | RHEL/Fedora, glibc >= 2.36 | no ALSA weak dependency |
sipnab-<version>-x86_64-unknown-linux-musl.tar.gz | x86_64 / amd64 | any Linux, any glibc, Alpine | static — no TUI audio playback, WASM plugins, vCon export or eBPF uprobe backend |
sipnab-<version>-aarch64-unknown-linux-musl.tar.gz | aarch64 / arm64 | any Linux, any glibc, Alpine | static — no TUI audio playback, WASM plugins, vCon export or eBPF uprobe backend |
sipnab-<version>-x86_64-unknown-linux-gnu.tar.gz | x86_64 / amd64 | glibc >= 2.36 + libpcap | full features; no audio plugin in 0.5.118 to 0.5.232 (why) |
sipnab-<version>-aarch64-unknown-linux-gnu.tar.gz | aarch64 / arm64 | glibc >= 2.36 + libpcap | full features; no audio plugin in 0.5.118 to 0.5.232 (why) |
sipnab-<version>-x86_64-apple-darwin.tar.gz | Intel | macOS 10.12+ | Intel Macs |
sipnab-<version>-aarch64-apple-darwin.tar.gz | Apple Silicon | macOS 11.0+ | M-series Macs |
sipnab-<version>-<target>.debug | per target | — | Linux symbol file for the binary of the same name, for reading a crash report or a core dump. One per tarball, plus -noaudio ones for the -noaudio packages |
sipnab-<version>-<target>.dSYM.zip | per target | — | macOS symbol bundle, the same for the two macOS tarballs |
SHA256SUMS.txt | — | — | checksums for every package, tarball, symbol file, and SBOM |
sipnab-<version>.cdx.json | — | — | CycloneDX SBOM — full dependency tree |
sipnab-audio-<version>.cdx.json | — | — | CycloneDX SBOM — audio feature subtree |
v<version>.tar.gz, v<version>.zip | — | anywhere Rust 1.99+ builds | tagged source tree |
Which capture backends an artifact can reach
libpcap selects a capture backend from the device name. sipnab passes the name through.
--device netmap:eth0reaches libpcap’s netmap module when the libpcap behind that binary carries one.- Which artifact you installed decides whether it was. The three families differ:
| Artifact family | libpcap | netmap | DPDK | AF_XDP |
|---|---|---|---|---|
*-linux-musl.tar.gz | statically linked, 1.10.6 | compiled in: netmap API 14 from 0.5.184, API 13 on 0.5.183 and earlier (see below) | no | no |
*-linux-gnu.tar.gz, .deb, .rpm, Docker image, Homebrew on Linux | the host’s, at runtime | whatever your distribution built | almost never | no |
*-apple-darwin.tar.gz, Homebrew on macOS | the one macOS ships, /usr/lib/libpcap.A.dylib, at runtime | no | no | no |
Warning: capture on a
netmap:device only on an interface dedicated to capture, such as a SPAN or mirror port, never on one the host needs. libpcap’s netmap module takes the interface’s rings away from the kernel, so the host stops receiving that interface’s traffic for as long as the capture runs. Anetmap:capture on the interface that carries your SIP service stops that service from receiving traffic until sipnab exits.
Debian and Ubuntu build libpcap without netmap.
- So the
.deb, the.rpmand the Docker image answerNo such device existsfor anetmap:name. - The static musl tarballs answer
netmap open: cannot access netmap:eth0instead. This is a different error, and the difference is the whole point:- the first says the module is absent,
- the second says the module tried and your kernel has no netmap device.
macOS builds libpcap on BPF alone, with netmap and DPDK both left out.
Homebrew on macOS installs the same darwin tarball rather than bringing a
libpcap of its own. A netmap: or dpdk: name on a Mac reaches nothing.
No artifact sipnab publishes carries DPDK. No libpcap has an AF_XDP backend at
all. So an xdp: name is never a capture path.
Ask sipnab what its own binary runs. The second line of --version is the
libpcap it loaded. sipnab asks the library at runtime rather than recording it
at build time. So on a gnu build it names your host’s library:
sipnab --version
On a musl tarball that line reads:
libpcap version 1.10.6 (64-bit time_t, with TPACKET_V3 and netmap); alternate capture backends named: netmap
and on Debian 13’s libpcap:
libpcap version 1.10.5 (with TPACKET_V3); alternate capture backends named: none
A backend the banner does not name remains unconfirmed rather than absent.
- libpcap puts netmap in its banner only from 1.10.6.
- libpcap names DPDK only in a build that captures from DPDK alone.
- The same report is the
libpcapblock of the MCPserver_capabilitiestool and of the RESTGET /v1/capabilitiesroute. - It also sits under the version in the TUI help view (F1).
A sipnab that predates the report prints only the first line. For one of those, look for the banner yourself:
strings "$(command -v sipnab)" | grep 'libpcap version'
An empty result means the binary links your system’s libpcap rather than embedding one. Ask that library instead:
strings /usr/lib/*/libpcap.so.* | grep 'libpcap version'
Fix a netmap capture that fails on an older release
Later releases fix three netmap: failures. Check your release with
sipnab --version, find the symptom below, and
upgrade to the release in the last column or later.
| Symptom | Affected releases | Fixed in |
|---|---|---|
On a musl tarball, a netmap: open fails with nm_open [948] NIOCREGIF failed: Invalid argument netmap:<iface>, and the kernel log says Minimum supported API is 14 (requested 13) | 0.5.183 and earlier, musl tarballs | 0.5.184 |
The capture stops, often while idle, and the kernel log records a segfault at address 0 in the capture-netmap thread | 0.5.188 and earlier | 0.5.189 |
A netmap: capture on a link with no traffic does not stop on SIGTERM or at the end of --duration | 0.5.189 and earlier | 0.5.190 |
The audio plugin in Linux packages
Live audio playback in the TUI loads a separate plugin,
libsipnab_audio.so on Linux and libsipnab_audio.dylib on macOS. From
0.5.118 to 0.5.232 the Linux gnu tarballs and the standard .deb and .rpm
held no plugin, and the packages recommended no sound library. 0.5.233 ships
the plugin again:
| Artifact (0.5.233) | Plugin | Recommends |
|---|---|---|
sipnab_<version>_<arch>.deb | /usr/lib/sipnab/libsipnab_audio.so | libasound2 or libasound2t64 |
sipnab-<version>-1.<arch>.rpm | /usr/lib/sipnab/libsipnab_audio.so | alsa-lib |
sipnab-<version>-<arch>-unknown-linux-gnu.tar.gz | libsipnab_audio.so | — |
sipnab-<version>-<arch>-apple-darwin.tar.gz | libsipnab_audio.dylib | — |
The -noaudio packages hold no plugin and recommend nothing. Before 0.5.233,
0.5.117 is the last release whose gnu tarballs and standard packages held the
plugin. In 0.5.118 to 0.5.232, sipnab --version still lists audio, because
the release builds the binary with the feature. Every other part of audio,
WAV export included, is in the binary and works without the plugin.
Check what a package holds before you install it:
dpkg-deb -c "sipnab_${VERSION}_amd64.deb" | grep libsipnab_audio
No output means no plugin.
Architecture naming
x86_64 = amd64 (Intel/AMD) and aarch64 = arm64 (ARM) are the same chips
under two spellings.
- Tarballs and
.rpmpackages usex86_64/aarch64. .debpackages useamd64/arm64.uname -mreports which one you have.
The unknown in x86_64-unknown-linux-gnu is the vendor field of the Rust
target triple (arch-vendor-os-abi).
- It is the canonical value meaning “no specific vendor”. That is why the
macOS files say
applein that position. - It is part of the platform name, not a failed detection or a broken build.
SHA256SUMS.txt, the build-provenance attestation and the install script all use the same names.
Every command below reads the release number from a VERSION variable. Set
it first, in the same shell, to the release you want, e.g. 0.5.233 for the
latest:
VERSION=0.5.233
On Linux x86_64, the static musl tarball runs on any distro and any glibc, Alpine included:
-
Download the tarball:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab-$VERSION-x86_64-unknown-linux-musl.tar.gz" -
Unpack it:
tar xzf "sipnab-$VERSION-x86_64-unknown-linux-musl.tar.gz" -
Install the binary:
sudo install -m 755 "sipnab-$VERSION-x86_64-unknown-linux-musl/sipnab" /usr/local/bin/sipnab
The same three steps on Linux aarch64, against the aarch64 musl tarball:
-
Download the tarball:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab-$VERSION-aarch64-unknown-linux-musl.tar.gz" -
Unpack it:
tar xzf "sipnab-$VERSION-aarch64-unknown-linux-musl.tar.gz" -
Install the binary:
sudo install -m 755 "sipnab-$VERSION-aarch64-unknown-linux-musl/sipnab" /usr/local/bin/sipnab
A manual download of the gnu build that checks the checksum before installing.
TARGET names the build. The tarball unpacks into ./sipnab-$VERSION-$TARGET/:
-
Set the target:
TARGET=x86_64-unknown-linux-gnu -
Download the tarball:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab-$VERSION-$TARGET.tar.gz" -
Download its checksum file:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab-$VERSION-$TARGET.tar.gz.sha256" -
Check the checksum:
sha256sum -c "sipnab-$VERSION-$TARGET.tar.gz.sha256" -
Unpack the tarball:
tar -xzf "sipnab-$VERSION-$TARGET.tar.gz" -
Install the binary:
sudo install -m 755 "sipnab-$VERSION-$TARGET/sipnab" /usr/local/bin/sipnab
The dynamic builds, whose names end in -unknown-linux-gnu.tar.gz, are the
ones that can add TUI audio playback. From 0.5.233 the tarball holds the
playback plugin (libsipnab_audio.so) beside the binary. From 0.5.118 to
0.5.232 it held the binary, the man page and the license files only. sipnab
looks for the plugin next to its own executable, then in /usr/lib/sipnab/,
then through the dynamic loader’s search path, so the step above, which
installs the binary alone, leaves playback off. See
The audio plugin in Linux packages.
- They require glibc >= 2.36 (Debian 12+, Ubuntu 23.04+) and libpcap.
- On an older distribution they fail with
version `GLIBC_2.36' not found. Use the static musl build there.
Install with cargo
cargo install sipnab --features full
On Alpine or any musl target,
--features fulldoes not give you audio.
- The playback plugin arrives through
dlopen.- Static musl has no dynamic loader. It returns “Dynamic loading not supported”.
- The build succeeds and the binary reports
audioin--version. But playback can never work.- Build without the
audiofeature. Or build dynamically linked (RUSTFLAGS="-C target-feature=-crt-static"plusapk add alsa-lib alsa-lib-dev), which is Alpine-only.- See the site’s Build from Source page for both recipes.
Install with your package manager
Debian/Ubuntu (.deb)
Download the .deb for your architecture from the latest release.
- Install it with
apt. It resolves thelibpcap0.8runtime dependency. - The
.debneeds glibc >= 2.36, i.e. Debian 12+ / Ubuntu 23.04+. - On older releases use the static musl tarball above.
Download and install the amd64 (x86_64) package. Set VERSION to the release
you want, e.g. 0.5.233, as in
Download a release binary yourself:
-
Set the version:
VERSION=0.5.233 -
Download the package:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab_${VERSION}_amd64.deb" -
Install it:
sudo apt install "./sipnab_${VERSION}_amd64.deb"
On an arm64 (aarch64) host, take the arm64 package instead, with VERSION set
as above. Installing the wrong-architecture .deb over the right one leaves
you with a binary that does not run:
-
Download the package:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab_${VERSION}_arm64.deb" -
Install it:
sudo apt install "./sipnab_${VERSION}_arm64.deb"
The package installs /usr/bin/sipnab, the man page, and a systemd unit.
- It creates a
sipnabsystem user for privilege dropping. - On Ubuntu 24.04+ the dependency resolves to
libpcap0.8t64.
The unit is not started for you. sudo systemctl enable --now sipnab starts a
capture on every interface as the sipnab user. The unit:
- uses only the two capabilities live capture needs,
- writes its log to the journal, and sends security alerts to syslog
(
--syslog), - keeps the per-message stream out of the journal,
- serves metrics on
127.0.0.1:9090.
The REST API stays off. Change any of that with a drop-in
(sudo systemctl edit sipnab). A package upgrade leaves the drop-in alone.
Run sipnab as a service shows how to check the unit
came up, drop-ins, and what to do when it does not start.
Each release publishes a standard package and a -noaudio package.
- The
-noaudiopackage has no audio plugin and no ALSA dependency.- Everything else, WAV export included, works the same.
- Only live playback in the TUI is unavailable.
- From 0.5.233 the standard package ships the plugin and recommends
libasound2. Releases from 0.5.118 to 0.5.232 did neither, so in those releases the two packages differ only in name. See The audio plugin in Linux packages.
The headless amd64 (x86_64) package:
-
Download the package:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab_${VERSION}_amd64-noaudio.deb" -
Install it:
sudo apt install "./sipnab_${VERSION}_amd64-noaudio.deb"
The headless arm64 (aarch64) package, for arm64 hosts:
-
Download the package:
curl -LO "https://github.com/NormB/sipnab/releases/download/v$VERSION/sipnab_${VERSION}_arm64-noaudio.deb" -
Install it:
sudo apt install "./sipnab_${VERSION}_arm64-noaudio.deb"
Alternatively, install the standard package with
sudo apt install --no-install-recommends "./sipnab_${VERSION}_amd64.deb".
- This skips the ALSA packages while keeping the plugin on disk.
- Playback then works as soon as
libasound2lands.
RHEL/Fedora (.rpm)
.rpm packages ship per release for x86_64 and aarch64. Each comes in a
standard and a -noaudio variant.
- The no-audio variant has no audio plugin and no
alsa-libweak dependency. - It is for headless servers, mirroring the
.debvariants.
Download the package for your architecture and variant from the
latest release, then install
it with dnf, which also installs the libpcap it needs. Pick the line that
matches uname -m (x86_64 or aarch64).
The standard package on an x86_64 host:
sudo dnf install ./sipnab-0.5.233-1.x86_64.rpm
The headless / no-ALSA variant on the same architecture:
sudo dnf install ./sipnab-0.5.233-1.x86_64-noaudio.rpm
The standard package on an aarch64 (arm64) host:
sudo dnf install ./sipnab-0.5.233-1.aarch64.rpm
The headless / no-ALSA variant on aarch64:
sudo dnf install ./sipnab-0.5.233-1.aarch64-noaudio.rpm
rpm -i does not fetch dependencies. On a host without libpcap it refuses:
error: Failed dependencies:
libpcap is needed by sipnab-0.5.232-1.aarch64
libpcap.so.1()(64bit) is needed by sipnab-0.5.232-1.aarch64
dnf prints Warning: skipped OpenPGP checks for 1 package from repository: @commandline: the packages carry no OpenPGP signature. Check the download
against SHA256SUMS.txt and its attestation instead, as in
Verify a download is genuine.
The package installs /usr/bin/sipnab, the man page and the systemd unit, and
creates the sipnab user. It creates no /etc/sipnab directory. On Fedora
42, sipnab --version then prints:
sipnab 0.5.232 (v0.5.232 a62a3ac2) features: native,tui,audio,tls,hep,api,mcp,mcp-http,metrics,plugins,bpf,vcon,opus,archive,g729
Homebrew (macOS)
brew install NormB/tap/sipnab
Nobody ran this command for this page: no Mac was available to test it. The tap exists, as NormB/homebrew-tap with
Formula/sipnab.rb. Live capture on macOS needs root: see
macOS.
Build it from source
Only this section needs a toolchain. The installer, the release tarballs and the packages all ship a finished binary.
Before you build, you need:
- Rust 1.99+ — the toolchain the project builds and tests against.
- libpcap headers —
libpcap-devon Debian/Ubuntu,libpcap-develon RHEL/Fedora. This is the one library sipnab links against. - pkg-config — how the build finds libpcap.
- cmake and a C compiler — for
--features full, whoseopusfeature compiles libopus from source and links it into the binary.
Two missing prerequisites stop the build late, after the dependencies have
compiled. Each failure below came from building tag v0.5.232 in the
rust:1.99-slim-trixie image:
| The build stops with | Missing | Fix |
|---|---|---|
error: linking with `cc` failed: exit status: 1 and, in the notes, /usr/bin/ld: cannot find -lpcap: No such file or directory | libpcap headers | sudo apt install libpcap-dev pkg-config (Debian, Ubuntu). On Fedora and RHEL the headers are libpcap-devel |
error: failed to run custom build command for `opusic-sys v0.7.5` and is `cmake` not installed? | cmake, for --features full | sudo apt install cmake (Debian, Ubuntu) |
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:
-
Clone the repository:
git clone https://github.com/NormB/sipnab.git -
Change into it:
cd sipnab -
Run the install script:
./scripts/install-from-source.sh --features full
The script does this:
- It runs
cargo install --path . --bin sipnab(forwarding any arguments). - Then on Linux it invokes the binary’s own
--setup-caps. So live capture works withoutsudo. - Non-Linux platforms skip the capability step and point you at
sudo.
This is a source install. It is distinct from the one-line installer at https://sipnab.com/install.sh. That installer downloads a prebuilt release binary and compiles nothing.
Basic build (TUI only, default features)
-
Clone the repository:
git clone https://github.com/NormB/sipnab.git -
Change into it:
cd sipnab -
Build the release binary:
cargo build --release -
Copy it onto your
PATH: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
Verify a download is genuine
Every release artifact is checksummed, signed with sigstore build provenance, and accompanied by a CycloneDX SBOM.
- The installer script verifies the sha256 for you.
- These steps are for manual downloads, mirrors, and anything that reached you by a route you did not choose.
Checksum. SHA256SUMS.txt covers every tarball, .deb, .rpm, symbol
file, and SBOM in the release:
sha256sum -c SHA256SUMS.txt --ignore-missing
Provenance. A checksum only proves the file matches the list. It says nothing about who produced the list. The attestation is cryptographic proof the artifact came from sipnab’s own release workflow, at a specific commit:
gh attestation verify "sipnab-$VERSION-x86_64-unknown-linux-gnu.tar.gz" \
--repo NormB/sipnab
This is what detects a rehosted or tampered copy, including one served with a matching checksum file.
On a terminal it ends with these lines, among others:
✓ Verification succeeded!
The following 1 attestation matched the policy criteria
- Signer workflow: .github/workflows/release.yml@refs/tags/v0.5.232
gh 2.102.0 printed nothing at all when its output went to a pipe or a file,
for a pass and for a failure alike. In a script, read the exit status instead:
0 for a pass, 1 otherwise. A file whose bytes differ from the release has
no attestation at all, and gh reports that as a lookup failure:
Error: HTTP 404: Not Found (https://api.github.com/repos/NormB/sipnab/attestations/sha256:9e7d72812c6ebd32e06af390adf104898dbc65c423c1ffa56ef58f0d4903a06b?per_page=30&predicate_type=https%3A%2F%2Fslsa.dev%2Fprovenance%2Fv1)
The .deb and .rpm packages carry the same attestation: run the command on
the package file.
This needs gh 2.49 or newer. Check with gh --version.
- The subcommand did not exist before then, and distributions lag.
- Ubuntu 24.04 ships 2.45. There the command prints
unknown command "attestation"followed by the general help text and still exits 0. - Piped or scripted, that reads as success while verifying nothing.
- Install a current
ghfrom https://github.com/cli/cli/releases rather than trusting a silent pass.
Signature and provenance files. Releases after v0.5.231 attach two more files. The release workflow makes both from its own short-lived GitHub identity, with no stored signing key:
| File | What it is |
|---|---|
SHA256SUMS.txt.sigstore.json | a Sigstore signature over SHA256SUMS.txt |
sipnab-<version>.intoto.jsonl | the build provenance above, as a file you can keep |
The signature proves the checksum list itself came from sipnab’s release workflow. Check it with cosign before you trust the list:
cosign verify-blob SHA256SUMS.txt \
--bundle SHA256SUMS.txt.sigstore.json \
--certificate-identity-regexp '^https://github\.com/NormB/sipnab/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
Verified OK means the list is genuine, and sha256sum -c above then
extends that to your download. That command works as written with cosign
3.1.4. cosign 2.4.1 rejects the bundle with bundle does not contain cert for verification, please provide public key. Add --new-bundle-format there.
cosign names what failed:
- a list that differs from the one the release signed:
failed to verify signature: could not verify message: invalid signature when validating ASN.1 encoded signature; - a signature from another workflow or repository:
failed to verify certificate identity: no matching CertificateIdentity found, followed by the identity it found. With--bundle,ghreads the provenance from the file instead of from GitHub’s attestation API, so you can check a copy of the release kept anywhere:
gh attestation verify "sipnab-$VERSION-x86_64-unknown-linux-gnu.tar.gz" \
--bundle "sipnab-$VERSION.intoto.jsonl" --repo NormB/sipnab
Dependencies. Two CycloneDX SBOMs ship with each release:
| File | Covers |
|---|---|
sipnab-<version>.cdx.json | the sipnab binary |
sipnab-audio-<version>.cdx.json | libsipnab_audio.so, the playback plugin |
Scan both files. The playback plugin is a separate library that the binary
loads at run time with dlopen. Its dependencies, rodio, cpal and alsa
among them, appear only in sipnab-audio-<version>.cdx.json.
Feed either to any CycloneDX-aware scanner:
grype "sbom:sipnab-$VERSION.cdx.json" # trivy sbom and osv-scanner read it too
The release generates the binary SBOM for the full,bpf feature set, the
largest any published binary carries. It lists every dependency of every published binary,
and can list some that the binary you downloaded does not contain.
Rebuild a release and compare it
A checksum and an attestation say where a binary came from. A rebuild says what it contains.
- The
sipnabbinary in each Linux gnu tarball is reproducible. Building the release’s tag yourself gives the same bytes. - Compare the binary, not the tarball or a package. Those carry file times.
- The audio plugin beside the binary is not covered.
- This applies to 0.5.198 and later.
You need a git checkout of the tag, not a source tarball. The binary embeds the commit hash and the tag, and a tarball has neither.
You also need the same toolchain the release used. For the gnu targets, that is:
- the
rust:1-bookwormimagerelease.ymlpins by digest, - Rust 1.99.0,
- the eBPF nightly
bpf/rust-toolchain.tomlnames, - and bpf-linker 0.11.0.
The release job’s log shows each version it used.
-
Check out the tag and install the pinned eBPF nightly:
# Run all of these, in order. git clone https://github.com/NormB/sipnab && cd sipnab git checkout "v$VERSION" (cd bpf && rustup toolchain install) -
Build the way the release does, with the feature set the release gives that target (
full,bpffor the gnu tarballs):SIPNAB_BPF_REQUIRED=1 bash scripts/reproducible-build.sh build x86_64-unknown-linux-gnu full,bpf -
Strip it the way the release does. The binary carries the symbol file’s name, so use the release’s name for it:
bash scripts/split-debuginfo.sh target/x86_64-unknown-linux-gnu/release/sipnab \ "sipnab-$VERSION-x86_64-unknown-linux-gnu" -
Compare it with the binary from the release tarball:
bash scripts/reproducible-build.sh compare \ target/x86_64-unknown-linux-gnu/release/sipnab "sipnab-$VERSION-x86_64-unknown-linux-gnu/sipnab"identicaland a sha256 means the bytes match. Otherwise the script prints both hashes, where the files first differ, and the strings that differ. The usual cause is a different toolchain rather than a different source.
To check that the project’s own build repeats, without a published binary to
compare against, use check. It builds a commit or tag twice in two
directories and compares the two:
SIPNAB_BPF_REQUIRED=1 bash scripts/reproducible-build.sh check \
x86_64-unknown-linux-gnu full,bpf /tmp/sipnab-repro "v$VERSION"
The project runs that check weekly. Reproducible builds says what it covers and what a rebuild must hold fixed.
Capture live traffic without root
Reading a pcap file needs no special permissions at all.
- Live capture (
sipnab -d <iface>or the defaultanydevice) needs libpcap and raw-socket access. - Rather than running the whole TUI as root, grant the binary the Linux capabilities once. Then run it as your normal user:
sudo sipnab --setup-caps
# equivalent to: sudo setcap cap_net_raw,cap_net_admin+ep $(command -v sipnab)
--setup-caps runs setcap on the sipnab binary and exits. It re-invokes
itself through sudo when not already root. After that, run sipnab without
sudo:
sipnab # live capture works; no sudo needed
Prefer this to sudo sipnab.
- When started as root, sipnab opens the capture device. Then it drops
privileges to an unprivileged user (
nobodyby default, or--user <name>). - That dropped user usually cannot read your home directory.
- So the in-TUI file browser (
O) comes up empty. It shows a “run without sudo” message explaining why. - Running unprivileged with capabilities avoids this entirely.
- Re-run
--setup-capsafter each reinstall. Replacing the file clears its capabilities.
macOS and other non-Linux platforms have no file capabilities. Run live capture under
sudothere.
Capture with the least privilege goes further: the privilege drop, a chroot, and the Landlock and seccomp confinement.
Feature flags
sipnab uses Cargo feature flags to control optional capability. The default build includes native, tui, audio, and metrics.
| Feature | Description | Dependencies |
|---|---|---|
native | Live capture, file capture, output writers, signal handling, CLI parser. Required (directly or transitively) by tui, hep, metrics, api, mcp, mcp-http, plugins, bpf, vcon, archive and g729. Not required by tls, audio, or wasm. Included by default. | pcap, clap, clap_complete, env_logger, crossbeam-channel, libc, pcap-file, memmap2, tracing-subscriber, tracing-log, tempfile |
tui | Interactive terminal UI (ratatui + crossterm). Included by default. | native, ratatui, crossterm, unicode-width, base64 |
audio | RTP 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) |
tls | TLS/DTLS decryption and SRTP key extraction (pure Rust) | ring, rustls, rsa, aes, cbc, zeroize, base64, libc |
hep | HEP v3 send + v1/v2/v3 receive (Homer Encapsulation Protocol) | native, hmac, sha2, rustls, base64 |
api | REST API + Prometheus metrics endpoint, over HTTP or HTTPS. 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, base64, hmac, sha2, utoipa, rustls, tokio-rustls, ring, hyper, hyper-util, futures-core |
mcp | Model Context Protocol server, stdio transport. Lets an AI agent, such as Claude Code or Claude Desktop, drive sipnab. | native, tokio, rmcp, base64, hmac, sha2 |
mcp-http | MCP server over HTTP (Streamable-HTTP). Adds the --mcp-transport http option. | mcp, api, rmcp/transport-streamable-http-server |
metrics | Standalone Prometheus /metrics server on a plain TCP listener and threads. Needs neither the api feature nor an async runtime. Included by default. | native, base64, rustls |
plugins | WASM plugin host (--plugin): runs third-party dialog detections in a sandbox that has no access to the sipnab process. | native, wasmi |
bpf | eBPF TLS capture (--uprobe-backend bpf): reads SIP plaintext and the peer addresses with no key material. Needs a nightly toolchain and bpf-linker to build, and a kernel with CONFIG_DEBUG_INFO_BTF to run — without the linker the binary still builds, and --uprobe-backend bpf refuses at run time. | native, aya, sipnab-bpf-types/pod |
vcon | vCon export: one observed dialog as an IETF conversation container, with the audio inline when the run retained it, or signed and encrypted when a [[vcon.rule]] sets encrypt_to. Not in the default build. Adds --export-vcon/--vcon-out, the export_vcon MCP tool and GET /v1/dialogs/{call_id}/vcon. | native, sha2, hmac, base64, rustls, rsa, ring, aes, cbc, sha1_oaep, sha1, webpki, p256 |
opus | Ogg Opus recordings in vCon containers (audio_format = "opus" on a [[vcon.rule]]). Compiles libopus from the source opusic-sys vendors and links it statically, so building it needs cmake and a C compiler; the binary needs no system libopus. In full; not in the static musl builds, which have no vCon export. | vcon, opus |
archive | Password-protected ZIP and 7z input: -I evidence.zip reads the captures inside, stored, deflated, WinZip AES or ZipCrypto, and -I evidence.7z reads LZMA or LZMA2, AES-256 or not, without leaving a decrypted copy on disk. Adds --archive-password-file, --archive-password-command, --archive-password-stdin, --archive-password and --archive-password-encoding, and reads SIPNAB_ARCHIVE_PASSWORD and the systemd credential archive-password. | native, zip, sevenz-rust2, zeroize, unicode-normalization |
g729 | G.729 Annex A decoding, with Annex B comfort noise, for WAV export, vCon recordings, the live audio route and the dead-air measurement. Adds --g729-tables, [g729], and the sipnab g729 install and sipnab g729 status commands. sipnab ships no ITU-T table values: each host installs them with sipnab g729 install, described on the G.729 decoding page. Pure Rust, so in full and in the static musl builds. | native, g729 (crates/g729), sha2, rustls, base64 |
full | Everything: native + tui + audio + tls + hep + api + mcp + mcp-http + metrics + plugins + vcon + opus + archive + g729 | all |
wasm | WebAssembly target for in-browser pcap analysis | wasm-bindgen, js-sys, web-sys, console_error_panic_hook |
Build with specific features. For the TUI plus TLS decryption and nothing else:
cargo build --release --features tui,tls
For a headless capture host, with HEP listener, REST API, and MCP over HTTP, and with no TUI and no audio:
cargo build --release --no-default-features --features native,hep,api,mcp,mcp-http
For everything:
cargo build --release --features full
libasound.so.2 is an optional runtime dependency.
- The
audiofeature builds a separate plugin,libsipnab_audio.so.- The
.debinstalls it to/usr/lib/sipnab/. - Dev builds place it next to the binary.
- The
- The
sipnabbinarydlopens 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. You can still export the stream to a WAV file (F2).
On Debian/Ubuntu the package carries libasound2 as a Recommends. Install it for live playback. Only libpcap0.8 is a hard dependency.
For a fully audio-free build, drop the audio feature. Then the plugin is not
built.
Turn on the MCP server
To run sipnab as a Model Context Protocol server for an AI agent, such as Claude Code or Claude Desktop, start with MCP server.
- It covers the
mcpandmcp-httpfeatures and a first working example. - Connect an AI agent to sipnab covers running it on a server, including token-file generation and the systemd unit.
Release profile
The release build uses LTO, a single codegen unit, and symbol stripping for a small binary. It unwinds on panic, so sipnab can contain a panic in a parser of untrusted input instead of ending the process. It compiles line-table debug info:
[profile.release]
lto = true
codegen-units = 1
strip = true
panic = "unwind"
debug = "line-tables-only"
Target binary size (musl, stripped): <= 23 MB. The release workflow checks the 23 MB ceiling against each published musl binary and refuses to publish a larger one.
A local cargo build --release strips the line tables at link time, so your
own build carries no symbols. A release keeps them in a separate file instead:
download the .debug file (Linux) or .dSYM.zip (macOS) that matches your
binary from the release artifacts to resolve the
addresses in a crash report or a
core dump.
Cross-compilation
sipnab uses cross for cross-compilation. Cross.toml lists the supported targets.
cross is a separate binary, so install it first:
cargo install cross
With that in place, build for aarch64 Linux:
cross build --release --features full --target aarch64-unknown-linux-gnu
Or for x86_64 Linux:
cross build --release --features full --target x86_64-unknown-linux-gnu
The cross images automatically install the required libpcap-dev headers for the target architecture.
Run it in Docker
Run from a pre-built image
The image is ghcr.io/normb/sipnab. Pin a release tag:
docker pull ghcr.io/normb/sipnab:0.5.233
The tags follow the Docker workflow:
| Tag | Points at |
|---|---|
0.5.233 | That release |
0.5 | The newest release in the 0.5 series |
sha-<commit> | The image built from that commit |
latest | The newest commit on main, which can be ahead of every release |
latest is not a release. On 2026-11-03 it was the image of main commit
0d8eea1, which the workflow built after the 0.5.232 tag.
The image is linux/amd64 only. On an arm64 host docker pull fails with
no matching manifest for linux/arm64/v8 in the manifest list entries. Use a
release tarball or a package there.
Read a capture file by mounting it:
docker run --rm -v /path/to/capture.pcap:/data/capture.pcap:ro \
ghcr.io/normb/sipnab:0.5.233 -N -I /data/capture.pcap
Live capture needs --user root. The image runs as the unprivileged user
sipnab, and a non-root user in a container gets no capabilities, whatever
--cap-add grants. Started as root, sipnab opens the capture and then drops
to nobody:
docker run --rm --net=host --user root ghcr.io/normb/sipnab:0.5.233 -N -d eth0
INFO sipnab::capture::live: Capturing on 'lo' (link_type=1, snaplen=65535)
INFO sipnab::privilege: Dropped privileges to user 'nobody' (uid=65534, gid=65534)
Without --user root, with or without --cap-add NET_RAW --cap-add NET_ADMIN, the capture fails and the container exits with status 1:
Permission denied on 'lo'. Grant capture capabilities once (Linux), then re-run without sudo:
The outputs above came from an arm64 image built from the
Dockerfile’s runtime
stage with the 0.5.232 .deb binary, capturing lo, because the published
image has no arm64 variant. docker image inspect ghcr.io/normb/sipnab:0.5.233
shows the same "User": "sipnab" for the published image.
--net=hostlets the container see the host’s interfaces.- A listener (
-L,--metrics,--api) needs its port published, for example-p 9060:9060/udp, or--net=host. - Mount a
sipnab.tomlat/etc/sipnab/sipnab.tomlto configure it. - The image holds the binary only. It carries no audio plugin, so live playback is unavailable; WAV export works.
Check where an image came from before you run it:
gh attestation verify oci://ghcr.io/normb/sipnab:0.5.233 --repo NormB/sipnab
It names the workflow and the ref that built the image. For 0.5.233 that is
.github/workflows/docker.yml@refs/tags/v0.5.233. For latest it is
.github/workflows/docker.yml@refs/heads/main.
Build the Docker image locally
docker build -t sipnab .
The multi-stage Dockerfile uses rust:1.99-slim-trixie for the build stage and debian:trixie-slim for the runtime image.
- The runtime image adds
libpcap0.8t64andlibasound2t64. - It runs as a non-root
sipnabuser. - It builds for the host’s own architecture, so this is also how to get an arm64 image.
Platform notes
Linux
Full capability.
- Live capture requires
CAP_NET_RAWcapability or root. - Privilege dropping (
--user) usessetuid/setgidafter opening capture devices.
macOS
TUI and pcap file analysis work fully.
- Live capture requires root or BPF device access.
- Install libpcap headers via Xcode Command Line Tools (included by default) or Homebrew.
Check the oldest macOS version a build supports. The release builds use the Rust compiler’s default for each target. For an Intel build:
rustc --print deployment-target --target x86_64-apple-darwin
MACOSX_DEPLOYMENT_TARGET=10.12
For an Apple Silicon build:
rustc --print deployment-target --target aarch64-apple-darwin
MACOSX_DEPLOYMENT_TARGET=11.0
FreeBSD / other
The project does not build, test or publish sipnab for FreeBSD or other platforms. Live capture there depends on the platform’s libpcap.
Check it worked
After installing, confirm sipnab is working. Print the version, which also names the features in the binary:
sipnab --version
Print the full help, which lists every flag this build accepts:
sipnab --help
Open a capture file in the TUI, which is the quickest end-to-end test:
sipnab -I /path/to/capture.pcap
Or read the same file in CLI mode. It is non-interactive and shows the first
few SIP messages. -N streams one line per message, not per call:
sipnab -N -I /path/to/capture.pcap | head -5
For one line per call instead, ask for the report and suppress the message stream:
sipnab -N -I /path/to/capture.pcap --report --no-cli-print | head -5
Print the version banner and the config sipnab loaded, which is what a bug report wants:
sipnab -D
--version lists the Cargo features compiled into the binary. On a second
line it shows the libpcap it is running, e.g.
sipnab 0.5.233 (<hash>) features: native,tui,audio,tls,hep,api,mcp,mcp-http,metrics,plugins,bpf,vcon,opus,archive,g729
libpcap version 1.10.5 (with TPACKET_V3); alternate capture backends named: none
This is the fastest way to confirm a build carries the feature set
you expected (e.g. that mcp-http is present on a server build).
- The second line names the libpcap that decides whether a
netmap:device can work. See which capture backends an artifact can reach. -Vprints only the first line.
The feature list differs by artifact. The example above is a *-linux-gnu
release binary on a Debian 13 host. That host’s libpcap names no alternate
backend.
The *-linux-gnu binaries carry bpf, the uprobe backend that can report the
peer address a TLS session went out to.
- The static musl tarballs and the macOS builds do not carry it.
- On those,
--uprobe-tlsuses thetracefsbackend. Its dialogs name a process rather than a peer. --uprobe-backend bpfexits with an error that names the missingbpffeature.
The musl tarballs also
omit audio (static musl has no dlopen).
A first non-interactive run looks like this. The capture is
tests/pcap-samples/Asterisk_ZFONE_XLITE.pcap from the source repository: a
registration, an OPTIONS exchange, two refused subscriptions and one call. Each SIP message gets one line:
timestamp, source, destination, method or status line, transport:
sipnab -N -I Asterisk_ZFONE_XLITE.pcap | head -4
07:12:49.978 192.168.10.41:13434 -> 192.168.10.2:5060 REGISTER UDP
07:12:49.978 192.168.10.2:5060 -> 192.168.10.41:13434 401 Unauthorized UDP
07:12:49.984 192.168.10.41:13434 -> 192.168.10.2:5060 REGISTER UDP
07:12:49.987 192.168.10.2:5060 -> 192.168.10.41:13434 OPTIONS UDP
--report --no-cli-print gives the per-call view of the same file instead:
sipnab -N -I Asterisk_ZFONE_XLITE.pcap --report --no-cli-print | head -4
Call-ID From To State Code Duration Msgs PDD Tags
-------------------------------------------------------------------------------------------------------------------------
M2NhZDAwZmYwZGNkYmZjYzQzYmY... 10009 10009 Registered 200 0s 4 - -
6255692e34af33dd022daf7f531... asterisk 10009 Completed 200 0s 2 - -
Read two columns with care.
- The
Codecolumn is the final answer to the dialog’s INVITE, or to the request that opened a dialog without one.- It skips an answered challenge.
- So the
REGISTERrow shows the registrar’s 200 and not its 401.
Durationis the span from the dialog’s first message to its last, not talk time.
Upgrade sipnab
Upgrade the same way you installed. Each route below replaces the binary with the newer release. It keeps your configuration.
Before you upgrade, read the changelog. sipnab is pre-1.0 and makes no Semantic Versioning promise. Any release may change a flag, a config key or an output format.
- CHANGELOG.md calls out each breaking change in the entry that carries it.
- It marks them Breaking: (entries up to 0.5.100 spell it
BREAKING:). - Search the entries between your version and the new one for that word.
Only the latest release gets fixes, security fixes included.
- There are no long-term support branches (see SECURITY.md).
- Upgrading is how you get a fix.
Check the version you run now, and again after the upgrade:
sipnab --version
With the one-line installer
Run the installer again. It fetches the latest release and overwrites the binary in place:
curl -fsSL https://sipnab.com/install.sh | sh
If you installed with SIPNAB_INSTALL_DIR, set it again. Otherwise the new
binary lands in /usr/local/bin beside the old one:
curl -fsSL https://sipnab.com/install.sh | SIPNAB_INSTALL_DIR="$HOME/.local/bin" sh
From a release tarball
Repeat the download steps in
Download a release binary yourself with
VERSION set to the new release. The last step,
sudo install -m 755, replaces the old binary.
With a .deb package
Download the new .deb as in
Install with your package manager.
Install it over the old one.
apt treats a newer version of an installed package as an upgrade:
sudo apt install "./sipnab_${VERSION}_amd64.deb"
sudo dpkg -i with the same file also upgrades. But it does not fetch a
missing dependency, which apt does.
With an .rpm package
Use rpm -U, not rpm -i. rpm -i refuses a package that is already
installed. -U replaces the installed version:
sudo rpm -U "sipnab-${VERSION}-1.x86_64.rpm"
dnf does the same, and fetches a missing dependency too:
sudo dnf upgrade "./sipnab-${VERSION}-1.x86_64.rpm"
On aarch64, or for the -noaudio package, use that file’s name, as listed in
Install with your package manager.
With Homebrew
brew upgrade NormB/tap/sipnab
With cargo
Install the new version over the old one.
--forcereplaces the installed binary.--lockedbuilds with the exact dependency versions the release’s own tests ran against:
cargo install sipnab --features full --locked --force
From a source checkout
Fetch the latest code, then run the install script again, from the checkout:
git pull
./scripts/install-from-source.sh --features full
In Docker
Pull the new release’s tag, and use that tag in your docker run command:
docker pull ghcr.io/normb/sipnab:0.5.233
Pulling latest gives the newest main commit, not the newest release. See
Run from a pre-built image.
What an upgrade keeps, and what to redo
Your configuration survives every route. No package ships a configuration file.
- The
.debcreates an empty/etc/sipnabdirectory. The.rpmcreates nothing there. - An upgrade replaces only the files the package ships. So
/etc/sipnab/sipnab.tomland~/.config/sipnab/stay as you left them. - The installer, the tarball, Homebrew and cargo never touch either location.
Capabilities do not survive a replaced binary. If you granted live capture without root, grant it again after the upgrade. Replacing the file clears its capabilities (see Capture live traffic without root):
sudo sipnab --setup-caps
The .deb and .rpm service unit needs no such step: it grants the
capabilities itself each time it starts.
A running service keeps the old binary until it restarts. Neither package restarts it for you. If you enabled the systemd unit, restart it after the upgrade:
sudo systemctl restart sipnab
The package upgrade replaces the unit file too. Put your changes to the unit
in a drop-in (sudo systemctl edit sipnab). The upgrade leaves the drop-in
alone.
Uninstall it
Remove sipnab the way you installed it. Every method below removes the binary itself. The last part covers the files sipnab may have read but never created.
If you used the one-line installer, it copied a single binary and nothing else. So deleting that file is the whole uninstall:
sudo rm -f /usr/local/bin/sipnab
If you set SIPNAB_INSTALL_DIR, remove the copy there instead. command -v
answers where it actually is, which beats guessing:
command -v sipnab
On Debian or Ubuntu, stop and disable the service first, then remove the package:
# Run all of these, in order.
sudo systemctl disable --now sipnab
sudo apt remove sipnab
The package does not stop the service itself. A running sipnab survives
apt remove with its binary deleted, and the unit’s enable link stays behind,
pointing at a file that no longer exists.
What apt remove and apt purge both leave in place:
- the
sipnabuser; /etc/sipnaband anything in it;/var/lib/sipnab, the unit’s state directory;- drop-ins in
/etc/systemd/system/sipnab.service.d.
Remove them yourself when you no longer need them:
# Run all of these, in order.
sudo rm -rf /etc/sipnab /var/lib/sipnab /etc/systemd/system/sipnab.service.d
sudo systemctl daemon-reload
sudo userdel sipnab
On RHEL or Fedora, the same: stop and disable the service, remove the package, and remove what the package leaves:
# Run all of these, in order.
sudo systemctl disable --now sipnab
sudo dnf remove sipnab
On macOS with Homebrew:
brew uninstall sipnab
If you installed with cargo:
cargo uninstall sipnab
No run creates a configuration file on its own, so there is usually nothing to clean up.
- sipnab reads the first configuration file it finds:
- the one named by
--config, - then
$SIPNAB_CONFIG, $XDG_CONFIG_HOME/sipnab/sipnab.toml(by default~/.config/sipnab/sipnab.toml),~/.sipnabrc,- and
/etc/sipnab/sipnab.toml.
- the one named by
- It reads the credential files named by
--hep-auth-file,--mcp-token-fileand--mcp-signing-key-file. - It writes none of those on its own. You do, if you want them.
Two TUI actions are the exception. Both need you to ask for them:
sin the F10 column selector saves the layout to[display] visible_columns.- With
[names] persist_to_config = true, theNnaming dialog saves mappings to[names.manual].
Where they write:
- Either writes into the config file the run loaded, whichever of the five it was. It leaves the rest of the file, comments included, intact.
- With no file loaded, it creates the user config file and its directory
(
$XDG_CONFIG_HOME/sipnab/sipnab.toml, by default~/.config/sipnab/sipnab.toml). - When the settings came from
/etc/sipnab/sipnab.toml, sipnab refuses the save and says so on the status line.- A file of your own would hide every setting in it.
- Copy that file to
~/.config/sipnab/sipnab.tomlfirst.
- The
Ndialog also keeps a mapping file at~/.config/sipnab/hostswhatever the config says.
Remove what you find there:
rm -rf ~/.config/sipnab
No package removes a system-wide config file, because none ships one.
- The
.debcreates an empty/etc/sipnabdirectory. The.rpmcreates nothing there. - So a
sipnab.tomlyou put in/etc/sipnabsurvivesapt remove,apt purgeanddnf removealike.
Remove it yourself:
sudo rm -rf /etc/sipnab
Next steps
- examples.md — copy-paste recipes for the most common tasks
- keybindings.md — driving the interactive TUI
- cli-reference.md — every flag, for headless use