Add Debian/Ubuntu .deb packaging and update README

Debian packaging via cargo-deb:
- Add [package.metadata.deb] to Cargo.toml with assets, dependencies,
  and conffiles declarations
- Maintainer scripts: postinst (create fips group, enable services,
  restart on upgrade), prerm (stop/disable on remove, stop-only on
  upgrade), postrm (purge config, keys, group)
- Systemd units (fips.service, fips-dns.service) with /usr/bin/ paths
  for .deb installs
- tmpfiles.d entry for /run/fips/ runtime directory
- build-deb.sh wrapper script for building packages

README rewrite:
- Replace run-from-source Quick Start with Building section
- Add Installation options: Debian .deb (cargo-deb) and generic Linux
  (systemd tarball)
- Add full Configuration reference with default fips.yaml
- Add Usage sections: DNS resolution, monitoring (fipsctl + fipstop),
  service management, and testing
- Update project structure and features list
This commit is contained in:
Johnathan Corgan
2026-03-08 02:56:33 +00:00
parent c086ee3edf
commit 231ef7c82d
10 changed files with 359 additions and 83 deletions
+24
View File
@@ -37,6 +37,30 @@ futures = "0.3"
simple-dns = "0.11.2" simple-dns = "0.11.2"
socket2 = { version = "0.6.2", features = ["all"] } socket2 = { version = "0.6.2", features = ["all"] }
[package.metadata.deb]
maintainer = "Johnathan Corgan <jcorgan@corganlabs.com>"
copyright = "2026 Johnathan Corgan"
license-file = ["LICENSE", "0"]
section = "net"
priority = "optional"
depends = "libc6, systemd"
extended-description = """\
FIPS is a distributed, decentralized network routing protocol for mesh \
nodes connecting over arbitrary transports including UDP, TCP, and Ethernet. \
It provides encrypted peer-to-peer connectivity with automatic key management, \
TUN-based virtual networking, and .fips DNS resolution."""
maintainer-scripts = "packaging/debian/"
assets = [
["target/release/fips", "/usr/bin/", "755"],
["target/release/fipsctl", "/usr/bin/", "755"],
["target/release/fipstop", "/usr/bin/", "755"],
["packaging/common/fips.yaml", "/etc/fips/fips.yaml", "600"],
["packaging/debian/fips.service", "/lib/systemd/system/fips.service", "644"],
["packaging/debian/fips-dns.service", "/lib/systemd/system/fips-dns.service", "644"],
["packaging/debian/fips.tmpfiles", "/usr/lib/tmpfiles.d/fips.conf", "644"],
]
conf-files = ["/etc/fips/fips.yaml"]
[dev-dependencies] [dev-dependencies]
tempfile = "3.15" tempfile = "3.15"
criterion = { version = "0.8.2", features = ["html_reports"] } criterion = { version = "0.8.2", features = ["html_reports"] }
+141 -83
View File
@@ -21,10 +21,19 @@ identities, discover each other, and route traffic without any central
authority or global topology knowledge. authority or global topology knowledge.
FIPS uses Nostr keypairs (secp256k1/schnorr) as native node identities, FIPS uses Nostr keypairs (secp256k1/schnorr) as native node identities,
making every Nostr user a potential network participant. Nodes address each allowing users to generate their own persistent or ephemeral node addresses.
other by npub, and the same cryptographic identity used in the Nostr ecosystem Nodes address each other by npub, and the same cryptographic identity serves
serves as both the routing address and the basis for end-to-end encrypted as both the routing address and the basis for end-to-end encrypted sessions
sessions across the mesh. across the mesh.
FIPS allows existing TCP/IP based network software to use the FIPS mesh
network by generating a local IP address from the node npub and tunnelling
IP packets to other endpoints transparently knowing only their npub. Native
FIPS-aware applications do not need this IP tunneling or emulation capability.
All traffic over the FIPS mesh is encrypted and authenticated both
hop-to-hop between peers and independently end-to-end between FIPS
endpoints.
## Features ## Features
@@ -42,129 +51,177 @@ sessions across the mesh.
measurement measurement
- **ECN congestion signaling** — hop-by-hop CE flag relay with RFC 3168 IPv6 - **ECN congestion signaling** — hop-by-hop CE flag relay with RFC 3168 IPv6
marking, transport kernel drop detection marking, transport kernel drop detection
- **Operator visibility** — `fipsctl` control socket interface for runtime - **Operator visibility** — `fipsctl` CLI and `fipstop` TUI dashboard for
inspection of peers, links, sessions, tree state, and metrics runtime inspection of peers, links, sessions, tree state, and metrics
- **Zero configuration** — sensible defaults; a node can start with no config - **Zero configuration** — sensible defaults; a node can start with no config
file, though peer addresses are needed to join a network file, though peer addresses are needed to join a network
## Quick Start ## Building
### Requirements ```bash
- Rust 1.85+ (edition 2024)
- Linux (TUN interface requires `CAP_NET_ADMIN` or root)
### Build
```
git clone https://github.com/fips-network/fips.git git clone https://github.com/fips-network/fips.git
cd fips cd fips
cargo build --release cargo build --release
``` ```
### Run Requires Rust 1.85+ (edition 2024) and Linux with TUN support.
``` ## Installation
# Start with default search paths (see below):
sudo ./target/release/fips
# With an explicit configuration file: After building, choose one of the following methods to install.
sudo ./target/release/fips -c fips.yaml
### Debian / Ubuntu (.deb)
Requires [cargo-deb](https://crates.io/crates/cargo-deb):
```bash
cargo install cargo-deb
cargo deb
sudo dpkg -i target/debian/fips_*.deb
``` ```
Without `-c`, the node searches for `fips.yaml` in these locations This installs the daemon, CLI tools, systemd units, and a default
(highest priority first, values from later files override earlier ones): configuration. Edit `/etc/fips/fips.yaml` before starting:
1. `./fips.yaml` (current directory) ```bash
2. `~/.config/fips/fips.yaml` (user config) sudo nano /etc/fips/fips.yaml
3. `/etc/fips/fips.yaml` (system) sudo systemctl start fips
```
If no config file is found, the node starts with defaults (ephemeral The service is enabled at boot automatically. To use `fipsctl` and
identity, default ports, no peers). `fipstop` without sudo, add your user to the `fips` group:
A minimal two-node setup (each node points at the other): ```bash
sudo usermod -aG fips $USER # log out and back in to take effect
```
Remove with `sudo dpkg -r fips` (preserves config) or
`sudo dpkg -P fips` (removes everything including identity keys).
### Generic Linux (systemd tarball)
```bash
./packaging/systemd/build-tarball.sh
tar xzf deploy/fips-*-linux-*.tar.gz
cd fips-*-linux-*/
sudo ./install.sh
```
See [packaging/systemd/README.install.md](packaging/systemd/README.install.md)
for the full installation and configuration guide.
## Configuration
The default configuration file is installed at `/etc/fips/fips.yaml`:
```yaml ```yaml
# node-a.yaml # node-b.yaml # FIPS Node Configuration
node: # node:
identity: # identity: node:
nsec: "nsec1aaa..." # nsec: "nsec1bbb..." identity:
transports: # transports: # By default, a new ephemeral keypair is generated on each start.
udp: # udp: # Uncomment persistent to keep the same identity across restarts;
bind_addr: "0.0.0.0:2121" # bind_addr: "0.0.0.0:2121" # on first start a keypair is saved to fips.key/fips.pub next to
peers: # peers: # this config file (mode 0600/0644).
- npub: "npub1bbb..." # - npub: "npub1aaa..." # persistent: true
addresses: # addresses: #
- transport: udp # - transport: udp # Or set an explicit key (overrides persistent):
addr: "10.0.0.2:2121" # addr: "10.0.0.1:2121" # nsec: "nsec1..."
tun:
enabled: true
name: fips0
mtu: 1280
dns:
enabled: true
bind_addr: "127.0.0.1"
port: 5354
transports:
udp:
bind_addr: "0.0.0.0:2121"
tcp:
# Accepts inbound connections. No static outbound peers.
bind_addr: "0.0.0.0:8443"
# Ethernet transport — uncomment and set your interface name.
# ethernet:
# interface: "eth0"
# discovery: true
# announce: true
# auto_connect: true
# accept_connections: true
peers: []
# Static peers for bootstrapping (UDP or TCP):
# - npub: "npub1..."
# alias: "gateway"
# addresses:
# - transport: udp
# addr: "217.77.8.91:2121" # public FIPS testing node
# connect_policy: auto_connect
``` ```
The `nsec` field accepts bech32 (`nsec1...`) or hex-encoded secret keys. See [docs/design/fips-configuration.md](docs/design/fips-configuration.md)
Omit `nsec` for an ephemeral identity that changes each restart, or set for the full reference.
`node.identity.persistent: true` to auto-generate and reuse a stable
identity via key file (see
[fips-configuration.md](docs/design/fips-configuration.md#identity-nodeidentity)).
See [docs/design/fips-configuration.md](docs/design/fips-configuration.md) for ## Usage
the full configuration reference.
### Test Connectivity ### DNS Resolution
FIPS includes a built-in DNS resolver (enabled by default, port 5354) FIPS includes a DNS resolver (enabled by default, port 5354) that maps
that maps `.fips` names to fd00::/8 IPv6 addresses derived from each `.fips` names to fd00::/8 IPv6 addresses. With systemd-resolved:
node's public key. Configure your system to send `.fips` queries to it.
With systemd-resolved: ```bash
```
sudo resolvectl dns fips0 127.0.0.1:5354 sudo resolvectl dns fips0 127.0.0.1:5354
sudo resolvectl domain fips0 ~fips sudo resolvectl domain fips0 ~fips
``` ```
Or manually in `/etc/resolv.conf` (routes all DNS through FIPS for Then reach any FIPS node by npub with standard IPv6 tools:
`.fips` names only if your resolver supports conditional forwarding;
otherwise this sets it as a general nameserver):
``` ```bash
nameserver 127.0.0.1
options port:5354
```
Once DNS is configured, ping a peer by npub:
```
ping6 npub1bbb....fips ping6 npub1bbb....fips
ssh npub1bbb....fips
``` ```
Any IPv6-capable application can reach FIPS nodes this way — `ping6`, ### Monitoring
`ssh`, `curl`, etc.
### Inspect Use `fipsctl` to query a running node:
While a node is running, use `fipsctl` to inspect its state: ```bash
```
fipsctl show status # Node status overview fipsctl show status # Node status overview
fipsctl show peers # Authenticated peers fipsctl show peers # Authenticated peers
fipsctl show links # Active links fipsctl show links # Active links
fipsctl show tree # Spanning tree state fipsctl show tree # Spanning tree state
fipsctl show sessions # End-to-end sessions fipsctl show sessions # End-to-end sessions
fipsctl show bloom # Bloom filter state
fipsctl show mmp # MMP metrics summary
fipsctl show cache # Coordinate cache stats
fipsctl show connections # Pending handshake connections
fipsctl show transports # Transport instances fipsctl show transports # Transport instances
fipsctl show routing # Routing table summary fipsctl show routing # Routing table summary
``` ```
`fipsctl` communicates with the node via a Unix domain control socket `fipstop` provides an interactive TUI dashboard with live-updating
(enabled by default). All queries are read-only. Use `-s <path>` to views of node status, peers, links, sessions, tree state, transports,
override the socket path. and routing:
### Multi-node Testing ```bash
fipstop # connect to local daemon
fipstop -r 1 # 1-second refresh interval
```
See [testing/](testing/) for Docker-based integration test harnesses including ### Service Management
static topology tests and stochastic chaos simulation.
```bash
sudo systemctl start fips
sudo systemctl stop fips
sudo systemctl restart fips
sudo journalctl -u fips -f
```
### Testing
See [testing/](testing/) for Docker-based integration test harnesses
including static topology tests and stochastic chaos simulation.
## Documentation ## Documentation
@@ -175,7 +232,8 @@ a layered protocol specification. Start with
## Project Structure ## Project Structure
``` ```
src/ Rust source (library + fips/fipsctl binaries) src/ Rust source (library + fips/fipsctl/fipstop binaries)
packaging/ Debian, systemd tarball, and shared packaging files
docs/design/ Protocol design specifications docs/design/ Protocol design specifications
testing/ Docker-based integration test harnesses testing/ Docker-based integration test harnesses
``` ```
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Build a .deb package for FIPS using cargo-deb.
#
# Usage: ./build-deb.sh
#
# Prerequisites: cargo-deb (install with: cargo install cargo-deb)
# Output: deploy/fips_<version>_<arch>.deb
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}/../.."
cd "${PROJECT_ROOT}"
# Ensure cargo-deb is available
if ! command -v cargo-deb &>/dev/null; then
echo "cargo-deb not found. Install with: cargo install cargo-deb" >&2
exit 1
fi
# Build the .deb package
echo "Building .deb package..."
cargo deb
# Move output to deploy/
mkdir -p deploy
DEB_FILE=$(find target/debian -name '*.deb' -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2)
if [ -z "${DEB_FILE}" ]; then
echo "Error: No .deb file found in target/debian/" >&2
exit 1
fi
cp "${DEB_FILE}" deploy/
BASENAME=$(basename "${DEB_FILE}")
echo "Package built: deploy/${BASENAME}"
echo ""
echo "Install with: sudo dpkg -i deploy/${BASENAME}"
echo "Remove with: sudo dpkg -r fips"
echo "Purge with: sudo dpkg -P fips (removes config and identity keys)"
+27
View File
@@ -0,0 +1,27 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: fips
Upstream-Contact: Johnathan Corgan <jcorgan@corganlabs.com>
Source: https://github.com/fips-network/fips
Files: *
Copyright: 2026 Johnathan Corgan
License: MIT
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=Configure DNS routing for .fips domain
After=systemd-resolved.service
Wants=systemd-resolved.service
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'while ! ip link show fips0 >/dev/null 2>&1; do sleep 1; done; /usr/bin/resolvectl dns fips0 127.0.0.1:5354; /usr/bin/resolvectl domain fips0 ~fips'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
+28
View File
@@ -0,0 +1,28 @@
[Unit]
Description=FIPS Mesh Network Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/fips --config /etc/fips/fips.yaml
Restart=on-failure
RestartSec=5
# Logging: RUST_LOG controls verbosity.
# Use "info" for production, "debug" for troubleshooting.
Environment=RUST_LOG=info
# Control socket directory (/run/fips/).
# Group-readable so 'fips' group members can use fipsctl/fipstop.
RuntimeDirectory=fips
RuntimeDirectoryMode=0750
# Security hardening (daemon runs as root for TUN and raw sockets)
ProtectHome=yes
PrivateTmp=yes
ProtectKernelModules=yes
ProtectKernelTunables=no
[Install]
WantedBy=multi-user.target
+1
View File
@@ -0,0 +1 @@
d /run/fips 0750 root fips -
+34
View File
@@ -0,0 +1,34 @@
#!/bin/sh
# FIPS post-install script for Debian/Ubuntu
set -e
case "$1" in
configure)
# Create fips system group for control socket access
if ! getent group fips >/dev/null 2>&1; then
groupadd --system fips
fi
# Ensure runtime directory exists with correct ownership
if [ -d /run/systemd/system ]; then
systemd-tmpfiles --create /usr/lib/tmpfiles.d/fips.conf 2>/dev/null || true
fi
# Reload systemd and enable services
if [ -d /run/systemd/system ]; then
systemctl daemon-reload
systemctl enable fips.service 2>/dev/null || true
systemctl enable fips-dns.service 2>/dev/null || true
# On upgrade, restart services that were running before
if [ -n "$2" ]; then
systemctl start fips.service 2>/dev/null || true
systemctl start fips-dns.service 2>/dev/null || true
fi
fi
;;
esac
#DEBHELPER#
exit 0
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
# FIPS post-removal script for Debian/Ubuntu
set -e
case "$1" in
purge)
# Remove configuration and identity keys
rm -rf /etc/fips/
# Remove tmpfiles.d entry
rm -f /usr/lib/tmpfiles.d/fips.conf
# Remove runtime directory
rm -rf /run/fips/
# Remove fips system group
if getent group fips >/dev/null 2>&1; then
groupdel fips 2>/dev/null || true
fi
;;
esac
#DEBHELPER#
exit 0
+26
View File
@@ -0,0 +1,26 @@
#!/bin/sh
# FIPS pre-removal script for Debian/Ubuntu
set -e
case "$1" in
remove|purge)
if [ -d /run/systemd/system ]; then
systemctl stop fips-dns.service 2>/dev/null || true
systemctl disable fips-dns.service 2>/dev/null || true
systemctl stop fips.service 2>/dev/null || true
systemctl disable fips.service 2>/dev/null || true
systemctl daemon-reload
fi
;;
upgrade)
# Stop services before upgrade; postinst will restart them
if [ -d /run/systemd/system ]; then
systemctl stop fips-dns.service 2>/dev/null || true
systemctl stop fips.service 2>/dev/null || true
fi
;;
esac
#DEBHELPER#
exit 0