Files
fips/packaging/freebsd/README.md
T
Johnathan Corgan 30a283907b Correct the release documents the readiness pass found wrong
The closing code fence in the release notes carried an info string, so under
CommonMark it was not a closer and the block ran to the end of the file.
Rendered through GitHub's own markdown endpoint the published body stopped
emitting headings after "Upgrade notes" and ended inside a code block, so
the download section, the changelog and security links and the contributor
credits all became preformatted text. Rendering the corrected file the same
way returns all seven headings and a working release link. A lint fix had
rewritten both fences rather than only the opening one.

The post-upgrade instruction named a subcommand that does not exist: it said
to run fipsctl status, which exits 2, where the command is fipsctl show
status. That instruction is aimed at exactly the users this release exists
for.

Several claims were broader than the tree supports, and each is narrowed to
what is true. The two discovery fixes carry no platform gating, so the notes
no longer tell macOS, Windows, FreeBSD and OpenWrt users that nothing
changed for them, and no longer say the release contains no behavioral
change. The supported-distribution paragraph now covers the .deb and the
tarball rather than all Linux artifacts, since Arch and NixOS build from
source and OpenWrt is a musl target that does not depend on the glibc floor.
The install-test sentence says x86_64, because the arm64 package is
install-tested by nothing. The changelog no longer claims every producer
runs the floor check, since the deprecated host-build targets do not.

The counter guidance was wrong about which counter moves, the objdump line
prints the symbol beside the version, and the two relative links in the
notes resolve inside the repository but 404 in a release body, so they are
absolute now. That last change also makes the root mirror byte-identical to
the versioned copy for the first time.

The FreeBSD install line takes a concrete filename again: a placeholder is
not pasteable, which is the whole point of an install instruction.
2026-09-06 20:20:56 +00:00

101 lines
4.0 KiB
Markdown

# FIPS FreeBSD packaging
Builds a native FreeBSD `.pkg` shipping `fips`, `fipsctl`, `fipstop`,
rc.d services, and `.fips` DNS integration. `fips-gateway` is excluded
(its NAT backend is nftables, Linux-only).
Platform notes: the Ethernet and BLE transports are not available on
FreeBSD (UDP, TCP, Tor, and Nym are). The UDP datapath deliberately
uses the portable single-packet receive loop — FreeBSD's `recvmmsg(2)`
is a libc loop over `recvmsg`, not a kernel batch, so the Linux/macOS
batched arm would gain nothing — and the connected-UDP fast path is
not compiled pending FreeBSD-specific `SO_REUSEPORT` validation.
## Build
```sh
./packaging/freebsd/build-pkg.sh # cargo build --release + pkg create
./packaging/freebsd/build-pkg.sh --no-build # package existing release binaries
```
Output: `deploy/fips-<version>-freebsd-<arch>.pkg` (e.g.
`fips-0.5.1.dev-freebsd-amd64.pkg` — pkg versions cannot contain `-`).
## Install
```sh
pkg add ./deploy/fips-0.5.1-freebsd-amd64.pkg
# post-install seeds this from the sample if absent, at mode 0600
vi /usr/local/etc/fips/fips.yaml
sysrc fips_enable=YES fips_dns_enable=YES
service fips start
service fips_dns start
fipsctl show status
```
Config installs sample-style (`@sample` semantics via manifest
scripts), so an edited `fips.yaml` survives upgrade/removal.
`fips.yaml` is installed `0600` — it may hold the node's private key
(`nsec:`). The daemon runs under daemon(8) with pidfile
`/var/run/fips/fips.pid` and logs to `/var/log/fips.log` (rc.conf
knobs: `fips_config`, `fips_flags`, `fips_logfile`).
The package creates a `fips` group; members can run `fipsctl` and
`fipstop` without root (`pw groupmod fips -m <user>`, then re-login).
On `pkg upgrade` the services are stopped before the binaries are
replaced and started again afterwards if enabled; on `pkg delete` they
are stopped and the `.fips` resolver drop-in is removed.
## .fips DNS integration
The daemon answers `.fips` queries on `[::1]:5354`. `fips_dns` points
the system resolver's `fips.` zone there; backends tried in order:
base `local_unbound` (drop-in `/var/unbound/conf.d/fips.conf`), pkg
`unbound`, pkg `dnsmasq`. The unbound drop-in must (and does) set:
- `do-not-query-localhost: no` — unbound's default silently refuses
loopback forwarders, SERVFAILing every `.fips` query.
- `do-ip6: yes` — the daemon binds `::1` only.
- `domain-insecure: "fips."` — the zone is unsigned.
### One-time host resolver setup (NOT automated)
The package configures the `fips.` zone only; making the local
resolver the *system* resolver is an operator decision. On a typical
box:
```sh
sysrc local_unbound_enable=YES
local-unbound-setup 1.1.1.1 9.9.9.9 # explicit upstreams — see below
service local_unbound restart
```
Field-tested caveats (`fips-dns-setup` detects and warns about each):
- `/etc/resolv.conf` must list a loopback nameserver (ideally only
`127.0.0.1`), or nothing ever queries unbound and `.fips` cannot
resolve.
- **Do not use a home-router DNS proxy as unbound's upstream.** Many
CPE forwarders are EDNS-broken; unbound always sends EDNS, so every
public query SERVFAILs. Forward to real resolvers (ISP or public).
- Remove `options edns0` from `/etc/resolv.conf` if present, and set
`resolv_conf_options=""` in `/etc/resolvconf.conf` so resolvconf(8)
does not re-add it — against an EDNS-broken router it breaks libc
resolution outright.
- Never run `local-unbound-setup` with no arguments while resolv.conf
already points at 127.0.0.1 — it snapshots that as upstream and
forwards unbound to itself.
## Debugging
```sh
drill -p 5354 <npub>.fips @::1 AAAA # daemon directly (bypasses unbound)
drill <npub>.fips AAAA # full chain; SERVER: must be 127.0.0.1
cat /var/run/fips/dns-backend # which backend fips_dns configured
```
The TUN interface gets a kernel-assigned name (`tun0`, `tun1`, ...),
like `utun` on macOS, and is destroyed automatically when the daemon
exits. `ifconfig <name>` prints `Opened by PID <n>` for the process
holding a tun device.