Files
fips/packaging/nixos
ArjenandJohnathan Corgan a6567f9cf3 Add NixOS flake module (nixosModules.default) + overlay
Expose the fips daemon as a managed NixOS service so flake consumers
can enable it with a single line instead of hand-rolling a systemd unit.

Flake outputs (system-independent, outside eachDefaultSystem):
- overlays.default  — adds pkgs.fips
- nixosModules.default — packaging/nixos/ module providing services.fips.*

Module options (services.fips):
- enable        (bool, default false) — main mesh daemon
- package       (package, default pkgs.fips via overlay)
- configFile    (path, default /share/fips/fips.yaml) — seed source
- openFirewall  (bool, default true)  — UDP 2121 + TCP 8443
- dns.enable    (bool, default true)  — route .fips to [::1]:5354 via
                                         systemd-resolved (declarative,
                                         no setup/teardown scripts)
- gateway.enable(bool, default false) — outbound LAN gateway service

Hybrid config pattern: fips.yaml + identity keys live in /var/lib/fips/
(writable, seeded on first run only); hosts/ACL files stay at /etc/fips/
because fips hardcodes those paths on Linux. Launched with --config so
fips never loads /etc/fips/fips.yaml by accident.

flake.nix: ship fips.yaml, hosts, and fips.nft via postInstall so the
module can reference them from /share/fips/ without the source tree.
Also fix deprecated stdenv.isLinux -> stdenv.hostPlatform.isLinux and
platforms.linux ++ darwin -> platforms.unix.

packaging/README.md: document the overlay + module and show a full
flake.nix consumer example.
2026-08-23 17:39:22 +01:00
..

NixOS Packaging

NixOS module and flake outputs for FIPS.

Quick Start (flake consumers)

Add fips as a flake input and enable the service:

# flake.nix
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    fips = {
      url = "github:jmcorgan/fips";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, fips, ... }@inputs: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [
        ./configuration.nix
        fips.nixosModules.default     # ← import the module
        {
          services.fips.enable = true; # ← enable the daemon
        }
      ];
    };
  };
}

Apply with:

sudo nixos-rebuild switch --flake .#myhost

Options

Option Type Default Description
services.fips.enable bool false Enable the FIPS mesh network daemon
services.fips.package package pkgs.fips The fips package (provided via overlay)
services.fips.configFile path shipped default Default fips.yaml used to seed /var/lib/fips/fips.yaml on first run
services.fips.openFirewall bool true Open UDP 2121 + TCP 8443
services.fips.dns.enable bool true Route .fips queries to the fips DNS responder via systemd-resolved
services.fips.gateway.enable bool false Enable the outbound LAN gateway (fips-gateway.service)

What it does

  • Installs the fips, fipsctl, fipstop, and fips-gateway binaries
  • Creates a fips group (add your user for non-sudo fipsctl/fipstop)
  • Seeds /var/lib/fips/fips.yaml and /etc/fips/hosts from the shipped defaults on first run only — operator edits are never clobbered
  • Runs fips as a systemd service (fips.service) as root:fips (root is required for TUN interfaces and raw sockets)
  • Routes .fips DNS queries to the fips responder on [::1]:5354 via systemd-resolved (enabled by default; disable with services.fips.dns.enable = false)
  • Optionally runs the outbound LAN gateway (fips-gateway.service)
  • Opens firewall ports for UDP (2121) and TCP (8443) transports

Config file layout (hybrid pattern)

FIPS uses a hybrid config pattern that balances declarative defaults with operator-editable runtime state:

Path Purpose Writable Seeded from
/var/lib/fips/fips.yaml Main config yes services.fips.configFile (first run only)
/var/lib/fips/fips.key Node identity (private) yes generated by fips on first start
/var/lib/fips/fips.pub Node identity (public) yes generated by fips on first start
/etc/fips/hosts Static hostname → npub map yes shipped hosts (first run only)
/etc/fips/peers.allow Peer allowlist (ACL) yes operator-created
/etc/fips/peers.deny Peer denylist (ACL) yes operator-created
/etc/fips/fips.d/ nftables drop-in rules yes operator-created

Why two locations?

  • /var/lib/fips/ holds the main config and identity keys. This survives system rebuilds and reboots. fips derives key paths from the config file's parent directory, so fips.key/fips.pub land here automatically.
  • /etc/fips/ holds the hosts file and ACL files. fips hardcodes these paths on Linux (DEFAULT_HOSTS_PATH, DEFAULT_PEERS_ALLOW_PATH, DEFAULT_PEERS_DENY_PATH), so they cannot be relocated.

Why not environment.etc?

NixOS environment.etc creates symlinks into the read-only Nix store. That makes files immutable at runtime and would clobber operator edits on every rebuild. The module instead seeds real writable files via a preStart script that only runs when the target file is absent.

Why --config /var/lib/fips/fips.yaml?

fips has a config search path (./fips.yaml, ~/.config/fips/fips.yaml, /etc/fips/fips.yaml). Passing --config explicitly bypasses that search path entirely, so fips loads only the user-managed file and never accidentally picks up a stale /etc/fips/fips.yaml.

Usage after install

sudo journalctl -u fips -f     # follow logs
fipsctl show status            # check status (needs fips group membership)
fipstop                        # live monitoring

To use fipsctl/fipstop without sudo, add your user to the fips group:

users.users.myuser.extraGroups = [ "fips" ];

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

Editing config at runtime

sudo nano /var/lib/fips/fips.yaml   # edit main config
sudo nano /etc/fips/hosts           # add static hostname mappings
sudo nano /etc/fips/peers.allow     # add peers to the allowlist
sudo systemctl restart fips         # apply changes

Files are group-writable (0664, owned by root:fips), so fips group members can edit without sudo.

Files

packaging/nixos/
├── default.nix   # NixOS module (services.fips.*)
└── README.md     # this file

The flake also exposes:

  • overlays.default — adds pkgs.fips
  • nixosModules.default — the NixOS module