intake/module.nix

128 lines
3.8 KiB
Nix

flake:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
filterAttrs
foldl
imap1
mapAttrsToList
mkEnableOption
mkIf
mkMerge
mkOption
mkPackageOption
types
;
in
{
options = {
services.intake = {
package = mkPackageOption pkgs "intake" { };
extraPackages = mkOption {
type = types.listOf types.package;
default = [ ];
description = "Extra packages available to all enabled users and their intake services.";
};
users = mkOption {
description = "User intake service definitions.";
default = { };
type = types.attrsOf (
types.submodule {
options = {
enable = mkEnableOption "intake, a universal and extensible feed aggregator.";
dataDir = mkOption {
type = types.str;
default = "/home/$USER/.local/share/intake";
description = "The data directory for this user's intake service.";
};
listen.addr = mkOption {
type = types.str;
default = "127.0.0.1";
description = "The listen address for this user's intake service.";
};
listen.port = mkOption {
type = types.port;
default = 80;
description = "The listen port for this user's intake service.";
};
extraPackages = mkOption {
type = types.listOf types.package;
default = [ ];
description = "Extra packages available to this user and their intake service.";
};
};
}
);
};
};
};
config =
let
intakeCfg = config.services.intake;
enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users;
enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers;
userPackages =
userName:
[ intakeCfg.package ] ++ intakeCfg.extraPackages ++ intakeCfg.users.${userName}.extraPackages;
in
{
# Apply the overlay so intake is included in pkgs.
nixpkgs.overlays = [ flake.overlays.default ];
# Give every intake user the shared packages and their user-specific packages.
users.users =
let
addPackagesToUser = userName: {
${userName}.packages = userPackages userName;
};
in
mkMerge (map addPackagesToUser enabledUserNames);
# Define a user service for each configured user
systemd.services =
let
runScript =
userName:
let
listen = enabledUsers.${userName}.listen;
in
pkgs.writeShellScript "intake-run.sh" ''
mkdir -p $INTAKE_DATA_DIR
${intakeCfg.package}/bin/intake serve --addr ${listen.addr} --port ${toString listen.port}
'';
# systemd service definition for a single user, given `services.intake.users.userName` = `userCfg`
userServiceConfig = userName: userCfg: {
"intake-${userName}" = {
description = "Intake service for user ${userName}";
script = "${runScript userName}";
path = config.environment.systemPackages ++ intakeCfg.extraPackages ++ userCfg.extraPackages;
environment = {
INTAKE_DATA_DIR = "/home/${userName}/.local/share/intake";
};
serviceConfig = {
User = userName;
Type = "simple";
};
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
enable = userCfg.enable;
};
};
in
mkMerge (mapAttrsToList userServiceConfig enabledUsers);
};
}