Files
fips/packaging/nixos/README.md
T
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

143 lines
5.0 KiB
Markdown

# NixOS Packaging
NixOS module and flake outputs for FIPS.
## Quick Start (flake consumers)
Add fips as a flake input and enable the service:
```nix
# 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:
```sh
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
```sh
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:
```nix
users.users.myuser.extraGroups = [ "fips" ];
```
Log out and back in for the group change to take effect.
### Editing config at runtime
```sh
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