Files
fips/packaging
Johnathan Corgan 7493153a89 Add a feature-gated profiler for the rx-loop maintenance tick
The tick arm runs twenty-six housekeeping steps in sequence on the one
runtime thread, and is polled last, so anything slow in it holds up
inbound packets, TUN traffic and control commands behind it. Field
evidence says that happens for over a second at a time, but the
attribution behind that is two months old and predates the
connect-on-send gate, the control read isolation, and the peer lifecycle
rework. This measures it rather than continuing to reason about it.

Per step it records exact count, max and total into fixed static
counters; a dedicated writer thread drains them every ten seconds to a
TSV under /var/log/fips, one file per capture, capped at 32 MB. Nothing
accumulates: the counters are swapped to zero each interval and the
thread holds no history. Arming is `fipsctl profile tick on`, served in
the control accept task so the toggle cannot queue behind the very
behaviour it measures, and it does not survive a restart.

The whole thing is behind a Cargo feature that is off by default,
because the risk worth eliminating is the twenty-six edited call sites
in the hot loop. With the feature off the macro expands to the bare
expression, which makes the default build's neutrality something you
read off the generated code rather than something a benchmark fails to
disprove.

The measurement that matters is how late each tick is against the
deadline it was scheduled for, since the arm is polled last and that
lateness is the delay. Two earlier designs derived it from the interval
between entries and both under-reported: the schedule is fixed, so a
steady delay leaves every gap exactly one period and any gap-derived
figure reads zero under precisely the sustained overload this is meant
to find. The interval hands back its own deadline, so the delay is now a
subtraction with no model behind it, and a test drives three late ticks
at a constant gap to keep it that way.

CI gains a default-features clippy and a feature-on build and test on
both runners, closing the gap left by clippy already running with all
features.
2026-07-28 00:56:54 +00:00
..

FIPS Packaging

This directory contains packaging for all supported target platforms. All build outputs go to deploy/ at the project root.

Quick Start

make deb        # Debian/Ubuntu .deb
make tarball    # systemd install tarball
make ipk        # OpenWrt .ipk (opkg, OpenWrt 24.x and earlier)
make apk        # OpenWrt .apk (apk-tools, mandatory on OpenWrt 25+)
make aur        # Arch Linux AUR package (fips-git, local build + namcap)
make pkg        # macOS .pkg installer
make zip        # Windows .zip package
make all        # deb + tarball (default)

Build Prerequisites

These targets build FIPS from source, so the host needs a build environment in addition to a Rust toolchain (the version pinned in rust-toolchain.toml is auto-installed by rustup).

On Linux, libclang is required: the LAN gateway's nftables bindings are generated by bindgen at build time, which needs libclang.so on the build host. Without it the build fails inside the rustables crate with an "Unable to find libclang" error.

sudo apt install libclang-dev    # Debian / Ubuntu

This is a build-time prerequisite only — it is not a runtime dependency, so hosts installing a pre-built .deb do not need it.

BLE support is optional and, when building with it, additionally needs bluez, libdbus-1-dev, and pkg-config; the build picks up BLE if those are present and skips it cleanly if not.

Directory Structure

packaging/
  aur/            Arch Linux AUR packaging (PKGBUILD, supporting files)
  common/         Shared assets (default config, hosts file)
  debian/         Debian/Ubuntu .deb packaging via cargo-deb
  macos/          macOS .pkg installer via pkgbuild
  systemd/        Generic Linux systemd tarball packaging
  openwrt-ipk/    OpenWrt .ipk packaging via cargo-zigbuild (opkg)
  openwrt-apk/    OpenWrt .apk packaging via cargo-zigbuild + apk mkpkg
  windows/        Windows .zip package with service scripts

Formats

Debian/Ubuntu (.deb)

Built with cargo-deb. Installs fips, fipsctl, and fipstop to /usr/bin/, and enables the systemd service.

The default configuration ships as an example at /usr/share/fips/fips.yaml.example and is not a dpkg conf-file. (It is deliberately not under /usr/share/doc, which minimal and container installs path-exclude, since the postinst reads it at install time.) On install, postinst seeds /etc/fips/fips.yaml (mode 600) from the example only if it does not already exist, so a configuration that was rendered by configuration management or edited by an operator is never prompted for or clobbered on upgrade. To reset to defaults, remove /etc/fips/fips.yaml and reinstall, or copy the example back manually.

# Build
make deb

# Install
sudo dpkg -i deploy/fips_<version>_<arch>.deb

# Remove (preserves config and keys)
sudo dpkg -r fips

# Purge (removes config and identity keys)
sudo dpkg -P fips

systemd Tarball

A self-contained tarball with binaries and an install.sh script for any systemd-based Linux distribution.

# Build
make tarball

# Install (on target host)
tar -xzf deploy/fips-<version>-linux-<arch>.tar.gz
sudo ./fips-<version>-linux-<arch>/install.sh

See systemd/README.install.md for full installation and configuration instructions.

OpenWrt (.ipk, opkg — OpenWrt 24.x and earlier)

Cross-compiled with cargo-zigbuild and assembled as a standard .ipk archive. Supports aarch64, mipsel, mips, arm, and x86_64 targets.

# Build (default: aarch64)
make ipk

# Build for a specific architecture
bash packaging/openwrt-ipk/build-ipk.sh --arch mipsel

See openwrt-ipk/README.md for router-specific installation instructions.

OpenWrt (.apk, apk-tools — mandatory on OpenWrt 25+)

OpenWrt 25 makes apk-tools the mandatory package manager (it is opt-in on 24.10). Same SDK-free approach (cargo-zigbuild), but the .apk container is assembled by apk mkpkg rather than hand-rolled, so the build additionally needs an apk-tools v3 apk binary built from source. The installed-filesystem payload is shared with the .ipk package.

# Build (default: aarch64; also x86_64)
make apk

# Build for a specific architecture
bash packaging/openwrt-apk/build-apk.sh --arch x86_64

Packages are unsigned; install with apk add --allow-untrusted. See openwrt-apk/README.md for building apk-tools and router-specific installation.

macOS (.pkg)

Built with pkgbuild (included with Xcode command-line tools). Installs binaries to /usr/local/bin/, config to /usr/local/etc/fips/, sets up the /etc/resolver/fips DNS resolver for .fips domains, and loads a launchd daemon. The TUN device is named utun<N> (kernel-assigned) rather than fips0.

# Build
make pkg

# Install
sudo installer -pkg deploy/fips-<version>-macos-<arch>.pkg -target /

# Remove
sudo packaging/macos/uninstall.sh

Windows (.zip)

A ZIP archive containing binaries, default config, and PowerShell service helper scripts. Requires the wintun driver for TUN support.

# Build
make zip

# Or directly
powershell -File packaging/windows/build-zip.ps1

# Extract and install as service (requires Administrator)
Expand-Archive deploy\fips-<version>-windows-x86_64.zip -DestinationPath fips
cd fips
powershell -File install-service.ps1

# Uninstall (preserves config)
powershell -File uninstall-service.ps1

# Uninstall and remove config
powershell -File uninstall-service.ps1 -RemoveAll

Arch Linux (AUR)

Two AUR packages are maintained: fips (release, builds from tagged tarball) and fips-git (development, builds from latest git master).

# Build and validate locally (git variant)
make aur

# Install from AUR
yay -S fips-git    # development build from master
yay -S fips        # release build from latest tag

See aur/README.md for AUR publication instructions and maintainer guide.

Nix / NixOS (flake)

A flake at the project root builds all four binaries (fips, fipsctl, fips-gateway, fipstop) from source. It pins the exact toolchain from rust-toolchain.toml via fenix and wires up the build-time native dependencies (libclang for bindgen, plus dbus and pkg-config for BLE), so it needs no system setup beyond Nix with flakes enabled.

nix build .#fips          # build the package (all four binaries)
nix run .#fips -- --help  # run a binary directly
nix run .#fipsctl -- status
nix develop               # dev shell with the pinned toolchain + cargo-edit
nix flake check           # build + validate the flake

Add to a NixOS configuration via the flake's packages.<system>.fips output, e.g. environment.systemPackages = [ fips.packages.${system}.default ];.

Shared Assets

common/ contains assets used across packaging formats:

  • fips.yaml — default configuration (ephemeral identity, UDP/TCP/TUN/DNS)
  • hosts — static hostname-to-npub mappings for .fips DNS resolution