feat!: make declarative version

This commit is contained in:
Jet 2026-03-21 02:09:38 -07:00
parent cf3c5ef1f5
commit f4d95c595e
No known key found for this signature in database
13 changed files with 493 additions and 95 deletions

View file

@ -25,11 +25,11 @@ nix build .#noisebell-discord
## NixOS deployment
The flake exports NixOS modules. Each service runs as a hardened systemd unit behind Caddy.
The flake exports a NixOS module for the hosted remote machine. It imports `agenix`, declares the Noisebell secrets from `secrets/*.age`, and wires the cache and Discord services together with sensible defaults. Each service runs as a hardened systemd unit behind Caddy.
```nix
{
inputs.noisebell.url = "git+https://git.extremist.software/jet/noisebell?dir=remote";
inputs.noisebell.url = "git+https://git.extremist.software/jet/noisebell";
outputs = { self, nixpkgs, noisebell, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
@ -41,19 +41,11 @@ The flake exports NixOS modules. Each service runs as a hardened systemd unit be
enable = true;
domain = "cache.noisebell.example.com";
piAddress = "http://noisebell-pi:80";
piApiKeyFile = "/run/secrets/noisebell-pi-api-key";
inboundApiKeyFile = "/run/secrets/noisebell-inbound-api-key";
outboundWebhooks = [{
url = "http://localhost:3001/webhook";
secretFile = "/run/secrets/noisebell-discord-webhook-secret";
}];
};
services.noisebell-discord = {
enable = true;
domain = "discord.noisebell.example.com";
discordTokenFile = "/run/secrets/noisebell-discord-token";
channelId = "123456789012345678";
webhookSecretFile = "/run/secrets/noisebell-discord-webhook-secret";
};
})
];
@ -61,3 +53,14 @@ The flake exports NixOS modules. Each service runs as a hardened systemd unit be
};
}
```
`nixosModules.default` handles these secrets automatically:
| Secret file | Deployed on | Used for |
|-------------|-------------|----------|
| `secrets/pi-to-cache-key.age` | Pi + remote | Pi authenticates to cache `/webhook` |
| `secrets/cache-to-pi-key.age` | Pi + remote | cache authenticates to Pi GET endpoints |
| `secrets/discord-webhook-secret.age` | remote | cache authenticates to Discord bot `/webhook` |
| `secrets/discord-token.age` | remote | Discord bot login |
When `extremist-software` builds a system using the Noisebell flake input, Nix uses the checked-out flake source for that input. The module points `agenix` at encrypted files inside that Noisebell source tree, such as `${inputs.noisebell}/secrets/discord-token.age`. At activation time `agenix` decrypts them locally on the target host into runtime paths like `/run/agenix/noisebell-discord-token`. The service modules then read those local decrypted files when systemd starts them.

61
remote/hosted-module.nix Normal file
View file

@ -0,0 +1,61 @@
{ self, agenix }:
{ config, lib, ... }:
let
cfgCache = config.services.noisebell-cache;
cfgDiscord = config.services.noisebell-discord;
in
{
imports = [ agenix.nixosModules.default ];
users.groups.noisebell = { };
users.users.noisebell-cache.extraGroups = lib.mkIf cfgCache.enable [ "noisebell" ];
users.users.noisebell-discord.extraGroups = lib.mkIf cfgDiscord.enable [ "noisebell" ];
age.secrets.noisebell-pi-to-cache-key = {
file = "${self}/secrets/pi-to-cache-key.age";
group = "noisebell";
mode = "0440";
};
age.secrets.noisebell-cache-to-pi-key = {
file = "${self}/secrets/cache-to-pi-key.age";
group = "noisebell";
mode = "0440";
};
age.secrets.noisebell-discord-token = {
file = "${self}/secrets/discord-token.age";
group = "noisebell";
mode = "0440";
};
age.secrets.noisebell-discord-webhook-secret = {
file = "${self}/secrets/discord-webhook-secret.age";
group = "noisebell";
mode = "0440";
};
services.noisebell-cache = lib.mkIf cfgCache.enable {
piApiKeyFile = lib.mkDefault config.age.secrets.noisebell-cache-to-pi-key.path;
inboundApiKeyFile = lib.mkDefault config.age.secrets.noisebell-pi-to-cache-key.path;
outboundWebhooks = lib.mkDefault (
lib.optional cfgDiscord.enable {
url = "http://127.0.0.1:${toString cfgDiscord.port}/webhook";
secretFile = config.age.secrets.noisebell-discord-webhook-secret.path;
}
);
};
services.noisebell-discord = lib.mkIf cfgDiscord.enable (
{
discordTokenFile = lib.mkDefault config.age.secrets.noisebell-discord-token.path;
webhookSecretFile = lib.mkDefault config.age.secrets.noisebell-discord-webhook-secret.path;
}
// lib.optionalAttrs cfgCache.enable {
cacheUrl = lib.mkDefault "http://127.0.0.1:${toString cfgCache.port}";
imageBaseUrl = lib.mkDefault "https://${cfgCache.domain}/image";
}
);
}