FIPS — Free Internetworking Peering System
===========================================

FIPS is a self-organizing encrypted mesh network built on Nostr identities,
capable of operating over arbitrary transports (UDP, TCP, Ethernet, Tor, Nym,
Bluetooth) without central infrastructure.

This is the SlackBuild that produces a Slackware .txz package from a GitHub
source release. It is not an official FIPS package; see the upstream project
for the canonical releases and documentation.

Upstream
--------
Project:   https://github.com/jmcorgan/fips
Website:   https://fips.network
Version:   0.5.1 (v0.5.1 tag)
License:   MIT

This SlackBuild builds from the v0.5.1 source tag. Change VERSION and
DOWNLOAD in fips.SlackBuild to build a different release.

Package contents
---------------
/bin
  fips            — mesh daemon
  fipsctl         — CLI control and inspection tool
  fipstop         — live TUI dashboard
  fips-gateway    — outbound LAN gateway binary (opt-in; see below)

/etc/fips
  fips.yaml         — node configuration (mode 0600; preserved on upgrade)
  fips.yaml.template — fresh default config (used when fips.yaml already exists)
  hosts            — static hostname-to-npub mappings for .fips DNS
  hosts.template   — fresh default hosts file
  fips.nft         — mesh-interface nftables baseline (mode 0644; opt-in)
  fips.nft.template — fresh default nftables ruleset
  fips.d/          — operator drop-in directory for nftables rules

/etc/rc.d/rc.fips     — init script (start|stop|restart|status)
/etc/dnsmasq.d/fips.conf     — dnsmasq .fips forwarding (see DNS section)
/etc/unbound/conf.d/fips.conf — unbound .fips forwarding (see DNS section)

/usr/doc/fips-0.5.1
  README, README.md, fips.dnsmasq.conf, fips.unbound.conf

Build prerequisites
-------------------
These are the packages a normal user needs to *build* the SlackBuild. Run
`./fips.SlackBuild` as yourself (no root required). Install these first:

  - rust (>= 1.94.1)
      The project pins Rust 1.94.1 in rust-toolchain.toml. Install via
      rustup (which will pull the pinned toolchain) or use any Rust >= 1.94.1.
      rustup is the recommended path:
        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
      Then ensure the toolchain is available:
        rustup default stable   # or the pinned toolchain if rustup manages it
      Rust is not in the Slackware 15.0 tree; see slackbuilds.org for a
      rust slackbuild if you prefer that route.

  - llvm (provides clang + libclang)
      Available in Slackware 15.0 /extra (package name: llvm). This is
      required at build time by the rustables crate, which uses bindgen to
      generate the nftables bindings. libclang.so + headers must be present
      for the build to succeed.
        installpkg /path/to/llvm-*.txz
      또는 slackbuilds.org 에서 llvm slackbuild 사용.

The following are assumed present on a standard Slackware 15.0 install and
are not documented as separate prerequisites:

  - dbus (provides D-Bus headers, dbus-1.pc, and libdbus-1.so)
      Required at build time by the bluer crate (BLE transport). Slackware
      ships dev files inside the main dbus package; there is no separate
      dbus-dev package. A stock Slackware 15.0 install already has this.

  - pkg-config, git, makepkg
      Standard Slackware tooling; present on a stock install.

Note: the build compiles all four binaries. The bluer (BLE) and rustables
(nftables) crates are compiled unconditionally on Linux because they are
declared as target-specific dependencies, not as optional features. Even if
you never use BLE or nftables at runtime, the build needs their dev headers
present. On Slackware 15.0 this means dbus (for bluer) and llvm (for
rustables) must both be installed before building.

Runtime requirements
--------------------
The daemon runs as root (it needs TUN and raw sockets). Non-root use of
fipsctl and fipstop requires membership in the fips group (created during
install).

  - TUN support
      The kernel must have TUN support (CONFIG_TUN) and /dev/net/tun must
      exist. Slackware 15.0 includes this by default on standard kernels.
      If /dev/net/tun is missing, load the tun module:
        modprobe tun

  - Optional: nftables (for fips-gateway and the fips-firewall ruleset)
      fips-gateway (opt-in LAN gateway) and the optional fips-firewall
      nftables ruleset both require nftables + the nft command at runtime.
      Slackware 15.0 ships nftables in /extra. If you do not use either
      feature, nftables is not required at runtime.
        installpkg /path/to/nftables-*.txz

Installation
------------
Build the package as a normal user:
    chmod +x fips.SlackBuild
    ./fips.SlackBuild

Install the resulting .txz as root:
    installpkg /tmp/fips-0.5.1-x86_64-1.txz

The post-install script (doinst.sh) runs automatically and:
  - Makes /etc/rc.d/rc.fips executable.
  - Creates the fips system group if it does not already exist.
  - Creates /var/run/fips with the correct ownership (re-created on each
    start by rc.fips if /var/run is tmpfs).

Configuration
-------------
Edit /etc/fips/fips.yaml before first start. Key settings:

  - Identity
      By default a new ephemeral keypair is generated on each start. For a
      persistent identity (recommended if you want static peers to reach you),
      uncomment "persistent: true" in the identity section. A keypair is then
      saved to /etc/fips/fips.key / fips.pub on first start.

  - Transports
      The default config enables UDP (0.0.0.0:2121), TCP (0.0.0.0:8443),
      and a TUN interface named fips0. Ethernet and BLE are opt-in; see the
      config file for the sections to uncomment.

  - DNS
      The daemon runs a DNS responder on [::1]:5354 by default. See the DNS
      section below for how to make your system resolve .fips names.

Starting the daemon
-------------------
Start manually:
    /etc/rc.d/rc.fips start

Check status:
    /etc/rc.d/rc.fips status
    fipsctl show status

Stop:
    /etc/rc.d/rc.fips stop

Restart:
    /etc/rc.d/rc.fips restart

Start at boot (optional): add the following to /etc/rc.d/rc.M, after the
networking blocks (e.g., after rc.inet2):
    if [ -x /etc/rc.d/rc.fips ]; then
      /etc/rc.d/rc.fips start
    fi

To stop at shutdown, add to /etc/rc.d/rc.K:
    if [ -x /etc/rc.d/rc.fips ]; then
      /etc/rc.d/rc.fips stop
    fi

Using fipsctl and fipstop without root
--------------------------------------
Add your user to the fips group:
    gpasswd -a $USER fips
Then log out and back in for group membership to take effect. After that,
fipsctl and fipstop connect to the daemon's control socket without sudo.

DNS: resolving .fips names
---------------------------
Every FIPS node has a Nostr identity (a "npub"). The daemon runs a local DNS
responder that answers queries like "<npub>.fips" with the node's current IPv6
mesh address. The /etc/fips/hosts file adds static alias.fips -> npub mappings
on top of that. This is how existing apps (SSH, browsers, etc.) refer to mesh
peers by name instead of by raw IPv6 address.

The daemon always provides the responder on [::1]:5354 (IPv6 loopback by
default). What the package does is ship a drop-in config for your local
resolver so that .fips queries get forwarded to that responder. The package
does NOT configure or start the resolver for you; that is an operator
decision, matching the FreeBSD packaging approach.

dnsmasq
~~~~~~~
If you run dnsmasq, the package installs /etc/dnsmasq.d/fips.conf. For it to
take effect:

  1. Ensure /etc/dnsmasq.conf has the conf-dir directive enabled:
       conf-dir=/etc/dnsmasq.d
     This line is shipped commented out in the Slackware dnsmasq package
     (line 678 in the default config).
  2. Ensure /etc/resolv.conf lists 127.0.0.1 (or ::1) as a nameserver so
     local queries reach dnsmasq.
  3. Start or reload dnsmasq:
       /etc/rc.d/rc.dnsmasq restart

unbound
~~~~~~~
If you run unbound, the package installs /etc/unbound/conf.d/fips.conf. For
it to take effect:

  1. Confirm your unbound is configured to read drop-ins from
     /etc/unbound/conf.d/ (some builds use a different path; if yours does,
     install the drop-in where your unbound reads it, or copy the contents
     into your main unbound.conf).
  2. unbound must be configured to allow loopback forwarding and IPv6:
       server:
         do-not-query-localhost: no
         do-ip6: yes
     These are the settings required for the drop-in to work. If your
     unbound.conf already sets these, the drop-in is sufficient. If not,
     add them to /etc/unbound/unbound.conf (or your included config) and
     reload unbound.
  3. Ensure /etc/resolv.conf lists 127.0.0.1 (or ::1) as a nameserver.
  4. Reload unbound:
       /etc/rc.d/rc.unbound restart

If you run neither dnsmasq nor unbound
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The daemon's DNS responder still works; your system just won't forward .fips
queries to it automatically. To resolve .fips names, configure whichever
resolver your system uses (or your router) to forward the fips. zone to
[::1]:5354.

fips-gateway (opt-in)
---------------------
fips-gateway is installed but not started by default. It bridges LAN clients
onto the FIPS mesh so that non-FIPS hosts can reach .fips destinations via
DNS-allocated virtual IPs and kernel NAT.

To use it:

  1. Configure a "gateway:" section in /etc/fips/fips.yaml (pool, lan
     interface, upstream DNS, conntrack settings — see the config file).
  2. Enable IPv6 forwarding and proxy_ndp as needed (the config file documents
     the sysctl settings).
  3. Start the gateway (manual):
       /usr/bin/fips-gateway --config /etc/fips/fips.yaml

fips-gateway requires nftables at runtime (its NAT backend is nftables, Linux
only). If you do not need LAN-gateway mode, you can ignore fips-gateway
entirely.

fips-firewall (opt-in)
----------------------
The package ships /etc/fips/fips.nft, a default-deny mesh-interface baseline
that polices only the fips0 interface. It is NOT applied automatically. To
use it:

  1. Edit /etc/fips/fips.nft if you want to add drop-ins under
     /etc/fips/fips.d/ (the file includes that directory).
  2. Apply it manually:
       nft -f /etc/fips/fips.nft
  3. To apply on every start, add the nft invocation to rc.fips (or to a
     separate rc script) — the package does not do this for you.

fips-firewall requires nftables at runtime. If you do not use it, the ruleset
is inert (it is not loaded).

Upgrading
---------
A new version of this SlackBuild produces a new .txz. Install it with
installpkg (or upgradepkg). The post-install script preserves your config and
identity keys in /etc/fips/. The config files are treated as user-edited:
fips.yaml and fips.nft are kept if they already exist, with fresh templates
installed alongside as .template files.

Because FIPS is pre-1.0 and the protocol and APIs are not yet stable, config
format and service layout may change between releases. Review the upstream
release notes before upgrading.

Logs
----
The daemon writes its log to /var/log/fips.log (append-only, managed by
rc.fips). /var/log is not rotated by this package. If you want rotation,
configure logrotate or a similar tool for /var/log/fips.log, or set up a
logrotate slackbuild. Rotating the log requires restarting the daemon unless
you move the file and signal the daemon to reopen its handles (the daemon
does not currently support log rotation signals).

Removal
-------
Remove the package:
    removepkg fips

This removes the binaries, init script, DNS drop-ins, and docs. It does NOT
remove /etc/fips/ (your config and identity keys) or the fips group. To
remove those as well:
    rm -rf /etc/fips
    groupdel fips

Building a different version
----------------------------
Edit the VERSION and DOWNLOAD variables at the top of fips.SlackBuild:
    VERSION="0.6.0"
    DOWNLOAD="https://github.com/jmcorgan/fips/archive/refs/tags/v${VERSION}.tar.gz"
Then rebuild. The version is also referenced in the package name and in the
documentation paths inside the package; update those if you change VERSION.

Maintainer
----------
This SlackBuild was prepared for personal use and may be shared. It is not an
official FIPS package and is not part of the upstream FIPS repository.

Known limitations
-----------------
- The daemon runs as root. Non-root control is via the fips group only.
- Log rotation is not set up by the package.
- fips-firewall is not applied automatically; it is an opt-in ruleset.
- .fips DNS resolution requires a local resolver (dnsmasq or unbound) to be
  configured and running; the package ships the drop-in but does not start
  or configure the resolver.
- BLE transport requires a running BlueZ daemon (bluetoothd) at runtime in
  addition to the build-time dbus dependency.
