nixos/service/portable: Provide an entrypoint function

... and tidy up in various small ways.

This should help a bit to make more clear the separation between
the portable parts and the systemd system service parts.
This commit is contained in:
Robert Hensing
2025-08-20 11:34:52 +02:00
parent d88b9464b0
commit 90162e8113
5 changed files with 81 additions and 31 deletions

View File

@@ -25,6 +25,7 @@ let
escapeShellArg escapeShellArg
concatMapStringsSep concatMapStringsSep
sourceFilesBySuffices sourceFilesBySuffices
modules
; ;
common = import ./common.nix; common = import ./common.nix;
@@ -129,7 +130,16 @@ let
''; '';
portableServiceOptions = buildPackages.nixosOptionsDoc { portableServiceOptions = buildPackages.nixosOptionsDoc {
inherit (evalModules { modules = [ ../../modules/system/service/portable/service.nix ]; }) options; inherit
(evalModules {
modules = [
(modules.importApply ../../modules/system/service/portable/service.nix {
pkgs = throw "nixos docs / portableServiceOptions: Do not reference pkgs in docs";
})
];
})
options
;
inherit revision warningsAreErrors; inherit revision warningsAreErrors;
transformOptions = transformOptions =
opt: opt:

View File

@@ -1,6 +1,11 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib) concatLists mapAttrsToList showOption; inherit (lib)
concatLists
mapAttrsToList
showOption
types
;
in in
rec { rec {
flattenMapServicesConfigToList = flattenMapServicesConfigToList =
@@ -30,4 +35,43 @@ rec {
assertion = ass.assertion; assertion = ass.assertion;
}) config.assertions }) config.assertions
); );
/**
This is the entrypoint for the portable part of modular services.
It provides the various options that are consumed by service manager implementations.
# Inputs
`serviceManagerPkgs`: A Nixpkgs instance which will be used for built-in logic such as converting `configData.<path>.text` to a store path.
`extraRootModules`: Modules to be loaded into the "root" service submodule, but not into its sub-`services`. That's the modules' own responsibility.
`extraRootSpecialArgs`: Fixed module arguments that are provided in a similar manner to `extraRootModules`.
# Output
An attribute set.
`serviceSubmodule`: a Module System option type which is a `submodule` with the portable modules and this function's inputs loaded into it.
*/
configure =
{
serviceManagerPkgs,
extraRootModules ? [ ],
extraRootSpecialArgs ? { },
}:
let
modules = [
(lib.modules.importApply ./service.nix { pkgs = serviceManagerPkgs; })
];
serviceSubmodule = types.submoduleWith {
class = "service";
modules = modules ++ extraRootModules;
specialArgs = extraRootSpecialArgs;
};
in
{
inherit serviceSubmodule;
};
} }

View File

@@ -1,3 +1,9 @@
# Non-module arguments
# These are separate from the module arguments to avoid implicit dependencies.
# This makes service modules self-contains, allowing mixing of Nixpkgs versions.
{ pkgs }:
# The module
{ {
lib, lib,
... ...
@@ -11,13 +17,14 @@ in
_class = "service"; _class = "service";
imports = [ imports = [
../../../misc/assertions.nix ../../../misc/assertions.nix
(lib.modules.importApply ./config-data.nix { inherit pkgs; })
]; ];
options = { options = {
services = mkOption { services = mkOption {
type = types.attrsOf ( type = types.attrsOf (
types.submoduleWith { types.submoduleWith {
modules = [ modules = [
./service.nix (lib.modules.importApply ./service.nix { inherit pkgs; })
]; ];
} }
); );

View File

@@ -52,8 +52,8 @@ let
in in
{ {
_class = "service";
imports = [ imports = [
../portable/service.nix
(lib.mkAliasOptionModule [ "systemd" "service" ] [ "systemd" "services" "" ]) (lib.mkAliasOptionModule [ "systemd" "service" ] [ "systemd" "services" "" ])
(lib.mkAliasOptionModule [ "systemd" "socket" ] [ "systemd" "sockets" "" ]) (lib.mkAliasOptionModule [ "systemd" "socket" ] [ "systemd" "sockets" "" ])
]; ];
@@ -101,6 +101,8 @@ in
}; };
} }
); );
# Rendered by the portable docs instead.
visible = false;
}; };
}; };
config = { config = {

View File

@@ -59,41 +59,28 @@ let
// concatMapAttrs ( // concatMapAttrs (
subServiceName: subService: makeUnits unitType (dash prefix subServiceName) subService subServiceName: subService: makeUnits unitType (dash prefix subServiceName) subService
) service.services; ) service.services;
modularServiceConfiguration = portable-lib.configure {
serviceManagerPkgs = pkgs;
extraRootModules = [
./service.nix
./config-data-path.nix
];
extraRootSpecialArgs = {
systemdPackage = config.systemd.package;
};
};
in in
{ {
_class = "nixos";
# First half of the magic: mix systemd logic into the otherwise abstract services # First half of the magic: mix systemd logic into the otherwise abstract services
options = { options = {
system.services = mkOption { system.services = mkOption {
description = '' description = ''
A collection of NixOS [modular services](https://nixos.org/manual/nixos/unstable/#modular-services) that are configured as systemd services. A collection of NixOS [modular services](https://nixos.org/manual/nixos/unstable/#modular-services) that are configured as systemd services.
''; '';
type = types.attrsOf ( type = types.attrsOf modularServiceConfiguration.serviceSubmodule;
types.submoduleWith {
class = "service";
modules = [
./service.nix
./config-data-path.nix
(lib.modules.importApply ../portable/config-data.nix { inherit pkgs; })
{
# Extend portable services option
options.services = lib.mkOption {
type = types.attrsOf (
types.submoduleWith {
modules = [
(lib.modules.importApply ../portable/config-data.nix { inherit pkgs; })
];
}
);
};
}
];
specialArgs = {
# perhaps: features."systemd" = { };
systemdPackage = config.systemd.package;
};
}
);
default = { }; default = { };
visible = "shallow"; visible = "shallow";
}; };