Major overhaul of the nix side of things, part II.
This commit is contained in:
parent
9759c2da12
commit
ce4cf7149d
7 changed files with 371 additions and 303 deletions
18
flake.lock
generated
18
flake.lock
generated
|
|
@ -121,6 +121,23 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-nonflake": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1679437018,
|
||||
"narHash": "sha256-vOuiDPLHSEo/7NkiWtxpHpHgoXoNmrm+wkXZ6a072Fc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "19cf008bb18e47b6e3b4e16e32a9a4bdd4b45f7e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1678872516,
|
||||
|
|
@ -169,6 +186,7 @@
|
|||
"devshell": "devshell",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-nonflake": "nixpkgs-nonflake",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"rust-overlay": "rust-overlay",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
|
|
|
|||
240
flake.nix
240
flake.nix
|
|
@ -1,6 +1,12 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
# We re-use the systemd lib from NixOS, this input allows to import the needed modules.
|
||||
# TODO: is there a better way to do this?
|
||||
nixpkgs-nonflake = {
|
||||
url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake = false;
|
||||
};
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
devshell = {
|
||||
url = "github:numtide/devshell";
|
||||
|
|
@ -41,6 +47,7 @@
|
|||
outputs =
|
||||
{ self
|
||||
, nixpkgs
|
||||
, nixpkgs-nonflake
|
||||
, flake-utils
|
||||
, rust-overlay
|
||||
, crane
|
||||
|
|
@ -49,137 +56,140 @@
|
|||
, pre-commit-hooks
|
||||
,
|
||||
}:
|
||||
(flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ (import rust-overlay) devshell.overlays.default ];
|
||||
};
|
||||
# TODO Pin the version for release
|
||||
rust = pkgs.rust-bin.stable.latest;
|
||||
llvm = pkgs.llvmPackages_latest;
|
||||
(flake-utils.lib.eachSystem
|
||||
(with flake-utils.lib.system; [ x86_64-linux aarch64-linux ])
|
||||
(system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ (import rust-overlay) devshell.overlays.default ];
|
||||
};
|
||||
# TODO Pin the version for release
|
||||
rust = pkgs.rust-bin.stable.latest;
|
||||
llvm = pkgs.llvmPackages_latest;
|
||||
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain rust.default;
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain rust.default;
|
||||
|
||||
# Common derivation arguments used for all builds
|
||||
commonArgs = {
|
||||
src = craneLib.cleanCargoSource ./.;
|
||||
buildInputs = with pkgs; [
|
||||
dbus
|
||||
];
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pkg-config
|
||||
];
|
||||
};
|
||||
# Common derivation arguments used for all builds
|
||||
commonArgs = {
|
||||
src = craneLib.cleanCargoSource ./.;
|
||||
buildInputs = with pkgs; [
|
||||
dbus
|
||||
];
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pkg-config
|
||||
];
|
||||
};
|
||||
|
||||
# Build only the cargo dependencies
|
||||
cargoArtifacts = craneLib.buildDepsOnly (commonArgs // {
|
||||
pname = "system-manager";
|
||||
});
|
||||
# Build only the cargo dependencies
|
||||
cargoArtifacts = craneLib.buildDepsOnly (commonArgs // {
|
||||
pname = "system-manager";
|
||||
});
|
||||
|
||||
system-manager = craneLib.buildPackage (commonArgs // {
|
||||
pname = "system-manager";
|
||||
inherit cargoArtifacts;
|
||||
});
|
||||
system-manager = craneLib.buildPackage (commonArgs // {
|
||||
pname = "system-manager";
|
||||
inherit cargoArtifacts;
|
||||
});
|
||||
|
||||
system-manager-clippy = craneLib.cargoClippy (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
|
||||
});
|
||||
system-manager-clippy = craneLib.cargoClippy (commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
|
||||
});
|
||||
|
||||
# treefmt-nix configuration
|
||||
treefmt.config = {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
nixpkgs-fmt.enable = true;
|
||||
rustfmt = {
|
||||
enable = true;
|
||||
package = rust.rustfmt;
|
||||
# treefmt-nix configuration
|
||||
treefmt.config = {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
nixpkgs-fmt.enable = true;
|
||||
rustfmt = {
|
||||
enable = true;
|
||||
package = rust.rustfmt;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
inherit system-manager;
|
||||
default = self.packages.${system}.system-manager;
|
||||
};
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
inherit system-manager;
|
||||
default = self.packages.${system}.system-manager;
|
||||
};
|
||||
|
||||
devShells.default = pkgs.devshell.mkShell {
|
||||
packages = with pkgs; [
|
||||
llvm.clang
|
||||
openssl
|
||||
pkg-config
|
||||
(rust.default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
})
|
||||
(treefmt-nix.lib.mkWrapper pkgs treefmt.config)
|
||||
];
|
||||
env = [
|
||||
{
|
||||
name = "PKG_CONFIG_PATH";
|
||||
value = pkgs.lib.makeSearchPath "lib/pkgconfig" [
|
||||
pkgs.dbus.dev
|
||||
pkgs.systemdMinimal.dev
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "LIBCLANG_PATH";
|
||||
value = "${llvm.libclang}/lib";
|
||||
}
|
||||
{
|
||||
# for rust-analyzer
|
||||
name = "RUST_SRC_PATH";
|
||||
value = "${rust.rust-src}";
|
||||
}
|
||||
{
|
||||
name = "RUST_BACKTRACE";
|
||||
value = "1";
|
||||
}
|
||||
{
|
||||
name = "RUSTFLAGS";
|
||||
value =
|
||||
let
|
||||
getLib = pkg: "${pkgs.lib.getLib pkg}/lib";
|
||||
in
|
||||
pkgs.lib.concatStringsSep " " [
|
||||
"-L${getLib pkgs.systemdMinimal} -lsystemd"
|
||||
devShells.default = pkgs.devshell.mkShell {
|
||||
packages = with pkgs; [
|
||||
llvm.clang
|
||||
openssl
|
||||
pkg-config
|
||||
(rust.default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
})
|
||||
(treefmt-nix.lib.mkWrapper pkgs treefmt.config)
|
||||
];
|
||||
env = [
|
||||
{
|
||||
name = "PKG_CONFIG_PATH";
|
||||
value = pkgs.lib.makeSearchPath "lib/pkgconfig" [
|
||||
pkgs.dbus.dev
|
||||
pkgs.systemdMinimal.dev
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "DEVSHELL_NO_MOTD";
|
||||
value = "1";
|
||||
}
|
||||
];
|
||||
devshell.startup.pre-commit.text = (pre-commit-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
check-format = {
|
||||
enable = true;
|
||||
entry = "treefmt --fail-on-change";
|
||||
}
|
||||
{
|
||||
name = "LIBCLANG_PATH";
|
||||
value = "${llvm.libclang}/lib";
|
||||
}
|
||||
{
|
||||
# for rust-analyzer
|
||||
name = "RUST_SRC_PATH";
|
||||
value = "${rust.rust-src}";
|
||||
}
|
||||
{
|
||||
name = "RUST_BACKTRACE";
|
||||
value = "1";
|
||||
}
|
||||
{
|
||||
name = "RUSTFLAGS";
|
||||
value =
|
||||
let
|
||||
getLib = pkg: "${pkgs.lib.getLib pkg}/lib";
|
||||
in
|
||||
pkgs.lib.concatStringsSep " " [
|
||||
"-L${getLib pkgs.systemdMinimal} -lsystemd"
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "DEVSHELL_NO_MOTD";
|
||||
value = "1";
|
||||
}
|
||||
];
|
||||
devshell.startup.pre-commit.text = (pre-commit-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
check-format = {
|
||||
enable = true;
|
||||
entry = "treefmt --fail-on-change";
|
||||
};
|
||||
cargo-clippy = {
|
||||
enable = true;
|
||||
description = "Lint Rust code.";
|
||||
entry = "cargo-clippy --workspace -- -D warnings";
|
||||
files = "\\.rs$";
|
||||
pass_filenames = false;
|
||||
};
|
||||
};
|
||||
cargo-clippy = {
|
||||
enable = true;
|
||||
description = "Lint Rust code.";
|
||||
entry = "cargo-clippy --workspace -- -D warnings";
|
||||
files = "\\.rs$";
|
||||
pass_filenames = false;
|
||||
};
|
||||
};
|
||||
}).shellHook;
|
||||
};
|
||||
}).shellHook;
|
||||
};
|
||||
|
||||
checks = {
|
||||
inherit
|
||||
# Build the crate as part of `nix flake check` for convenience
|
||||
system-manager
|
||||
system-manager-clippy;
|
||||
};
|
||||
}))
|
||||
checks = {
|
||||
inherit
|
||||
# Build the crate as part of `nix flake check` for convenience
|
||||
system-manager
|
||||
system-manager-clippy;
|
||||
};
|
||||
}))
|
||||
//
|
||||
{
|
||||
lib = import ./nix/lib.nix {
|
||||
inherit nixpkgs self;
|
||||
nixosModules = "${nixpkgs-nonflake}/nixos";
|
||||
};
|
||||
|
||||
systemConfigs.default = self.lib.makeSystemConfig {
|
||||
|
|
|
|||
31
nix/lib.nix
31
nix/lib.nix
|
|
@ -1,5 +1,6 @@
|
|||
{ nixpkgs
|
||||
, self
|
||||
{ nixpkgs # The nixpkgs flake
|
||||
, self # The system-manager flake
|
||||
, nixosModules # The path to the nixos modules dir from nixpkgs
|
||||
,
|
||||
}:
|
||||
let
|
||||
|
|
@ -16,22 +17,30 @@ in
|
|||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (self.packages.${system}) system-manager;
|
||||
|
||||
# TODO can we call lib.evalModules directly instead of building a NixOS system?
|
||||
nixosConfig = (lib.nixosSystem {
|
||||
inherit system;
|
||||
# Module that sets additional module arguments
|
||||
extraArgsModule = { lib, config, pkgs, ... }: {
|
||||
_module.args = {
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
utils = import "${nixosModules}/lib/utils.nix" {
|
||||
inherit lib config pkgs;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = (lib.evalModules {
|
||||
modules = [
|
||||
extraArgsModule
|
||||
./modules/system-manager.nix
|
||||
] ++ modules;
|
||||
specialArgs = extraSpecialArgs;
|
||||
}).config;
|
||||
|
||||
returnIfNoAssertions = drv:
|
||||
let
|
||||
failedAssertions = map (x: x.message) (lib.filter (x: !x.assertion) nixosConfig.assertions);
|
||||
failedAssertions = map (x: x.message) (lib.filter (x: !x.assertion) config.assertions);
|
||||
in
|
||||
if failedAssertions != [ ]
|
||||
then throw "\nFailed assertions:\n${lib.concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
|
||||
else lib.showWarnings nixosConfig.warnings drv;
|
||||
else lib.showWarnings config.warnings drv;
|
||||
|
||||
services =
|
||||
lib.mapAttrs'
|
||||
|
|
@ -40,7 +49,7 @@ in
|
|||
storePath =
|
||||
''${unit.unit}/${unitName}'';
|
||||
})
|
||||
nixosConfig.system-manager.systemd.units;
|
||||
config.systemd.units;
|
||||
|
||||
servicesPath = pkgs.writeTextFile {
|
||||
name = "services";
|
||||
|
|
@ -64,7 +73,7 @@ in
|
|||
|
||||
filteredEntries = lib.filterAttrs
|
||||
(_name: etcFile: etcFile.enable)
|
||||
nixosConfig.system-manager.environment.etc;
|
||||
config.environment.etc;
|
||||
|
||||
srcDrvs = lib.mapAttrs addToStore filteredEntries;
|
||||
|
||||
|
|
@ -131,7 +140,7 @@ in
|
|||
|
||||
declare -a failed_assertions=()
|
||||
|
||||
${mkAssertions nixosConfig.system-manager.preActivationAssertions}
|
||||
${mkAssertions config.system-manager.preActivationAssertions}
|
||||
|
||||
if [ ''${#failed_assertions[@]} -ne 0 ]; then
|
||||
for failed_assertion in ''${failed_assertions[@]}; do
|
||||
|
|
|
|||
|
|
@ -4,79 +4,77 @@
|
|||
}:
|
||||
{
|
||||
config = {
|
||||
system-manager = {
|
||||
environment.etc = {
|
||||
foo = {
|
||||
text = ''
|
||||
This is just a test!
|
||||
'';
|
||||
target = "foo_test";
|
||||
};
|
||||
|
||||
"foo.conf".text = ''
|
||||
launch_the_rockets = true
|
||||
environment.etc = {
|
||||
foo = {
|
||||
text = ''
|
||||
This is just a test!
|
||||
'';
|
||||
|
||||
"baz/bar/foo2" = {
|
||||
text = ''
|
||||
Another test!
|
||||
'';
|
||||
mode = "symlink";
|
||||
};
|
||||
|
||||
foo3 = {
|
||||
text = "boo!";
|
||||
mode = "0700";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
"a/nested/example/foo3" = {
|
||||
text = "boo!";
|
||||
mode = "0764";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
"a/nested/example2/foo3" = {
|
||||
text = "boo!";
|
||||
mode = "0764";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
out-of-store = {
|
||||
source = "/run/systemd/system/";
|
||||
};
|
||||
target = "foo_test";
|
||||
};
|
||||
|
||||
"foo.conf".text = ''
|
||||
launch_the_rockets = true
|
||||
'';
|
||||
|
||||
"baz/bar/foo2" = {
|
||||
text = ''
|
||||
Another test!
|
||||
'';
|
||||
mode = "symlink";
|
||||
};
|
||||
|
||||
foo3 = {
|
||||
text = "boo!";
|
||||
mode = "0700";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
"a/nested/example/foo3" = {
|
||||
text = "boo!";
|
||||
mode = "0764";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
"a/nested/example2/foo3" = {
|
||||
text = "boo!";
|
||||
mode = "0764";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
out-of-store = {
|
||||
source = "/run/systemd/system/";
|
||||
};
|
||||
systemd.services =
|
||||
lib.listToAttrs
|
||||
(lib.flip lib.genList 10 (ix:
|
||||
lib.nameValuePair "service-${toString ix}"
|
||||
{
|
||||
enable = true;
|
||||
description = "service-${toString ix}";
|
||||
wants = [ "network-online.target" ];
|
||||
after = [
|
||||
"network-online.target"
|
||||
"avahi-daemon.service"
|
||||
"chrony.service"
|
||||
"nss-lookup.target"
|
||||
"tinc.service"
|
||||
"pulseaudio.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecReload = "${lib.getBin pkgs.coreutils}/bin/true";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requiredBy = lib.mkIf (ix > 5) [ "service-0.service" ];
|
||||
script = ''
|
||||
sleep ${if ix > 5 then "2" else "1"}
|
||||
'';
|
||||
})
|
||||
);
|
||||
};
|
||||
systemd.services =
|
||||
lib.listToAttrs
|
||||
(lib.flip lib.genList 10 (ix:
|
||||
lib.nameValuePair "service-${toString ix}"
|
||||
{
|
||||
enable = true;
|
||||
description = "service-${toString ix}";
|
||||
wants = [ "network-online.target" ];
|
||||
after = [
|
||||
"network-online.target"
|
||||
"avahi-daemon.service"
|
||||
"chrony.service"
|
||||
"nss-lookup.target"
|
||||
"tinc.service"
|
||||
"pulseaudio.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecReload = "${lib.getBin pkgs.coreutils}/bin/true";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requiredBy = lib.mkIf (ix > 5) [ "service-0.service" ];
|
||||
script = ''
|
||||
sleep ${if ix > 5 then "2" else "1"}
|
||||
'';
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
, ...
|
||||
}:
|
||||
{
|
||||
options.system-manager = {
|
||||
options = {
|
||||
environment.etc = lib.mkOption {
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
|
|
@ -100,7 +100,6 @@
|
|||
Changing this option takes precedence over `gid`.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = {
|
||||
|
|
@ -110,7 +109,6 @@
|
|||
in lib.mkDerivedConfig options.text (pkgs.writeText name')
|
||||
);
|
||||
};
|
||||
|
||||
}
|
||||
));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,35 +8,54 @@
|
|||
./systemd.nix
|
||||
];
|
||||
|
||||
options.system-manager = {
|
||||
allowAnyDistro = lib.mkEnableOption "the usage of system-manager on untested distributions";
|
||||
options = {
|
||||
assertions = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.unspecified;
|
||||
internal = true;
|
||||
default = [ ];
|
||||
example = [{ assertion = false; message = "you can't enable this for that reason"; }];
|
||||
description = lib.mdDoc ''
|
||||
This option allows modules to express conditions that must
|
||||
hold for the evaluation of the system configuration to
|
||||
succeed, along with associated error messages for the user.
|
||||
'';
|
||||
};
|
||||
|
||||
preActivationAssertions = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule ({ name, ... }: {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "the assertion";
|
||||
warnings = lib.mkOption {
|
||||
internal = true;
|
||||
default = [ ];
|
||||
type = lib.types.listOf lib.types.str;
|
||||
example = [ "The `foo' service is deprecated and will go away soon!" ];
|
||||
description = lib.mdDoc ''
|
||||
This option allows modules to show warnings to users during
|
||||
the evaluation of the system configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
system-manager = {
|
||||
allowAnyDistro = lib.mkEnableOption "the usage of system-manager on untested distributions";
|
||||
|
||||
preActivationAssertions = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule ({ name, ... }: {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "the assertion";
|
||||
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
script = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
script = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = { };
|
||||
}));
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
# Avoid some standard NixOS assertions
|
||||
boot = {
|
||||
loader.grub.enable = false;
|
||||
initrd.enable = false;
|
||||
};
|
||||
system.stateVersion = lib.mkDefault lib.trivial.release;
|
||||
|
||||
system-manager.preActivationAssertions = {
|
||||
osVersion =
|
||||
|
|
|
|||
|
|
@ -6,13 +6,31 @@
|
|||
}:
|
||||
|
||||
let
|
||||
cfg = config.system-manager.systemd;
|
||||
cfg = config.systemd;
|
||||
|
||||
inherit (utils) systemdUtils;
|
||||
systemd-lib = utils.systemdUtils.lib;
|
||||
in
|
||||
{
|
||||
options.system-manager.systemd = {
|
||||
options.systemd = {
|
||||
|
||||
# TODO: this is a bit dirty.
|
||||
# The value here gets added to the PATH of every service.
|
||||
# We could consider copying the systemd lib from NixOS and removing the bits
|
||||
# that are not relevant to us, like this option.
|
||||
package = lib.mkOption {
|
||||
type = lib.types.oneOf [ lib.types.str lib.types.path lib.types.package ];
|
||||
default = pkgs.systemdMinimal;
|
||||
};
|
||||
|
||||
globalEnvironment = lib.mkOption {
|
||||
type = with lib.types; attrsOf (nullOr (oneOf [ str path package ]));
|
||||
default = { };
|
||||
example = { TZ = "CET"; };
|
||||
description = lib.mdDoc ''
|
||||
Environment variables passed to *all* systemd units.
|
||||
'';
|
||||
};
|
||||
|
||||
units = lib.mkOption {
|
||||
description = lib.mdDoc "Definition of systemd units.";
|
||||
|
|
@ -106,87 +124,85 @@ in
|
|||
};
|
||||
|
||||
config = {
|
||||
system-manager = {
|
||||
systemd = {
|
||||
timers =
|
||||
lib.mapAttrs
|
||||
(name: service:
|
||||
{
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = service.startAt;
|
||||
})
|
||||
(lib.filterAttrs (name: service: service.enable && service.startAt != [ ]) cfg.services);
|
||||
|
||||
units =
|
||||
lib.mapAttrs' (n: v: lib.nameValuePair "${n}.path" (systemd-lib.pathToUnit n v)) cfg.paths
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.service" (systemd-lib.serviceToUnit n v)) cfg.services
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.slice" (systemd-lib.sliceToUnit n v)) cfg.slices
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.socket" (systemd-lib.socketToUnit n v)) cfg.sockets
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.target" (systemd-lib.targetToUnit n v)) cfg.targets
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.timer" (systemd-lib.timerToUnit n v)) cfg.timers
|
||||
// lib.listToAttrs (map
|
||||
(v:
|
||||
let n = utils.escapeSystemdPath v.where;
|
||||
in lib.nameValuePair "${n}.mount" (systemd-lib.mountToUnit n v))
|
||||
cfg.mounts)
|
||||
// lib.listToAttrs (map
|
||||
(v:
|
||||
let n = utils.escapeSystemdPath v.where;
|
||||
in lib.nameValuePair "${n}.automount" (systemd-lib.automountToUnit n v))
|
||||
cfg.automounts);
|
||||
};
|
||||
|
||||
environment.etc =
|
||||
let
|
||||
allowCollisions = false;
|
||||
|
||||
enabledUnits = cfg.units;
|
||||
in
|
||||
{
|
||||
"systemd/system".source = pkgs.runCommand "system-manager-units"
|
||||
systemd = {
|
||||
timers =
|
||||
lib.mapAttrs
|
||||
(name: service:
|
||||
{
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
}
|
||||
''
|
||||
mkdir -p $out
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = service.startAt;
|
||||
})
|
||||
(lib.filterAttrs (name: service: service.enable && service.startAt != [ ]) cfg.services);
|
||||
|
||||
for i in ${toString (lib.mapAttrsToList (n: v: v.unit) enabledUnits)}; do
|
||||
fn=$(basename $i/*)
|
||||
if [ -e $out/$fn ]; then
|
||||
if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
|
||||
ln -sfn /dev/null $out/$fn
|
||||
else
|
||||
${if allowCollisions then ''
|
||||
mkdir -p $out/$fn.d
|
||||
ln -s $i/$fn $out/$fn.d/overrides.conf
|
||||
'' else ''
|
||||
echo "Found multiple derivations configuring $fn!"
|
||||
exit 1
|
||||
''}
|
||||
fi
|
||||
else
|
||||
ln -fs $i/$fn $out/
|
||||
fi
|
||||
done
|
||||
|
||||
${lib.concatStrings (
|
||||
lib.mapAttrsToList (name: unit:
|
||||
lib.concatMapStrings (name2: ''
|
||||
mkdir -p $out/'${name2}.wants'
|
||||
ln -sfn '../${name}' $out/'${name2}.wants'/
|
||||
'') (unit.wantedBy or [])
|
||||
) enabledUnits)}
|
||||
|
||||
${lib.concatStrings (
|
||||
lib.mapAttrsToList (name: unit:
|
||||
lib.concatMapStrings (name2: ''
|
||||
mkdir -p $out/'${name2}.requires'
|
||||
ln -sfn '../${name}' $out/'${name2}.requires'/
|
||||
'') (unit.requiredBy or [])
|
||||
) enabledUnits)}
|
||||
'';
|
||||
};
|
||||
units =
|
||||
lib.mapAttrs' (n: v: lib.nameValuePair "${n}.path" (systemd-lib.pathToUnit n v)) cfg.paths
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.service" (systemd-lib.serviceToUnit n v)) cfg.services
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.slice" (systemd-lib.sliceToUnit n v)) cfg.slices
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.socket" (systemd-lib.socketToUnit n v)) cfg.sockets
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.target" (systemd-lib.targetToUnit n v)) cfg.targets
|
||||
// lib.mapAttrs' (n: v: lib.nameValuePair "${n}.timer" (systemd-lib.timerToUnit n v)) cfg.timers
|
||||
// lib.listToAttrs (map
|
||||
(v:
|
||||
let n = utils.escapeSystemdPath v.where;
|
||||
in lib.nameValuePair "${n}.mount" (systemd-lib.mountToUnit n v))
|
||||
cfg.mounts)
|
||||
// lib.listToAttrs (map
|
||||
(v:
|
||||
let n = utils.escapeSystemdPath v.where;
|
||||
in lib.nameValuePair "${n}.automount" (systemd-lib.automountToUnit n v))
|
||||
cfg.automounts);
|
||||
};
|
||||
|
||||
environment.etc =
|
||||
let
|
||||
allowCollisions = false;
|
||||
|
||||
enabledUnits = lib.filterAttrs (_: unit: unit.enable) cfg.units;
|
||||
in
|
||||
{
|
||||
"systemd/system".source = pkgs.runCommand "system-manager-units"
|
||||
{
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
}
|
||||
''
|
||||
mkdir -p $out
|
||||
|
||||
for i in ${toString (lib.mapAttrsToList (n: v: v.unit) enabledUnits)}; do
|
||||
fn=$(basename $i/*)
|
||||
if [ -e $out/$fn ]; then
|
||||
if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
|
||||
ln -sfn /dev/null $out/$fn
|
||||
else
|
||||
${if allowCollisions then ''
|
||||
mkdir -p $out/$fn.d
|
||||
ln -s $i/$fn $out/$fn.d/overrides.conf
|
||||
'' else ''
|
||||
echo "Found multiple derivations configuring $fn!"
|
||||
exit 1
|
||||
''}
|
||||
fi
|
||||
else
|
||||
ln -fs $i/$fn $out/
|
||||
fi
|
||||
done
|
||||
|
||||
${lib.concatStrings (
|
||||
lib.mapAttrsToList (name: unit:
|
||||
lib.concatMapStrings (name2: ''
|
||||
mkdir -p $out/'${name2}.wants'
|
||||
ln -sfn '../${name}' $out/'${name2}.wants'/
|
||||
'') (unit.wantedBy or [])
|
||||
) enabledUnits)}
|
||||
|
||||
${lib.concatStrings (
|
||||
lib.mapAttrsToList (name: unit:
|
||||
lib.concatMapStrings (name2: ''
|
||||
mkdir -p $out/'${name2}.requires'
|
||||
ln -sfn '../${name}' $out/'${name2}.requires'/
|
||||
'') (unit.requiredBy or [])
|
||||
) enabledUnits)}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue