chore: Split options and modules into multiple files
This commit is contained in:
parent
508da85384
commit
a2a58ceda9
12 changed files with 628 additions and 574 deletions
15
flake.nix
15
flake.nix
|
@ -35,8 +35,6 @@
|
|||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
colmenaOptions = import ./src/nix/hive/options.nix;
|
||||
colmenaModules = import ./src/nix/hive/modules.nix;
|
||||
in
|
||||
flake-utils.lib.eachSystem supportedSystems (
|
||||
system:
|
||||
|
@ -71,7 +69,7 @@
|
|||
inherit
|
||||
(pkgs.lib.evalModules {
|
||||
modules = [
|
||||
colmenaOptions.deploymentOptions
|
||||
./src/nix/hive/options/deployment.nix
|
||||
suppressModuleArgsDocs
|
||||
];
|
||||
specialArgs = {
|
||||
|
@ -87,7 +85,7 @@
|
|||
inherit
|
||||
(pkgs.lib.evalModules {
|
||||
modules = [
|
||||
colmenaOptions.metaOptions
|
||||
./src/nix/hive/options/meta.nix
|
||||
suppressModuleArgsDocs
|
||||
];
|
||||
})
|
||||
|
@ -166,15 +164,18 @@
|
|||
colmena = final.callPackage ./package.nix { };
|
||||
};
|
||||
nixosModules = {
|
||||
inherit (colmenaOptions) deploymentOptions metaOptions;
|
||||
inherit (colmenaModules) keyChownModule keyServiceModule assertionModule;
|
||||
deploymentOptions = import ./src/nix/hive/options/deployment.nix;
|
||||
metaOptions = import ./src/nix/hive/options/meta.nix;
|
||||
|
||||
keyChownModule = import ./src/nix/hive/modules/key-chown.nix;
|
||||
keyServiceModule = import ./src/nix/hive/modules/key-service.nix;
|
||||
assertionModule = import ./src/nix/hive/modules/assertions.nix;
|
||||
};
|
||||
|
||||
lib.makeHive =
|
||||
rawHive:
|
||||
import ./src/nix/hive/eval.nix {
|
||||
inherit rawHive colmenaOptions colmenaModules;
|
||||
inherit rawHive;
|
||||
hermetic = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
rawHive ? null, # Colmena Hive attrset
|
||||
rawFlake ? null, # Nix Flake attrset with `outputs.colmena`
|
||||
hermetic ? rawFlake != null, # Whether we are allowed to use <nixpkgs>
|
||||
colmenaOptions ? import ./options.nix,
|
||||
colmenaModules ? import ./modules.nix,
|
||||
}:
|
||||
with builtins;
|
||||
let
|
||||
|
||||
defaultHive = {
|
||||
|
@ -29,9 +26,9 @@ let
|
|||
|
||||
rawToHive =
|
||||
rawHive:
|
||||
if typeOf rawHive == "lambda" || rawHive ? __functor then
|
||||
if (builtins.isFunction rawHive) || rawHive ? __functor then
|
||||
rawHive { }
|
||||
else if typeOf rawHive == "set" then
|
||||
else if (builtins.isAttrs rawHive) then
|
||||
rawHive
|
||||
else
|
||||
throw "The config must evaluate to an attribute set.";
|
||||
|
@ -61,7 +58,7 @@ let
|
|||
userMeta =
|
||||
(lib.modules.evalModules {
|
||||
modules = [
|
||||
colmenaOptions.metaOptions
|
||||
./options/meta.nix
|
||||
uncheckedUserMeta
|
||||
];
|
||||
}).config;
|
||||
|
@ -69,7 +66,7 @@ let
|
|||
registry =
|
||||
(lib.modules.evalModules {
|
||||
modules = [
|
||||
colmenaOptions.registryOptions
|
||||
./options/registry.nix
|
||||
{ registry = uncheckedRegistries; }
|
||||
];
|
||||
}).config.registry;
|
||||
|
@ -99,9 +96,9 @@ let
|
|||
nodeConfig = hive.${node};
|
||||
in
|
||||
assert lib.assertMsg (
|
||||
!elem node reservedNames
|
||||
!builtins.elem node reservedNames
|
||||
) "\"${node}\" is a reserved name and cannot be used as the name of a node";
|
||||
if typeOf nodeConfig == "list" then nodeConfig else [ nodeConfig ];
|
||||
if (builtins.isList nodeConfig) then nodeConfig else [ nodeConfig ];
|
||||
|
||||
mkNixpkgs =
|
||||
configName: pkgConf:
|
||||
|
@ -123,15 +120,15 @@ let
|
|||
}
|
||||
'';
|
||||
in
|
||||
if typeOf pkgConf == "path" || (typeOf pkgConf == "set" && pkgConf ? outPath) then
|
||||
if (builtins.isPath pkgConf) || ((builtins.isAttrs pkgConf) && pkgConf ? outPath) then
|
||||
if hermetic then
|
||||
throw (uninitializedError "a path to Nixpkgs")
|
||||
# The referenced file might return an initialized Nixpkgs attribute set directly
|
||||
else
|
||||
mkNixpkgs configName (import pkgConf)
|
||||
else if typeOf pkgConf == "lambda" then
|
||||
else if (builtins.isFunction pkgConf) then
|
||||
if hermetic then throw (uninitializedError "a Nixpkgs lambda") else pkgConf { overlays = [ ]; }
|
||||
else if typeOf pkgConf == "set" then
|
||||
else if (builtins.isAttrs pkgConf) then
|
||||
if pkgConf ? outputs then throw (uninitializedError "an uninitialized Nixpkgs input") else pkgConf
|
||||
else
|
||||
throw ''
|
||||
|
@ -173,7 +170,7 @@ let
|
|||
] hive.${name}) "${name} does not have a deployment system type!"
|
||||
);
|
||||
assert (lib.assertMsg (
|
||||
builtins.typeOf hive.registry == "set"
|
||||
builtins.isAttrs hive.registry
|
||||
)) "The hive's registry is not a set, but of type '${builtins.typeOf hive.registry}'";
|
||||
assert (
|
||||
lib.assertMsg (lib.hasAttr hive.${name}.deployment.systemType hive.registry)
|
||||
|
@ -183,7 +180,7 @@ let
|
|||
# We cannot use `configs` because we need to access to the raw configuration fragment.
|
||||
inherit (hive.registry.${hive.${name}.deployment.systemType}) evalConfig;
|
||||
npkgs =
|
||||
if hasAttr name hive.meta.nodeNixpkgs then
|
||||
if builtins.hasAttr name hive.meta.nodeNixpkgs then
|
||||
mkNixpkgs "meta.nodeNixpkgs.${name}" hive.meta.nodeNixpkgs.${name}
|
||||
else
|
||||
nixpkgs;
|
||||
|
@ -205,15 +202,15 @@ let
|
|||
# Before 22.11, most config keys were untyped thus the merging
|
||||
# was broken. Let's warn the user if not all config attributes
|
||||
# set in meta.nixpkgs are overridden.
|
||||
metaKeys = attrNames npkgs.config;
|
||||
metaKeys = builtins.attrNames npkgs.config;
|
||||
nodeKeys = [
|
||||
"doCheckByDefault"
|
||||
"warnings"
|
||||
"allowAliases"
|
||||
] ++ (attrNames config.nixpkgs.config);
|
||||
remainingKeys = filter (k: !elem k nodeKeys) metaKeys;
|
||||
] ++ (builtins.attrNames config.nixpkgs.config);
|
||||
remainingKeys = builtins.filter (k: !builtins.elem k nodeKeys) metaKeys;
|
||||
in
|
||||
lib.optional (!hasTypedConfig && length remainingKeys != 0)
|
||||
lib.optional (!hasTypedConfig && builtins.length remainingKeys != 0)
|
||||
"The following Nixpkgs configuration keys set in meta.nixpkgs will be ignored: ${toString remainingKeys}";
|
||||
}
|
||||
//
|
||||
|
@ -229,8 +226,8 @@ let
|
|||
|
||||
modules = [
|
||||
nixpkgsModule
|
||||
colmenaModules.assertionModule
|
||||
colmenaOptions.deploymentOptions
|
||||
./modules/assertions.nix
|
||||
./options/deployment.nix
|
||||
(hive.registry.${hive.${name}.deployment.systemType}.defaults or hive.defaults)
|
||||
] ++ configs;
|
||||
specialArgs =
|
||||
|
@ -242,12 +239,12 @@ let
|
|||
// (hive.meta.nodeSpecialArgs.${name} or { });
|
||||
};
|
||||
|
||||
nodeNames = filter (name: !elem name reservedNames) (attrNames hive);
|
||||
nodeNames = builtins.filter (name: !builtins.elem name reservedNames) (builtins.attrNames hive);
|
||||
|
||||
# Used as the `nodes` argument in modules. We skip recursive type checking
|
||||
# for performance.
|
||||
uncheckedNodes = listToAttrs (
|
||||
map (
|
||||
uncheckedNodes = builtins.listToAttrs (
|
||||
builtins.map (
|
||||
name:
|
||||
let
|
||||
configs = [
|
||||
|
@ -280,23 +277,24 @@ rec {
|
|||
# Exported attributes
|
||||
__schema = "v0.20241006";
|
||||
|
||||
nodes = listToAttrs (
|
||||
map (name: {
|
||||
nodes = builtins.listToAttrs (
|
||||
builtins.map (name: {
|
||||
inherit name;
|
||||
value = evalNode name (configsFor name);
|
||||
}) nodeNames
|
||||
);
|
||||
toplevel = lib.mapAttrs (_: v: v.config.system.build.toplevel) nodes;
|
||||
deploymentConfig = lib.mapAttrs (_: v: v.config.deployment) nodes;
|
||||
deploymentConfigSelected = names: lib.filterAttrs (name: _: elem name names) deploymentConfig;
|
||||
evalSelected = names: lib.filterAttrs (name: _: elem name names) toplevel;
|
||||
deploymentConfigSelected =
|
||||
names: lib.filterAttrs (name: _: builtins.elem name names) deploymentConfig;
|
||||
evalSelected = names: lib.filterAttrs (name: _: builtins.elem name names) toplevel;
|
||||
evalSelectedDrvPaths = names: lib.mapAttrs (_: v: v.drvPath) (evalSelected names);
|
||||
metaConfig = lib.filterAttrs (n: v: elem n metaConfigKeys) hive.meta;
|
||||
metaConfig = lib.filterAttrs (n: v: builtins.elem n metaConfigKeys) hive.meta;
|
||||
# We cannot perform a `metaConfigKeys`-style simple check here
|
||||
# because registry is arbitrarily deep and may evaluate nixpkgs indirectly.
|
||||
registryConfig = lib.mapAttrs (
|
||||
systemTypeName: systemType:
|
||||
lib.filterAttrs (n: v: elem n serializableSystemTypeConfigKeys) systemType
|
||||
lib.filterAttrs (n: v: builtins.elem n serializableSystemTypeConfigKeys) systemType
|
||||
) hive.registry;
|
||||
introspect =
|
||||
f:
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
};
|
||||
|
||||
outputs =
|
||||
{ self, hive }:
|
||||
{ hive, ... }:
|
||||
{
|
||||
processFlake =
|
||||
let
|
||||
|
@ -20,8 +20,6 @@
|
|||
import ./eval.nix {
|
||||
inherit rawFlake;
|
||||
hermetic = true;
|
||||
colmenaOptions = import ./options.nix;
|
||||
colmenaModules = import ./modules.nix;
|
||||
};
|
||||
|
||||
# Uses an already-evaluated hive.
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
with builtins;
|
||||
{
|
||||
assertionModule =
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
assertions = lib.mapAttrsToList (
|
||||
key: opts:
|
||||
let
|
||||
nonNulls = l: filter (x: x != null) l;
|
||||
in
|
||||
{
|
||||
assertion =
|
||||
length (nonNulls [
|
||||
opts.text
|
||||
opts.keyCommand
|
||||
opts.keyFile
|
||||
]) == 1;
|
||||
message =
|
||||
let
|
||||
prefix = "${name}.deployment.keys.${key}";
|
||||
in
|
||||
"Exactly one of `${prefix}.text`, `${prefix}.keyCommand` and `${prefix}.keyFile` must be set.";
|
||||
}
|
||||
) config.deployment.keys;
|
||||
};
|
||||
|
||||
# Change the ownership of all keys uploaded pre-activation
|
||||
#
|
||||
# This is built as part of the system profile.
|
||||
# We must be careful not to access `text` / `keyCommand` / `keyFile` here
|
||||
keyChownModule =
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
preActivationKeys = lib.filterAttrs (
|
||||
name: key: key.uploadAt == "pre-activation"
|
||||
) config.deployment.keys;
|
||||
scriptDeps = if config.system.activationScripts ? groups then [ "groups" ] else [ "users" ];
|
||||
|
||||
commands = lib.mapAttrsToList (
|
||||
name: key:
|
||||
let
|
||||
keyPath = "${key.destDir}/${name}";
|
||||
in
|
||||
''
|
||||
if [ -f "${keyPath}" ]; then
|
||||
if ! chown ${key.user}:${key.group} "${keyPath}"; then
|
||||
# Error should be visible in stderr
|
||||
failed=1
|
||||
fi
|
||||
else
|
||||
>&2 echo "Key ${keyPath} does not exist. Skipping chown."
|
||||
fi
|
||||
''
|
||||
) preActivationKeys;
|
||||
|
||||
script = lib.stringAfter scriptDeps ''
|
||||
# This script is injected by Colmena to change the ownerships
|
||||
# of keys (`deployment.keys`) deployed before system activation.
|
||||
|
||||
>&2 echo "setting up key ownerships..."
|
||||
|
||||
# We set the ownership of as many keys as possible before failing
|
||||
failed=
|
||||
|
||||
${concatStringsSep "\n" commands}
|
||||
|
||||
if [ -n "$failed" ]; then
|
||||
>&2 echo "Failed to set the ownership of some keys."
|
||||
|
||||
# The activation script has a trap to handle failed
|
||||
# commands and print out various debug information.
|
||||
# Let's trigger that instead of `exit 1`.
|
||||
false
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
system.activationScripts.colmena-chown-keys = lib.mkIf (length commands != 0) script;
|
||||
};
|
||||
|
||||
# Create "${name}-key" services for NixOps compatibility
|
||||
#
|
||||
# This is built as part of the system profile.
|
||||
# We must be careful not to access `text` / `keyCommand` / `keyFile` here
|
||||
#
|
||||
# Sadly, path units don't automatically deactivate the bound units when
|
||||
# the key files are deleted, so we use inotifywait in the services' scripts.
|
||||
#
|
||||
# <https://github.com/systemd/systemd/issues/3642>
|
||||
keyServiceModule =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
systemd.paths = lib.mapAttrs' (name: val: {
|
||||
name = "${name}-key";
|
||||
value = {
|
||||
wantedBy = [ "paths.target" ];
|
||||
pathConfig = {
|
||||
PathExists = val.path;
|
||||
};
|
||||
};
|
||||
}) config.deployment.keys;
|
||||
|
||||
systemd.services = lib.mapAttrs' (name: val: {
|
||||
name = "${name}-key";
|
||||
value = {
|
||||
enable = true;
|
||||
serviceConfig = {
|
||||
TimeoutStartSec = "infinity";
|
||||
Restart = "always";
|
||||
RestartSec = "100ms";
|
||||
};
|
||||
path = [ pkgs.inotify-tools ];
|
||||
preStart = ''
|
||||
(while read f; do if [ "$f" = "${val.name}" ]; then break; fi; done \
|
||||
< <(inotifywait -qm --format '%f' -e create,move ${val.destDir}) ) &
|
||||
if [[ -e "${val.path}" ]]; then
|
||||
echo 'flapped down'
|
||||
kill %1
|
||||
exit 0
|
||||
fi
|
||||
wait %1
|
||||
'';
|
||||
script = ''
|
||||
inotifywait -qq -e delete_self "${val.path}" &
|
||||
if [[ ! -e "${val.path}" ]]; then
|
||||
echo 'flapped up'
|
||||
exit 0
|
||||
fi
|
||||
wait %1
|
||||
'';
|
||||
};
|
||||
}) config.deployment.keys;
|
||||
};
|
||||
}
|
28
src/nix/hive/modules/assertions.nix
Normal file
28
src/nix/hive/modules/assertions.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
name,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) filter mapAttrsToList;
|
||||
in
|
||||
|
||||
{
|
||||
assertions = mapAttrsToList (key: opts: {
|
||||
assertion =
|
||||
builtins.length (
|
||||
filter (x: x != null) [
|
||||
opts.text
|
||||
opts.keyCommand
|
||||
opts.keyFile
|
||||
]
|
||||
) == 1;
|
||||
message =
|
||||
let
|
||||
prefix = "${name}.deployment.keys.${key}";
|
||||
in
|
||||
"Exactly one of `${prefix}.text`, `${prefix}.keyCommand` and `${prefix}.keyFile` must be set.";
|
||||
}) config.deployment.keys;
|
||||
}
|
64
src/nix/hive/modules/key-chown.nix
Normal file
64
src/nix/hive/modules/key-chown.nix
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Change the ownership of all keys uploaded pre-activation
|
||||
#
|
||||
# This is built as part of the system profile.
|
||||
# We must be careful not to access `text` / `keyCommand` / `keyFile` here
|
||||
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
filterAttrs
|
||||
mapAttrsToList
|
||||
mkIf
|
||||
stringAfter
|
||||
;
|
||||
|
||||
preActivationKeys = filterAttrs (
|
||||
_: { uploadAt, ... }: uploadAt == "pre-activation"
|
||||
) config.deployment.keys;
|
||||
|
||||
scriptDeps = if config.system.activationScripts ? groups then [ "groups" ] else [ "users" ];
|
||||
|
||||
commands = mapAttrsToList (
|
||||
name: key:
|
||||
let
|
||||
keyPath = "${key.destDir}/${name}";
|
||||
in
|
||||
''
|
||||
if [ -f "${keyPath}" ]; then
|
||||
if ! chown ${key.user}:${key.group} "${keyPath}"; then
|
||||
# Error should be visible in stderr
|
||||
failed=1
|
||||
fi
|
||||
else
|
||||
>&2 echo "Key ${keyPath} does not exist. Skipping chown."
|
||||
fi
|
||||
''
|
||||
) preActivationKeys;
|
||||
|
||||
script = stringAfter scriptDeps ''
|
||||
# This script is injected by Colmena to change the ownerships
|
||||
# of keys (`deployment.keys`) deployed before system activation.
|
||||
|
||||
>&2 echo "setting up key ownerships..."
|
||||
|
||||
# We set the ownership of as many keys as possible before failing
|
||||
failed=
|
||||
|
||||
${concatStringsSep "\n" commands}
|
||||
|
||||
if [ -n "$failed" ]; then
|
||||
>&2 echo "Failed to set the ownership of some keys."
|
||||
|
||||
# The activation script has a trap to handle failed
|
||||
# commands and print out various debug information.
|
||||
# Let's trigger that instead of `exit 1`.
|
||||
false
|
||||
fi
|
||||
'';
|
||||
in
|
||||
|
||||
{
|
||||
system.activationScripts.colmena-chown-keys = mkIf (commands != [ ]) script;
|
||||
}
|
61
src/nix/hive/modules/key-service.nix
Normal file
61
src/nix/hive/modules/key-service.nix
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Create "${name}-key" services for NixOps compatibility
|
||||
#
|
||||
# This is built as part of the system profile.
|
||||
# We must be careful not to access `text` / `keyCommand` / `keyFile` here
|
||||
#
|
||||
# Sadly, path units don't automatically deactivate the bound units when
|
||||
# the key files are deleted, so we use inotifywait in the services' scripts.
|
||||
#
|
||||
# <https://github.com/systemd/systemd/issues/3642>
|
||||
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mapAttrs' nameValuePair;
|
||||
in
|
||||
|
||||
{
|
||||
systemd.paths = mapAttrs' (
|
||||
name: value:
|
||||
nameValuePair "${name}-key" {
|
||||
wantedBy = [ "paths.target" ];
|
||||
pathConfig.PathExists = value.path;
|
||||
}
|
||||
) config.deployment.keys;
|
||||
|
||||
systemd.services = mapAttrs' (
|
||||
name: value:
|
||||
nameValuePair "${name}-key" {
|
||||
enable = true;
|
||||
serviceConfig = {
|
||||
TimeoutStartSec = "infinity";
|
||||
Restart = "always";
|
||||
RestartSec = "100ms";
|
||||
};
|
||||
path = [ pkgs.inotify-tools ];
|
||||
preStart = ''
|
||||
(while read f; do if [ "$f" = "${value.name}" ]; then break; fi; done \
|
||||
< <(inotifywait -qm --format '%f' -e create,move ${value.destDir}) ) &
|
||||
if [[ -e "${value.path}" ]]; then
|
||||
echo 'flapped down'
|
||||
kill %1
|
||||
exit 0
|
||||
fi
|
||||
wait %1
|
||||
'';
|
||||
script = ''
|
||||
inotifywait -qq -e delete_self "${value.path}" &
|
||||
if [[ ! -e "${value.path}" ]]; then
|
||||
echo 'flapped up'
|
||||
exit 0
|
||||
fi
|
||||
wait %1
|
||||
'';
|
||||
}
|
||||
) config.deployment.keys;
|
||||
}
|
|
@ -1,396 +0,0 @@
|
|||
with builtins;
|
||||
rec {
|
||||
keyType =
|
||||
{
|
||||
lib,
|
||||
name,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) types;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
description = ''
|
||||
File name of the key.
|
||||
'';
|
||||
default = name;
|
||||
type = types.str;
|
||||
};
|
||||
text = lib.mkOption {
|
||||
description = ''
|
||||
Content of the key.
|
||||
One of `text`, `keyCommand` and `keyFile` must be set.
|
||||
'';
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
keyFile = lib.mkOption {
|
||||
description = ''
|
||||
Path of the local file to read the key from.
|
||||
One of `text`, `keyCommand` and `keyFile` must be set.
|
||||
'';
|
||||
default = null;
|
||||
apply = value: if value == null then null else toString value;
|
||||
type = types.nullOr types.path;
|
||||
};
|
||||
keyCommand = lib.mkOption {
|
||||
description = ''
|
||||
Command to run to generate the key.
|
||||
One of `text`, `keyCommand` and `keyFile` must be set.
|
||||
'';
|
||||
default = null;
|
||||
type =
|
||||
let
|
||||
nonEmptyList = types.addCheck (types.listOf types.str) (l: length l > 0);
|
||||
in
|
||||
types.nullOr nonEmptyList;
|
||||
};
|
||||
destDir = lib.mkOption {
|
||||
description = ''
|
||||
Destination directory on the host.
|
||||
'';
|
||||
default = "/run/keys";
|
||||
type = types.path;
|
||||
};
|
||||
path = lib.mkOption {
|
||||
description = ''
|
||||
Full path to the destination.
|
||||
'';
|
||||
default = "${config.destDir}/${config.name}";
|
||||
type = types.path;
|
||||
internal = true;
|
||||
};
|
||||
user = lib.mkOption {
|
||||
description = ''
|
||||
The group that will own the file.
|
||||
'';
|
||||
default = "root";
|
||||
type = types.str;
|
||||
};
|
||||
group = lib.mkOption {
|
||||
description = ''
|
||||
The group that will own the file.
|
||||
'';
|
||||
default = "root";
|
||||
type = types.str;
|
||||
};
|
||||
permissions = lib.mkOption {
|
||||
description = ''
|
||||
Permissions to set for the file.
|
||||
'';
|
||||
default = "0600";
|
||||
type = types.str;
|
||||
};
|
||||
uploadAt = lib.mkOption {
|
||||
description = ''
|
||||
When to upload the keys.
|
||||
|
||||
- pre-activation (default): Upload the keys before activating the new system profile.
|
||||
- post-activation: Upload the keys after successfully activating the new system profile.
|
||||
|
||||
For `colmena upload-keys`, all keys are uploaded at the same time regardless of the configuration here.
|
||||
'';
|
||||
default = "pre-activation";
|
||||
type = types.enum [
|
||||
"pre-activation"
|
||||
"post-activation"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Colmena-specific options
|
||||
#
|
||||
# Largely compatible with NixOps/Morph.
|
||||
deploymentOptions =
|
||||
{ name, lib, ... }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
deployment = {
|
||||
systemType = lib.mkOption {
|
||||
description = mdDoc ''
|
||||
System type used for this node, e.g. NixOS.
|
||||
'';
|
||||
default = "nixos";
|
||||
# TODO: enum among all registered systems?
|
||||
type = types.str;
|
||||
};
|
||||
targetHost = lib.mkOption {
|
||||
description = ''
|
||||
The target SSH node for deployment.
|
||||
|
||||
By default, the node's attribute name will be used.
|
||||
If set to null, only local deployment will be supported.
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = name;
|
||||
};
|
||||
targetPort = lib.mkOption {
|
||||
description = ''
|
||||
The target SSH port for deployment.
|
||||
|
||||
By default, the port is the standard port (22) or taken
|
||||
from your ssh_config.
|
||||
'';
|
||||
type = types.nullOr types.ints.unsigned;
|
||||
default = null;
|
||||
};
|
||||
targetUser = lib.mkOption {
|
||||
description = ''
|
||||
The user to use to log into the remote node. If set to null, the
|
||||
target user will not be specified in SSH invocations.
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = "root";
|
||||
};
|
||||
allowLocalDeployment = lib.mkOption {
|
||||
description = ''
|
||||
Allow the configuration to be applied locally on the host running
|
||||
Colmena.
|
||||
|
||||
For local deployment to work, all of the following must be true:
|
||||
- The node must be running NixOS.
|
||||
- The node must have deployment.allowLocalDeployment set to true.
|
||||
- The node's networking.hostName must match the hostname.
|
||||
|
||||
To apply the configurations locally, run `colmena apply-local`.
|
||||
You can also set deployment.targetHost to null if the nost is not
|
||||
accessible over SSH (only local deployment will be possible).
|
||||
'';
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
buildOnTarget = lib.mkOption {
|
||||
description = ''
|
||||
Whether to build the system profiles on the target node itself.
|
||||
|
||||
When enabled, Colmena will copy the derivation to the target
|
||||
node and initiate the build there. This avoids copying back the
|
||||
build results involved with the native distributed build
|
||||
feature. Furthermore, the `build` goal will be equivalent to
|
||||
the `push` goal. Since builds happen on the target node, the
|
||||
results are automatically "pushed" and won't exist in the local
|
||||
Nix store.
|
||||
|
||||
You can temporarily override per-node settings by passing
|
||||
`--build-on-target` (enable for all nodes) or
|
||||
`--no-build-on-target` (disable for all nodes) on the command
|
||||
line.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
tags = lib.mkOption {
|
||||
description = ''
|
||||
A list of tags for the node.
|
||||
|
||||
Can be used to select a group of nodes for deployment.
|
||||
'';
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
keys = lib.mkOption {
|
||||
description = ''
|
||||
A set of secrets to be deployed to the node.
|
||||
|
||||
Secrets are transferred to the node out-of-band and
|
||||
never ends up in the Nix store.
|
||||
'';
|
||||
type = types.attrsOf (types.submodule keyType);
|
||||
default = { };
|
||||
};
|
||||
replaceUnknownProfiles = lib.mkOption {
|
||||
description = ''
|
||||
Allow a configuration to be applied to a host running a profile we
|
||||
have no knowledge of. By setting this option to false, you reduce
|
||||
the likelyhood of rolling back changes made via another Colmena user.
|
||||
|
||||
Unknown profiles are usually the result of either:
|
||||
- The node had a profile applied, locally or by another Colmena.
|
||||
- The host running Colmena garbage-collecting the profile.
|
||||
|
||||
To force profile replacement on all targeted nodes during apply,
|
||||
use the flag `--force-replace-unknown-profiles`.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
privilegeEscalationCommand = lib.mkOption {
|
||||
description = ''
|
||||
Command to use to elevate privileges when activating the new profiles on SSH hosts.
|
||||
|
||||
This is used on SSH hosts when `deployment.targetUser` is not `root`.
|
||||
The user must be allowed to use the command non-interactively.
|
||||
'';
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"sudo"
|
||||
"-H"
|
||||
"--"
|
||||
];
|
||||
};
|
||||
sshOptions = lib.mkOption {
|
||||
description = ''
|
||||
Extra SSH options to pass to the SSH command.
|
||||
'';
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
# Options for a registered system type
|
||||
systemTypeOptions =
|
||||
{ name, lib, ... }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
mdDoc = lib.mdDoc or lib.id;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
evalConfig = lib.mkOption {
|
||||
description = mdDoc ''
|
||||
Evaluation function which share the same interface as `nixos/lib/eval-config.nix`
|
||||
which can be tailored to your own usecases or to target another type of system,
|
||||
e.g. nix-darwin.
|
||||
'';
|
||||
type = types.functionTo types.unspecified;
|
||||
};
|
||||
supportsDeployment = lib.mkOption {
|
||||
description = mdDoc ''
|
||||
Whether this system type supports deployment or not.
|
||||
|
||||
If it supports deployment, it needs to have appropriate activation code,
|
||||
refer to how to write custom activators.
|
||||
'';
|
||||
default = name == "nixos";
|
||||
defaultText = "If a NixOS system, then true, otherwise false by default";
|
||||
};
|
||||
defaults = lib.mkOption {
|
||||
description = mdDoc ''
|
||||
Default configuration for that system type.
|
||||
'';
|
||||
type = types.functionTo types.unspecified;
|
||||
default = _: { };
|
||||
};
|
||||
};
|
||||
};
|
||||
registryOptions =
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
mdDoc = lib.mdDoc or lib.id;
|
||||
in
|
||||
{
|
||||
options.registry = lib.mkOption {
|
||||
description = mdDoc ''
|
||||
A registry of all system types.
|
||||
'';
|
||||
type = types.attrsOf (types.submodule systemTypeOptions);
|
||||
};
|
||||
};
|
||||
# Hive-wide options
|
||||
metaOptions =
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
description = ''
|
||||
The name of the configuration.
|
||||
'';
|
||||
type = types.str;
|
||||
default = "hive";
|
||||
};
|
||||
description = lib.mkOption {
|
||||
description = ''
|
||||
A short description for the configuration.
|
||||
'';
|
||||
type = types.str;
|
||||
default = "A Colmena Hive";
|
||||
};
|
||||
nixpkgs = lib.mkOption {
|
||||
description = ''
|
||||
The pinned Nixpkgs package set. Accepts one of the following:
|
||||
|
||||
- A path to a Nixpkgs checkout
|
||||
- The Nixpkgs lambda (e.g., import <nixpkgs>)
|
||||
- An initialized Nixpkgs attribute set
|
||||
|
||||
This option must be specified when using Flakes.
|
||||
'';
|
||||
type = types.unspecified;
|
||||
default = null;
|
||||
};
|
||||
nodeNixpkgs = lib.mkOption {
|
||||
description = ''
|
||||
Node-specific Nixpkgs pins.
|
||||
'';
|
||||
type = types.attrsOf types.unspecified;
|
||||
default = { };
|
||||
};
|
||||
nodeSpecialArgs = lib.mkOption {
|
||||
description = ''
|
||||
Node-specific special args.
|
||||
'';
|
||||
type = types.attrsOf types.unspecified;
|
||||
default = { };
|
||||
};
|
||||
machinesFile = lib.mkOption {
|
||||
description = ''
|
||||
Use the machines listed in this file when building this hive configuration.
|
||||
|
||||
If your Colmena host has nix configured to allow for remote builds
|
||||
(for nix-daemon, your user being included in trusted-users)
|
||||
you can set a machines file that will be passed to the underlying
|
||||
nix-store command during derivation realization as a builders option.
|
||||
For example, if you support multiple orginizations each with their own
|
||||
build machine(s) you can ensure that builds only take place on your
|
||||
local machine and/or the machines specified in this file.
|
||||
|
||||
See https://nixos.org/manual/nix/stable/advanced-topics/distributed-builds
|
||||
for the machine specification format.
|
||||
|
||||
This option is ignored when builds are initiated on the remote nodes
|
||||
themselves via `deployment.buildOnTarget` or `--build-on-target`. To
|
||||
still use the Nix distributed build functionality, configure the
|
||||
builders on the target nodes with `nix.buildMachines`.
|
||||
'';
|
||||
default = null;
|
||||
apply = value: if value == null then null else toString value;
|
||||
type = types.nullOr types.path;
|
||||
};
|
||||
specialArgs = lib.mkOption {
|
||||
description = ''
|
||||
A set of special arguments to be passed to NixOS modules.
|
||||
|
||||
This will be merged into the `specialArgs` used to evaluate
|
||||
the NixOS configurations.
|
||||
'';
|
||||
default = { };
|
||||
type = types.attrsOf types.unspecified;
|
||||
};
|
||||
allowApplyAll = lib.mkOption {
|
||||
description = ''
|
||||
Whether to allow deployments without a node filter set.
|
||||
|
||||
If set to false, a node filter must be specified with `--on` when
|
||||
deploying.
|
||||
|
||||
It helps prevent accidental deployments to the entire cluster
|
||||
when tags are used (e.g., `@production` and `@staging`).
|
||||
'';
|
||||
default = true;
|
||||
type = types.bool;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
151
src/nix/hive/options/deployment.nix
Normal file
151
src/nix/hive/options/deployment.nix
Normal file
|
@ -0,0 +1,151 @@
|
|||
{ lib, name, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption;
|
||||
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
bool
|
||||
ints
|
||||
listOf
|
||||
nullOr
|
||||
str
|
||||
submodule
|
||||
;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
deployment = {
|
||||
systemType = mkOption {
|
||||
description = ''
|
||||
System type used for this node, e.g. NixOS.
|
||||
'';
|
||||
default = "nixos";
|
||||
# TODO: enum among all registered systems?
|
||||
type = str;
|
||||
};
|
||||
targetHost = mkOption {
|
||||
description = ''
|
||||
The target SSH node for deployment.
|
||||
|
||||
By default, the node's attribute name will be used.
|
||||
If set to null, only local deployment will be supported.
|
||||
'';
|
||||
type = nullOr str;
|
||||
default = name;
|
||||
};
|
||||
targetPort = mkOption {
|
||||
description = ''
|
||||
The target SSH port for deployment.
|
||||
|
||||
By default, the port is the standard port (22) or taken
|
||||
from your ssh_config.
|
||||
'';
|
||||
type = nullOr ints.unsigned;
|
||||
default = null;
|
||||
};
|
||||
targetUser = mkOption {
|
||||
description = ''
|
||||
The user to use to log into the remote node. If set to null, the
|
||||
target user will not be specified in SSH invocations.
|
||||
'';
|
||||
type = nullOr str;
|
||||
default = "root";
|
||||
};
|
||||
allowLocalDeployment = mkOption {
|
||||
description = ''
|
||||
Allow the configuration to be applied locally on the host running
|
||||
Colmena.
|
||||
|
||||
For local deployment to work, all of the following must be true:
|
||||
- The node must be running NixOS.
|
||||
- The node must have deployment.allowLocalDeployment set to true.
|
||||
- The node's networking.hostName must match the hostname.
|
||||
|
||||
To apply the configurations locally, run `colmena apply-local`.
|
||||
You can also set deployment.targetHost to null if the nost is not
|
||||
accessible over SSH (only local deployment will be possible).
|
||||
'';
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
buildOnTarget = mkOption {
|
||||
description = ''
|
||||
Whether to build the system profiles on the target node itself.
|
||||
|
||||
When enabled, Colmena will copy the derivation to the target
|
||||
node and initiate the build there. This avoids copying back the
|
||||
build results involved with the native distributed build
|
||||
feature. Furthermore, the `build` goal will be equivalent to
|
||||
the `push` goal. Since builds happen on the target node, the
|
||||
results are automatically "pushed" and won't exist in the local
|
||||
Nix store.
|
||||
|
||||
You can temporarily override per-node settings by passing
|
||||
`--build-on-target` (enable for all nodes) or
|
||||
`--no-build-on-target` (disable for all nodes) on the command
|
||||
line.
|
||||
'';
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
tags = mkOption {
|
||||
description = ''
|
||||
A list of tags for the node.
|
||||
|
||||
Can be used to select a group of nodes for deployment.
|
||||
'';
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
keys = mkOption {
|
||||
description = ''
|
||||
A set of secrets to be deployed to the node.
|
||||
|
||||
Secrets are transferred to the node out-of-band and
|
||||
never ends up in the Nix store.
|
||||
'';
|
||||
type = attrsOf (submodule (import ./key.nix));
|
||||
default = { };
|
||||
};
|
||||
replaceUnknownProfiles = mkOption {
|
||||
description = ''
|
||||
Allow a configuration to be applied to a host running a profile we
|
||||
have no knowledge of. By setting this option to false, you reduce
|
||||
the likelyhood of rolling back changes made via another Colmena user.
|
||||
|
||||
Unknown profiles are usually the result of either:
|
||||
- The node had a profile applied, locally or by another Colmena.
|
||||
- The host running Colmena garbage-collecting the profile.
|
||||
|
||||
To force profile replacement on all targeted nodes during apply,
|
||||
use the flag `--force-replace-unknown-profiles`.
|
||||
'';
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
privilegeEscalationCommand = mkOption {
|
||||
description = ''
|
||||
Command to use to elevate privileges when activating the new profiles on SSH hosts.
|
||||
|
||||
This is used on SSH hosts when `deployment.targetUser` is not `root`.
|
||||
The user must be allowed to use the command non-interactively.
|
||||
'';
|
||||
type = listOf str;
|
||||
default = [
|
||||
"sudo"
|
||||
"-H"
|
||||
"--"
|
||||
];
|
||||
};
|
||||
sshOptions = mkOption {
|
||||
description = ''
|
||||
Extra SSH options to pass to the SSH command.
|
||||
'';
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
120
src/nix/hive/options/key.nix
Normal file
120
src/nix/hive/options/key.nix
Normal file
|
@ -0,0 +1,120 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
name,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption;
|
||||
|
||||
inherit (lib.types)
|
||||
addCheck
|
||||
enum
|
||||
listOf
|
||||
nullOr
|
||||
path
|
||||
str
|
||||
;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = ''
|
||||
File name of the key.
|
||||
'';
|
||||
default = name;
|
||||
type = str;
|
||||
};
|
||||
|
||||
text = mkOption {
|
||||
description = ''
|
||||
Content of the key.
|
||||
One of `text`, `keyCommand` and `keyFile` must be set.
|
||||
'';
|
||||
default = null;
|
||||
type = nullOr str;
|
||||
};
|
||||
|
||||
keyFile = mkOption {
|
||||
description = ''
|
||||
Path of the local file to read the key from.
|
||||
One of `text`, `keyCommand` and `keyFile` must be set.
|
||||
'';
|
||||
default = null;
|
||||
apply = value: if value == null then null else builtins.toString value;
|
||||
type = nullOr path;
|
||||
};
|
||||
|
||||
keyCommand = mkOption {
|
||||
description = ''
|
||||
Command to run to generate the key.
|
||||
One of `text`, `keyCommand` and `keyFile` must be set.
|
||||
'';
|
||||
default = null;
|
||||
type =
|
||||
let
|
||||
nonEmptyList = addCheck (listOf str) (l: builtins.length l > 0);
|
||||
in
|
||||
nullOr nonEmptyList;
|
||||
};
|
||||
|
||||
destDir = mkOption {
|
||||
description = ''
|
||||
Destination directory on the host.
|
||||
'';
|
||||
default = "/run/keys";
|
||||
type = path;
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
description = ''
|
||||
Full path to the destination.
|
||||
'';
|
||||
default = "${config.destDir}/${config.name}";
|
||||
type = path;
|
||||
internal = true;
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
description = ''
|
||||
The group that will own the file.
|
||||
'';
|
||||
default = "root";
|
||||
type = str;
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
description = ''
|
||||
The group that will own the file.
|
||||
'';
|
||||
default = "root";
|
||||
type = str;
|
||||
};
|
||||
|
||||
permissions = mkOption {
|
||||
description = ''
|
||||
Permissions to set for the file.
|
||||
'';
|
||||
default = "0600";
|
||||
type = str;
|
||||
};
|
||||
|
||||
uploadAt = mkOption {
|
||||
description = ''
|
||||
When to upload the keys.
|
||||
|
||||
- pre-activation (default): Upload the keys before activating the new system profile.
|
||||
- post-activation: Upload the keys after successfully activating the new system profile.
|
||||
|
||||
For `colmena upload-keys`, all keys are uploaded at the same time regardless of the configuration here.
|
||||
'';
|
||||
default = "pre-activation";
|
||||
type = enum [
|
||||
"pre-activation"
|
||||
"post-activation"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
114
src/nix/hive/options/meta.nix
Normal file
114
src/nix/hive/options/meta.nix
Normal file
|
@ -0,0 +1,114 @@
|
|||
{ lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption;
|
||||
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
bool
|
||||
nullOr
|
||||
path
|
||||
str
|
||||
unspecified
|
||||
;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = ''
|
||||
The name of the configuration.
|
||||
'';
|
||||
type = str;
|
||||
default = "hive";
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
description = ''
|
||||
A short description for the configuration.
|
||||
'';
|
||||
type = str;
|
||||
default = "A Colmena Hive";
|
||||
};
|
||||
|
||||
nixpkgs = mkOption {
|
||||
description = ''
|
||||
The pinned Nixpkgs package set. Accepts one of the following:
|
||||
|
||||
- A path to a Nixpkgs checkout
|
||||
- The Nixpkgs lambda (e.g., import <nixpkgs>)
|
||||
- An initialized Nixpkgs attribute set
|
||||
|
||||
This option must be specified when using Flakes.
|
||||
'';
|
||||
type = unspecified;
|
||||
default = null;
|
||||
};
|
||||
|
||||
nodeNixpkgs = mkOption {
|
||||
description = ''
|
||||
Node-specific Nixpkgs pins.
|
||||
'';
|
||||
type = attrsOf unspecified;
|
||||
default = { };
|
||||
};
|
||||
|
||||
nodeSpecialArgs = mkOption {
|
||||
description = ''
|
||||
Node-specific special args.
|
||||
'';
|
||||
type = attrsOf unspecified;
|
||||
default = { };
|
||||
};
|
||||
|
||||
machinesFile = mkOption {
|
||||
description = ''
|
||||
Use the machines listed in this file when building this hive configuration.
|
||||
|
||||
If your Colmena host has nix configured to allow for remote builds
|
||||
(for nix-daemon, your user being included in trusted-users)
|
||||
you can set a machines file that will be passed to the underlying
|
||||
nix-store command during derivation realization as a builders option.
|
||||
For example, if you support multiple orginizations each with their own
|
||||
build machine(s) you can ensure that builds only take place on your
|
||||
local machine and/or the machines specified in this file.
|
||||
|
||||
See https://nixos.org/manual/nix/stable/advanced-topics/distributed-builds
|
||||
for the machine specification format.
|
||||
|
||||
This option is ignored when builds are initiated on the remote nodes
|
||||
themselves via `deployment.buildOnTarget` or `--build-on-target`. To
|
||||
still use the Nix distributed build functionality, configure the
|
||||
builders on the target nodes with `nix.buildMachines`.
|
||||
'';
|
||||
default = null;
|
||||
apply = value: if value == null then null else builtins.toString value;
|
||||
type = nullOr path;
|
||||
};
|
||||
|
||||
specialArgs = mkOption {
|
||||
description = ''
|
||||
A set of special arguments to be passed to NixOS modules.
|
||||
|
||||
This will be merged into the `specialArgs` used to evaluate
|
||||
the NixOS configurations.
|
||||
'';
|
||||
default = { };
|
||||
type = attrsOf unspecified;
|
||||
};
|
||||
|
||||
allowApplyAll = mkOption {
|
||||
description = ''
|
||||
Whether to allow deployments without a node filter set.
|
||||
|
||||
If set to false, a node filter must be specified with `--on` when
|
||||
deploying.
|
||||
|
||||
It helps prevent accidental deployments to the entire cluster
|
||||
when tags are used (e.g., `@production` and `@staging`).
|
||||
'';
|
||||
default = true;
|
||||
type = bool;
|
||||
};
|
||||
};
|
||||
}
|
54
src/nix/hive/options/registry.nix
Normal file
54
src/nix/hive/options/registry.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
{ lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption;
|
||||
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
functionTo
|
||||
submodule
|
||||
unspecified
|
||||
;
|
||||
in
|
||||
|
||||
{
|
||||
options.registry = mkOption {
|
||||
description = ''
|
||||
A registry of all system types.
|
||||
'';
|
||||
type = attrsOf (
|
||||
submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
evalConfig = mkOption {
|
||||
description = ''
|
||||
Evaluation function which share the same interface as `nixos/lib/eval-config.nix`
|
||||
which can be tailored to your own usecases or to target another type of system,
|
||||
e.g. nix-darwin.
|
||||
'';
|
||||
type = functionTo unspecified;
|
||||
};
|
||||
supportsDeployment = mkOption {
|
||||
description = ''
|
||||
Whether this system type supports deployment or not.
|
||||
|
||||
If it supports deployment, it needs to have appropriate activation code,
|
||||
refer to how to write custom activators.
|
||||
'';
|
||||
default = name == "nixos";
|
||||
defaultText = "If a NixOS system, then true, otherwise false by default";
|
||||
};
|
||||
defaults = mkOption {
|
||||
description = ''
|
||||
Default configuration for that system type.
|
||||
'';
|
||||
type = functionTo unspecified;
|
||||
default = _: { };
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
Loading…
Add table
Reference in a new issue