Files
fips/packaging/systemd
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 Installation Guide

Quick Start

tar xzf fips-*-linux-*.tar.gz
cd fips-*-linux-*/
sudo ./install.sh

What Gets Installed

File Location
fips (daemon) /usr/local/bin/fips
fipsctl (CLI) /usr/local/bin/fipsctl
fipstop (TUI) /usr/local/bin/fipstop
fips-gateway (LAN bridge) /usr/local/bin/fips-gateway
Configuration /etc/fips/fips.yaml
Identity key /etc/fips/fips.key (auto-generated)
Public key /etc/fips/fips.pub (auto-generated)
Hosts file /etc/fips/hosts
Firewall baseline /etc/fips/fips.nft
Firewall drop-in directory /etc/fips/fips.d/
Daemon unit /etc/systemd/system/fips.service (enabled)
DNS routing unit /etc/systemd/system/fips-dns.service (enabled)
Gateway unit /etc/systemd/system/fips-gateway.service (NOT enabled)
Firewall unit /etc/systemd/system/fips-firewall.service (NOT enabled)
DNS helpers /usr/lib/fips/fips-dns-{setup,teardown}

A system group fips is created for control socket access. By default, only fips.service and fips-dns.service are enabled at install time. fips-gateway.service and fips-firewall.service are installed but require explicit operator opt-in (see the sections below).

Post-Install Configuration

Edit /etc/fips/fips.yaml before starting the service.

1. Identity

By default, the node generates a new ephemeral identity on each start for privacy. If the node's npub will be published for others to use as a static peer, enable a stable identity by uncommenting persistent: true in the identity section:

node:
  identity:
    persistent: true

On first start with persistence enabled, a keypair is auto-generated and saved:

  • /etc/fips/fips.key (mode 0600) — secret key
  • /etc/fips/fips.pub (mode 0644) — public key (npub)

The same identity is reused on subsequent starts. Alternatively, set node.identity.nsec to use a specific key.

2. Ethernet Transport

If using Ethernet for local mesh discovery, uncomment the ethernet section and set the interface name:

transports:
  ethernet:
    interface: "eth0"
    listen: true
    announce: true
    auto_connect: true
    accept_connections: true

3. Bluetooth Transport

If using BLE for local mesh discovery, the FIPS binary must be built with the ble feature (enabled by default). BlueZ must be installed and running:

sudo apt install bluez
sudo systemctl enable --now bluetooth

Add your service user to the bluetooth group, or run with CAP_NET_ADMIN + CAP_NET_RAW capabilities.

Configure BLE in the transports section:

transports:
  ble:
    adapter: "hci0"
    advertise: true
    scan: true
    auto_connect: true
    accept_connections: true

4. Static Peers

For bootstrapping over UDP or TCP, add known peers:

peers:
  - npub: "npub1..."
    alias: "gateway"
    addresses:
      - transport: udp
        addr: "test-us01.fips.network:2121"  # IP or hostname (e.g., "peer.example.com:2121")
    connect_policy: auto_connect

5. DNS Resolver

FIPS includes a DNS responder for .fips domain names that listens on fips0 and on [::1]:5354. The fips-dns.service helper detects the host's DNS routing system and configures it to forward .fips queries to the responder. Backends tried in order:

  1. systemd dns-delegate drop-in (systemd >= 258, declarative)
  2. systemd-resolved global drop-in via /etc/systemd/resolved.conf.d/
  3. systemd-resolved per-link resolvectl (legacy fallback)
  4. dnsmasq (standalone, drops a config in /etc/dnsmasq.d/)
  5. NetworkManager with the dnsmasq plugin

If none of the supported backends is detected, fips-dns-setup logs a warning with manual instructions and exits cleanly. The daemon itself keeps working; only the host's .fips resolution is left unwired.

The installer enables fips-dns.service automatically. To disable or re-enable later:

sudo systemctl disable --now fips-dns.service   # disable
sudo systemctl enable --now fips-dns.service    # re-enable

6. Mesh-interface firewall baseline (optional)

fips.nft is a default-deny baseline for inbound traffic on the fips0 mesh interface. It is shipped as /etc/fips/fips.nft (not loaded by default) along with a disabled fips-firewall.service unit. Enable it explicitly:

sudo systemctl enable --now fips-firewall.service

The baseline polices only fips0, leaving Docker, Tor, the host firewall, and other interfaces untouched. Outbound from fips0 is unrestricted; inbound is dropped except for replies to outbound flows, ICMPv6 echo-request, and any operator drop-ins under /etc/fips/fips.d/*.nft. Read the comments at the top of /etc/fips/fips.nft for the full policy and how to add per-service allow rules.

7. Outbound LAN gateway (optional)

fips-gateway bridges unmodified LAN hosts to .fips destinations through a DNS-allocated virtual IPv6 pool and kernel nftables NAT. The binary is installed at /usr/local/bin/fips-gateway and a fips-gateway.service unit ships disabled by default.

To enable it, configure the gateway block in /etc/fips/fips.yaml, then:

sudo systemctl enable --now fips-gateway.service

The unit Requires=fips.service, waits up to 30 seconds for fips0 to come up, and runs fips-gateway --config /etc/fips/fips.yaml. Inbound port-forward rules can be added in the same gateway: block.

Firewall Ports

Port Protocol Purpose
2121 UDP Peer-to-peer mesh traffic
8443 TCP Inbound peer connections

Service Management

The install ships four units. fips.service and fips-dns.service are enabled at install time. fips-gateway.service and fips-firewall.service are installed but disabled until the operator opts in.

# Daemon
sudo systemctl start fips
sudo systemctl stop fips
sudo systemctl restart fips

# DNS routing helper
sudo systemctl restart fips-dns

# Optional services (opt-in)
sudo systemctl enable --now fips-firewall   # mesh-interface nftables baseline
sudo systemctl enable --now fips-gateway    # outbound LAN gateway

# View logs (any of the units above)
sudo journalctl -u fips -f
sudo journalctl -u fips-gateway -f
sudo journalctl -u fips-firewall -f

# Switch to debug logging
sudo systemctl set-environment RUST_LOG=debug
sudo systemctl restart fips

Monitoring

# Quick status
fipsctl show status

# Interactive dashboard
fipstop

# Other queries
fipsctl show peers
fipsctl show links
fipsctl show sessions
fipsctl show routing
fipsctl show transports

Non-Root Access to fipsctl/fipstop

Add your user to the fips group:

sudo usermod -aG fips $USER

Log out and back in for the group change to take effect.

Uninstall

# Remove binaries and service, keep configuration
sudo ./uninstall.sh

# Remove everything including /etc/fips/ and the fips group
sudo ./uninstall.sh --purge