mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-05 19:18:25 +00:00
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.
This commit is contained in:
@@ -44,7 +44,7 @@
|
|||||||
rustPlatform.bindgenHook # sets LIBCLANG_PATH + clang for bindgen
|
rustPlatform.bindgenHook # sets LIBCLANG_PATH + clang for bindgen
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [
|
buildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [
|
||||||
pkgs.dbus # libdbus-1.so.3, linked via bluer→libdbus-sys
|
pkgs.dbus # libdbus-1.so.3, linked via bluer→libdbus-sys
|
||||||
pkgs.stdenv.cc.cc.lib # libgcc_s.so.1, needed by every Rust binary
|
pkgs.stdenv.cc.cc.lib # libgcc_s.so.1, needed by every Rust binary
|
||||||
];
|
];
|
||||||
@@ -57,21 +57,29 @@
|
|||||||
src = ./.;
|
src = ./.;
|
||||||
# Drop the build dir and the usual editor/VCS noise so the source
|
# Drop the build dir and the usual editor/VCS noise so the source
|
||||||
# hash is stable and unrelated edits don't trigger rebuilds.
|
# hash is stable and unrelated edits don't trigger rebuilds.
|
||||||
filter =
|
filter = path: type: (pkgs.lib.cleanSourceFilter path type) && (baseNameOf path != "target");
|
||||||
path: type:
|
|
||||||
(pkgs.lib.cleanSourceFilter path type) && (baseNameOf path != "target");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoLock.lockFile = ./Cargo.lock;
|
cargoLock.lockFile = ./Cargo.lock;
|
||||||
|
|
||||||
inherit buildInputs;
|
inherit buildInputs;
|
||||||
|
|
||||||
|
# Ship the default config, hosts file, and nftables baseline so
|
||||||
|
# the NixOS module can reference them via $out/share/fips/ without
|
||||||
|
# needing the source tree. DNS routing is handled declaratively
|
||||||
|
# via services.resolved on NixOS (no setup/teardown scripts needed).
|
||||||
|
postInstall = ''
|
||||||
|
install -Dm 0644 ${./packaging/common/fips.yaml} $out/share/fips/fips.yaml
|
||||||
|
install -Dm 0644 ${./packaging/common/hosts} $out/share/fips/hosts
|
||||||
|
install -Dm 0644 ${./packaging/common/fips.nft} $out/share/fips/fips.nft
|
||||||
|
'';
|
||||||
|
|
||||||
# autoPatchelfHook rewrites the RPATH of the built binaries so the
|
# autoPatchelfHook rewrites the RPATH of the built binaries so the
|
||||||
# daemon finds libdbus-1.so.3 (linked via bluer→libdbus-sys) in the
|
# daemon finds libdbus-1.so.3 (linked via bluer→libdbus-sys) in the
|
||||||
# Nix store at runtime — without it the `fips` binary fails to load
|
# Nix store at runtime — without it the `fips` binary fails to load
|
||||||
# on NixOS where there is no global /usr/lib.
|
# on NixOS where there is no global /usr/lib.
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
nativeBuildInputs ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ];
|
nativeBuildInputs ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.autoPatchelfHook ];
|
||||||
|
|
||||||
# The test suite exercises TUN devices, raw sockets and mDNS, none of
|
# The test suite exercises TUN devices, raw sockets and mDNS, none of
|
||||||
# which exist in the build sandbox. The AUR/Debian packaging likewise
|
# which exist in the build sandbox. The AUR/Debian packaging likewise
|
||||||
@@ -84,7 +92,7 @@
|
|||||||
homepage = cargoToml.package.homepage;
|
homepage = cargoToml.package.homepage;
|
||||||
license = pkgs.lib.licenses.mit;
|
license = pkgs.lib.licenses.mit;
|
||||||
mainProgram = "fips";
|
mainProgram = "fips";
|
||||||
platforms = pkgs.lib.platforms.linux ++ pkgs.lib.platforms.darwin;
|
platforms = pkgs.lib.platforms.unix;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,5 +132,15 @@
|
|||||||
|
|
||||||
formatter = pkgs.nixfmt;
|
formatter = pkgs.nixfmt;
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
// {
|
||||||
|
# System-independent outputs — outside eachDefaultSystem.
|
||||||
|
# Overlay so consumers get pkgs.fips automatically.
|
||||||
|
overlays.default = final: prev: {
|
||||||
|
fips = self.packages.${final.system}.default;
|
||||||
|
};
|
||||||
|
|
||||||
|
# NixOS module — consumers import this and set services.fips.enable = true.
|
||||||
|
nixosModules.default = import ./packaging/nixos;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-2
@@ -48,6 +48,7 @@ packaging/
|
|||||||
debian/ Debian/Ubuntu .deb packaging via cargo-deb
|
debian/ Debian/Ubuntu .deb packaging via cargo-deb
|
||||||
freebsd/ FreeBSD .pkg packaging via pkg-create(8)
|
freebsd/ FreeBSD .pkg packaging via pkg-create(8)
|
||||||
macos/ macOS .pkg installer via pkgbuild
|
macos/ macOS .pkg installer via pkgbuild
|
||||||
|
nixos/ NixOS flake module (services.fips.*)
|
||||||
systemd/ Generic Linux systemd tarball packaging
|
systemd/ Generic Linux systemd tarball packaging
|
||||||
openwrt-ipk/ OpenWrt .ipk packaging via cargo-zigbuild (opkg)
|
openwrt-ipk/ OpenWrt .ipk packaging via cargo-zigbuild (opkg)
|
||||||
openwrt-apk/ OpenWrt .apk packaging via cargo-zigbuild + apk mkpkg
|
openwrt-apk/ OpenWrt .apk packaging via cargo-zigbuild + apk mkpkg
|
||||||
@@ -244,8 +245,45 @@ nix develop # dev shell with the pinned toolchain + cargo-edit
|
|||||||
nix flake check # build + validate the flake
|
nix flake check # build + validate the flake
|
||||||
```
|
```
|
||||||
|
|
||||||
Add to a NixOS configuration via the flake's `packages.<system>.fips`
|
The flake also exposes:
|
||||||
output, e.g. `environment.systemPackages = [ fips.packages.${system}.default ];`.
|
|
||||||
|
- `overlays.default` — adds `pkgs.fips` to nixpkgs
|
||||||
|
- `nixosModules.default` — a NixOS module (`packaging/nixos/`) that provides
|
||||||
|
`services.fips.enable` and runs the daemon as a systemd service
|
||||||
|
|
||||||
|
**As a package only** (no service management):
|
||||||
|
|
||||||
|
```nix
|
||||||
|
environment.systemPackages = [ fips.packages.${system}.default ];
|
||||||
|
```
|
||||||
|
|
||||||
|
**As a managed NixOS service** (recommended — starts on boot, journalctl logs):
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# flake.nix
|
||||||
|
{
|
||||||
|
inputs.fips = {
|
||||||
|
url = "github:jmcorgan/fips";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, fips, ... }@inputs: {
|
||||||
|
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
specialArgs = { inherit inputs; };
|
||||||
|
modules = [
|
||||||
|
./configuration.nix
|
||||||
|
fips.nixosModules.default
|
||||||
|
{ services.fips.enable = true; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See [`packaging/nixos/README.md`](nixos/README.md) for the full option
|
||||||
|
reference (`services.fips.enable`, `.package`, `.configFile`,
|
||||||
|
`.openFirewall`).
|
||||||
|
|
||||||
## Shared Assets
|
## Shared Assets
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
# 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
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
# NixOS module for the FIPS mesh network daemon.
|
||||||
|
#
|
||||||
|
# Exposed as nixosModules.default in flake.nix.
|
||||||
|
# Consumers enable it with:
|
||||||
|
#
|
||||||
|
# { inputs, ... }: {
|
||||||
|
# imports = [ inputs.fips.nixosModules.default ];
|
||||||
|
# services.fips.enable = true;
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# The package is provided via the flake's overlay (overlays.default), so it
|
||||||
|
# lands in pkgs.fips without the consumer needing to know the input name.
|
||||||
|
#
|
||||||
|
# --- Hybrid config pattern ---
|
||||||
|
#
|
||||||
|
# fips.yaml and identity keys live in /var/lib/fips/ (writable, survives
|
||||||
|
# reboots and rebuilds). The shipped default is seeded there on first run
|
||||||
|
# only; operator edits are never clobbered.
|
||||||
|
#
|
||||||
|
# The hosts file and ACL files (peers.allow, peers.deny) MUST stay at
|
||||||
|
# /etc/fips/ because fips hardcodes those paths on Linux
|
||||||
|
# (DEFAULT_HOSTS_PATH, DEFAULT_PEERS_ALLOW_PATH, DEFAULT_PEERS_DENY_PATH).
|
||||||
|
# They are seeded as real writable files (not Nix store symlinks) so the
|
||||||
|
# operator can edit them directly.
|
||||||
|
#
|
||||||
|
# fips is launched with --config /var/lib/fips/fips.yaml, which bypasses
|
||||||
|
# the config search path entirely — fips will never accidentally load
|
||||||
|
# /etc/fips/fips.yaml instead of the user-managed version.
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.fips;
|
||||||
|
stateDir = "/var/lib/fips";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.fips = {
|
||||||
|
enable = lib.mkEnableOption "FIPS mesh network daemon";
|
||||||
|
|
||||||
|
package = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.fips;
|
||||||
|
defaultText = lib.literalExpression "pkgs.fips";
|
||||||
|
description = ''
|
||||||
|
The fips package to use. Defaults to the one provided by the
|
||||||
|
fips flake overlay (overlays.default).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
configFile = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
default = "${cfg.package}/share/fips/fips.yaml";
|
||||||
|
defaultText = lib.literalExpression "''${cfg.package}/share/fips/fips.yaml";
|
||||||
|
description = ''
|
||||||
|
Default fips.yaml used to seed the writable config at
|
||||||
|
/var/lib/fips/fips.yaml on first run. The operator can then edit
|
||||||
|
/var/lib/fips/fips.yaml directly; this file is never overwritten
|
||||||
|
after the initial seed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Open firewall ports for fips transports
|
||||||
|
(UDP 2121, TCP 8443).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dns = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Route .fips queries to the fips DNS responder on [::1]:5354
|
||||||
|
via systemd-resolved. Without this, .fips hostnames don't
|
||||||
|
resolve on the host.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gateway = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Enable the outbound LAN gateway. Lets non-fips hosts on the
|
||||||
|
LAN reach mesh destinations via DNS-allocated virtual IPs
|
||||||
|
and kernel NAT. Requires the fips daemon running with DNS.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# 'fips' group so non-root users can run fipsctl/fipstop without sudo
|
||||||
|
# and edit config/hosts files group-writable.
|
||||||
|
users.groups.fips = { };
|
||||||
|
|
||||||
|
# Writable directories for hosts file, ACL files, and nftables drop-ins.
|
||||||
|
# fips hardcodes /etc/fips/hosts, /etc/fips/peers.allow,
|
||||||
|
# /etc/fips/peers.deny on Linux, so these MUST live here. Created as
|
||||||
|
# real directories (not environment.etc symlinks) so the operator can
|
||||||
|
# edit files in place.
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /etc/fips 0775 root fips -"
|
||||||
|
"d /etc/fips/fips.d 0775 root fips -"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services.fips = {
|
||||||
|
description = "FIPS Mesh Network Daemon";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [
|
||||||
|
"network-online.target"
|
||||||
|
"systemd-tmpfiles-setup.service"
|
||||||
|
];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
|
||||||
|
# Seed config and hosts on first run only. Existing files are never
|
||||||
|
# overwritten, so operator edits survive service restarts and system
|
||||||
|
# rebuilds.
|
||||||
|
preStart = ''
|
||||||
|
# Seed writable config from the shipped default (only if absent).
|
||||||
|
# fips derives key paths (fips.key/fips.pub) from the config file's
|
||||||
|
# parent directory, so keys also land in /var/lib/fips/.
|
||||||
|
if [ ! -f ${stateDir}/fips.yaml ]; then
|
||||||
|
cp "${cfg.configFile}" ${stateDir}/fips.yaml
|
||||||
|
chown root:fips ${stateDir}/fips.yaml
|
||||||
|
chmod 0664 ${stateDir}/fips.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Seed hosts file (fips hardcodes /etc/fips/hosts on Linux).
|
||||||
|
if [ ! -f /etc/fips/hosts ]; then
|
||||||
|
cp "${cfg.package}/share/fips/hosts" /etc/fips/hosts
|
||||||
|
chown root:fips /etc/fips/hosts
|
||||||
|
chmod 0664 /etc/fips/hosts
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
# Run as root:fips so the daemon has root for TUN/raw sockets while
|
||||||
|
# group members can access the control socket and state files.
|
||||||
|
Group = "fips";
|
||||||
|
# --config bypasses the search path: fips loads ONLY this file,
|
||||||
|
# never /etc/fips/fips.yaml.
|
||||||
|
ExecStart = "${cfg.package}/bin/fips --config ${stateDir}/fips.yaml";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 5;
|
||||||
|
|
||||||
|
# Writable state directory (/var/lib/fips/) for config + keys.
|
||||||
|
# root:fips 0775 so group members can edit the config.
|
||||||
|
StateDirectory = "fips";
|
||||||
|
StateDirectoryMode = "0775";
|
||||||
|
|
||||||
|
# Control socket directory (/run/fips/) — group-accessible.
|
||||||
|
RuntimeDirectory = "fips";
|
||||||
|
RuntimeDirectoryMode = "0770";
|
||||||
|
|
||||||
|
# Log directory (/var/log/fips/) for the built-in profiler.
|
||||||
|
LogsDirectory = "fips";
|
||||||
|
|
||||||
|
# Security hardening (daemon runs as root for TUN and raw sockets).
|
||||||
|
# Mirrors packaging/systemd/fips.service.
|
||||||
|
ProtectHome = "yes";
|
||||||
|
PrivateTmp = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.resolved = lib.mkIf cfg.dns.enable {
|
||||||
|
enable = true;
|
||||||
|
settings.Resolve = {
|
||||||
|
DNS = [ "[::1]:5354" ];
|
||||||
|
Domains = [ "~fips" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.fips-gateway = lib.mkIf cfg.gateway.enable {
|
||||||
|
description = "FIPS Outbound LAN Gateway";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "fips.service" ];
|
||||||
|
requires = [ "fips.service" ];
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
${pkgs.iproute2}/bin/ip link show fips0 >/dev/null 2>&1 && exit 0
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "fips0 did not appear within 30s" >&2
|
||||||
|
exit 1
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${cfg.package}/bin/fips-gateway --config ${stateDir}/fips.yaml";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 5;
|
||||||
|
TimeoutStopSec = 15;
|
||||||
|
ProtectHome = "yes";
|
||||||
|
PrivateTmp = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||||
|
allowedTCPPorts = [ 8443 ];
|
||||||
|
allowedUDPPorts = [ 2121 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user