modules/flake/services: init

This commit is contained in:
Nikodem Rabuliński 2025-01-04 20:46:16 +01:00
parent 5c3f1dac68
commit 68445b2146
6 changed files with 111 additions and 2 deletions

View file

@ -24,6 +24,7 @@ Collection of my personal Nix configurations and opinionated NixOS, nix-darwin,
- system - my opinionated nixos/nix-darwin modules
- home - my opinionated home-manager modules
- flake - flake-parts modules
- services - configs for services I self-host
- secrets - agenix secrets
- wrappers - nix packages wrapped with my configs (see: [wrapper-manager](https://github.com/viperML/wrapper-manager))
- assets - miscellaneous values reused throughout my config

View file

@ -16,6 +16,7 @@
./modules
./wrappers
./pkgs
./services
];
perSystem =

View file

@ -62,7 +62,10 @@
nixos =
name: module:
baseNixos.extendModules {
modules = [ module ];
modules = [
module
config.__extraHostConfigs.${name} or { }
];
specialArgs.configurationName = name;
};
@ -70,7 +73,10 @@
name: module:
let
eval = baseDarwin._module.args.extendModules {
modules = [ module ];
modules = [
module
config.__extraHostConfigs.${name} or { }
];
specialArgs.configurationName = name;
};
in

View file

@ -8,5 +8,6 @@
imports = [
(import ./configurations.nix { inherit nixpkgs darwin home-manager; })
./services.nix
];
}

View file

@ -0,0 +1,95 @@
# List of features I want this module to eventually have
# TODO: Automatic port allocation
# TODO: Making it possible to conveniently isolate services (running them in NixOS containers)
# TODO: Handling specializations
# TODO: Convenient http handling
# TODO: Automatic backup
{ config, lib, ... }:
let
serviceModule =
{ config, ... }:
{
options = {
host = lib.mkOption {
type = lib.types.str;
};
ports = lib.mkOption {
type = with lib.types; listOf port;
default = [ ];
};
hosts = lib.mkOption {
type = with lib.types; listOf str;
default = [ config.host ];
};
config = lib.mkOption {
type = lib.types.deferredModule;
default = { };
};
hostConfig = lib.mkOption {
type = with lib.types; attrsOf deferredModule;
default = { };
};
};
};
moduleToHostConfigs =
cfg:
lib.genAttrs cfg.hosts (host: {
imports = [
cfg.config
(cfg.hostConfig.${host} or { })
];
});
maybeGetPreviousConfigs = acc: host: (acc.${host} or { imports = [ ]; }).imports;
in
{
_file = ./services.nix;
options = {
services = lib.mkOption {
type = with lib.types; attrsOf (submodule serviceModule);
default = { };
};
__extraHostConfigs = lib.mkOption {
type = with lib.types; attrsOf deferredModule;
readOnly = true;
};
};
config.__extraHostConfigs =
let
duplicatePorts = lib.pipe config.services [
lib.attrValues
(map (cfg: cfg.ports))
lib.flatten
(lib.groupBy' (cnt: _: cnt + 1) 0 toString)
(lib.filterAttrs (_: cnt: cnt > 1))
lib.attrNames
];
assertMsg =
let
plural = lib.length duplicatePorts > 1;
in
"\nBad service config:\nThe following port${if plural then "s" else ""} ${
if plural then "were" else "was"
} declared multiple times: ${lib.concatStringsSep ", " duplicatePorts}";
# Here I collect all the services.<name>.config into a flat
# __extraHostConfigs.<host>.imports = [
# ...
# ]
# so that I can easily import them in hosts/default.nix
hostConfigs = lib.pipe config.services [
lib.attrValues
(lib.foldl' (
acc: cfg:
acc
// lib.mapAttrs (host: c: {
imports = c.imports ++ (maybeGetPreviousConfigs acc host);
}) (moduleToHostConfigs cfg)
) { })
];
in
if duplicatePorts != [ ] then throw assertMsg else hostConfigs;
}

5
services/default.nix Normal file
View file

@ -0,0 +1,5 @@
{
imports = [
];
}