mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-05 19:18:25 +00:00
An ephemeral node wrote the private key of an identity it discards on every restart to fips.key, and overwrote any key already at that path, including an operator's key in the case where persistent: true was forgotten. It now writes only fips.pub, so the running npub stays visible, and holds the private key in memory only. A fips.key found at an ephemeral start is moved aside to fips.key.unused with a warning rather than used or overwritten, so an operator's key is recoverable and a stale key from an earlier release stops being read by fipsctl address. If that name is already taken or the rename fails, the file is left in place, a warning says so, and the start continues. Persistent and explicit-nsec identities are unchanged. The keygen note, the Windows service installer's closing note, and the documentation that described the old write are corrected, including the persistent identity how-to, which told operators to start once in ephemeral mode and then pin the key it wrote.
144 lines
5.0 KiB
Markdown
144 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 with `persistent: true` |
|
|
| `/var/lib/fips/fips.pub` | Node identity (public) | yes | written by fips on every 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`, `~/.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
|