adapt generator modules from clan-core modules
see https://git.clan.lol/clan/clan-core/src/branch/main/clanServices
This commit is contained in:
parent
39f4680381
commit
09bb7e1ed9
15 changed files with 511 additions and 0 deletions
|
@ -16,6 +16,7 @@
|
||||||
in {
|
in {
|
||||||
nixosModules.default = { imports = [ ./options.nix ]; };
|
nixosModules.default = { imports = [ ./options.nix ]; };
|
||||||
nixosModules.backend-on-machine = { imports = [ ./backends/on-machine.nix ]; };
|
nixosModules.backend-on-machine = { imports = [ ./backends/on-machine.nix ]; };
|
||||||
|
nixosModules.generators = { imports = [ ./generators ]; };
|
||||||
# TODO fix tests
|
# TODO fix tests
|
||||||
checks = forAllSystems (system: let
|
checks = forAllSystems (system: let
|
||||||
tests = {
|
tests = {
|
||||||
|
|
11
generators/default.nix
Normal file
11
generators/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./disk-id
|
||||||
|
./garage
|
||||||
|
./machine-id
|
||||||
|
./root-password
|
||||||
|
./sshd
|
||||||
|
./state-version
|
||||||
|
./user-password
|
||||||
|
];
|
||||||
|
}
|
30
generators/disk-id/default.nix
Normal file
30
generators/disk-id/default.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.vars.disk-id;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.vars.disk-id.enable = lib.mkEnableOption "Generates a uuid for use in disk device naming";
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
vars.generators.disk-id = {
|
||||||
|
files.diskId.secret = false;
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.bash
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
uuid=$(bash ${./uuid4.sh})
|
||||||
|
|
||||||
|
# Remove the hyphens from the UUID
|
||||||
|
uuid_no_hyphens=$(echo -n "$uuid" | tr -d '-')
|
||||||
|
|
||||||
|
echo -n "$uuid_no_hyphens" > "$out/diskId"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
disko.devices.disk."main".name = "main-" + config.vars.generators.disk-id.files.diskId.value;
|
||||||
|
};
|
||||||
|
}
|
20
generators/disk-id/uuid4.sh
Normal file
20
generators/disk-id/uuid4.sh
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Read 16 bytes from /dev/urandom
|
||||||
|
uuid=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null | od -An -tx1 | tr -d ' \n')
|
||||||
|
|
||||||
|
# Break the UUID into pieces and apply the required modifications
|
||||||
|
byte6=${uuid:12:2}
|
||||||
|
byte8=${uuid:16:2}
|
||||||
|
|
||||||
|
# Construct the correct version and variant
|
||||||
|
hex_byte6=$(printf "%x" $((0x$byte6 & 0x0F | 0x40)))
|
||||||
|
hex_byte8=$(printf "%x" $((0x$byte8 & 0x3F | 0x80)))
|
||||||
|
|
||||||
|
# Rebuild the UUID with the correct fields
|
||||||
|
uuid_v4="${uuid:0:12}${hex_byte6}${uuid:14:2}${hex_byte8}${uuid:18:14}"
|
||||||
|
|
||||||
|
# Format the UUID correctly 8-4-4-4-12
|
||||||
|
uuid_formatted="${uuid_v4:0:8}-${uuid_v4:8:4}-${uuid_v4:12:4}-${uuid_v4:16:4}-${uuid_v4:20:12}"
|
||||||
|
|
||||||
|
echo -n "$uuid_formatted"
|
59
generators/garage/default.nix
Normal file
59
generators/garage/default.nix
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.vars.garage;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.vars.garage.enable = lib.mkEnableOption ''
|
||||||
|
S3-compatible object store for small self-hosted geo-distributed deployments.
|
||||||
|
|
||||||
|
This module generates garage-specific keys automatically.
|
||||||
|
|
||||||
|
Options: [NixosModuleOptions](https://search.nixos.org/options?channel=unstable&size=50&sort=relevance&type=packages&query=garage)
|
||||||
|
Documentation: https://garagehq.deuxfleurs.fr/
|
||||||
|
'';
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.services.garage.serviceConfig = {
|
||||||
|
LoadCredential = [
|
||||||
|
"rpc_secret_path:${config.vars.generators.garage-shared.files.rpc_secret.path}"
|
||||||
|
"admin_token_path:${config.vars.generators.garage.files.admin_token.path}"
|
||||||
|
"metrics_token_path:${config.vars.generators.garage.files.metrics_token.path}"
|
||||||
|
];
|
||||||
|
Environment = [
|
||||||
|
"GARAGE_ALLOW_WORLD_READABLE_SECRETS=true"
|
||||||
|
"GARAGE_RPC_SECRET_FILE=%d/rpc_secret_path"
|
||||||
|
"GARAGE_ADMIN_TOKEN_FILE=%d/admin_token_path"
|
||||||
|
"GARAGE_METRICS_TOKEN_FILE=%d/metrics_token_path"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
vars.generators.garage = {
|
||||||
|
files.admin_token = { };
|
||||||
|
files.metrics_token = { };
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.openssl
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
openssl rand -base64 -out "$out"/admin_token 32
|
||||||
|
openssl rand -base64 -out "$out"/metrics_token 32
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
vars.generators.garage-shared = {
|
||||||
|
share = true;
|
||||||
|
files.rpc_secret = { };
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.openssl
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
openssl rand -hex -out "$out"/rpc_secret 32
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
46
generators/machine-id/default.nix
Normal file
46
generators/machine-id/default.nix
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
var = config.vars.generators.machine-id.files.machineId or { };
|
||||||
|
cfg = config.vars.machine-id;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.vars.machine-id.enable = lib.mkEnableOption "Sets the /etc/machine-id and exposes it as a nix option";
|
||||||
|
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
|
(lib.mkIf ((var.value or null) != null) {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = lib.stringLength var.value == 32;
|
||||||
|
message = "machineId must be exactly 32 characters long.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
boot.kernelParams = [
|
||||||
|
''systemd.machine_id=${var.value}''
|
||||||
|
];
|
||||||
|
environment.etc."machine-id" = {
|
||||||
|
text = var.value;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
{
|
||||||
|
vars.generators.machine-id = {
|
||||||
|
files.machineId.secret = false;
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.bash
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
uuid=$(bash ${./uuid4.sh})
|
||||||
|
|
||||||
|
# Remove the hyphens from the UUID
|
||||||
|
uuid_no_hyphens=$(echo -n "$uuid" | tr -d '-')
|
||||||
|
|
||||||
|
echo -n "$uuid_no_hyphens" > "$out/machineId"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
20
generators/machine-id/uuid4.sh
Normal file
20
generators/machine-id/uuid4.sh
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Read 16 bytes from /dev/urandom
|
||||||
|
uuid=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null | od -An -tx1 | tr -d ' \n')
|
||||||
|
|
||||||
|
# Break the UUID into pieces and apply the required modifications
|
||||||
|
byte6=${uuid:12:2}
|
||||||
|
byte8=${uuid:16:2}
|
||||||
|
|
||||||
|
# Construct the correct version and variant
|
||||||
|
hex_byte6=$(printf "%x" $((0x$byte6 & 0x0F | 0x40)))
|
||||||
|
hex_byte8=$(printf "%x" $((0x$byte8 & 0x3F | 0x80)))
|
||||||
|
|
||||||
|
# Rebuild the UUID with the correct fields
|
||||||
|
uuid_v4="${uuid:0:12}${hex_byte6}${uuid:14:2}${hex_byte8}${uuid:18:14}"
|
||||||
|
|
||||||
|
# Format the UUID correctly 8-4-4-4-12
|
||||||
|
uuid_formatted="${uuid_v4:0:8}-${uuid_v4:8:4}-${uuid_v4:12:4}-${uuid_v4:16:4}-${uuid_v4:20:12}"
|
||||||
|
|
||||||
|
echo -n "$uuid_formatted"
|
9
generators/options.nix
Normal file
9
generators/options.nix
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
options.vars = {
|
||||||
|
unattended = lib.mkEnableOption "Whether to default to generating values unattended, rather than prompting for desired values.";
|
||||||
|
};
|
||||||
|
}
|
60
generators/root-password/default.nix
Normal file
60
generators/root-password/default.nix
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.vars.root-password;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
../options.nix
|
||||||
|
];
|
||||||
|
options.vars.root-password = {
|
||||||
|
enable = lib.mkEnableOption "Automatically generates and configures a password for the root user.";
|
||||||
|
prompt = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = !config.vars.unattended;
|
||||||
|
example = true;
|
||||||
|
description = "Whether the user should be prompted.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
users.mutableUsers = false;
|
||||||
|
users.users.root.hashedPasswordFile =
|
||||||
|
config.vars.generators.root-password.files.password-hash.path;
|
||||||
|
|
||||||
|
vars.generators.root-password = {
|
||||||
|
files.password-hash = {
|
||||||
|
neededFor = "users";
|
||||||
|
};
|
||||||
|
files.password-hash.restartUnits = lib.optional (config.services.userborn.enable) "userborn.service";
|
||||||
|
files.password = {
|
||||||
|
deploy = false;
|
||||||
|
};
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.mkpasswd
|
||||||
|
pkgs.xkcdpass
|
||||||
|
];
|
||||||
|
prompts = lib.mkIf cfg.prompt {
|
||||||
|
password = {
|
||||||
|
type = "hidden";
|
||||||
|
persist = true;
|
||||||
|
description = "You can autogenerate a password, if you leave this prompt blank.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
prompt_value=${if cfg.prompt then ''$(cat "$prompts"/password)'' else ""}
|
||||||
|
if [[ -n "''${prompt_value-}" ]]; then
|
||||||
|
echo "$prompt_value" | tr -d "\n" > "$out"/password
|
||||||
|
else
|
||||||
|
xkcdpass --numwords 3 --delimiter - --count 1 | tr -d "\n" > "$out"/password
|
||||||
|
fi
|
||||||
|
mkpasswd -s -m sha-512 < "$out"/password | tr -d "\n" > "$out"/password-hash
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
6
generators/sshd/client.nix
Normal file
6
generators/sshd/client.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./shared.nix
|
||||||
|
];
|
||||||
|
}
|
6
generators/sshd/default.nix
Normal file
6
generators/sshd/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./client.nix
|
||||||
|
./server.nix
|
||||||
|
];
|
||||||
|
}
|
103
generators/sshd/server.nix
Normal file
103
generators/sshd/server.nix
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
stringSet = list: builtins.attrNames (builtins.groupBy lib.id list);
|
||||||
|
|
||||||
|
domains = stringSet config.vars.sshd.certificate.searchDomains;
|
||||||
|
|
||||||
|
cfg = config.vars.sshd;
|
||||||
|
|
||||||
|
name = config.networking.hostName;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ../shared.nix ];
|
||||||
|
options = {
|
||||||
|
vars.sshd = {
|
||||||
|
enable = lib.mkEnableOption "Set up the opensshd service, generating a host key for the machine.";
|
||||||
|
hostKeys.rsa.enable = lib.mkEnableOption "Generate RSA host key";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings.PasswordAuthentication = false;
|
||||||
|
|
||||||
|
settings.HostCertificate = lib.mkIf (
|
||||||
|
cfg.certificate.searchDomains != [ ]
|
||||||
|
) config.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
||||||
|
|
||||||
|
hostKeys =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
path = config.vars.generators.openssh.files."ssh.id_ed25519".path;
|
||||||
|
type = "ed25519";
|
||||||
|
}
|
||||||
|
]
|
||||||
|
++ lib.optional cfg.hostKeys.rsa.enable {
|
||||||
|
path = config.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
||||||
|
type = "rsa";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vars.generators.openssh = {
|
||||||
|
files."ssh.id_ed25519" = { };
|
||||||
|
files."ssh.id_ed25519.pub".secret = false;
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.openssh
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
ssh-keygen -t ed25519 -N "" -f "$out"/ssh.id_ed25519
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.ssh.knownHosts.sshd-self-ed25519 = {
|
||||||
|
hostNames = [
|
||||||
|
"localhost"
|
||||||
|
config.networking.hostName
|
||||||
|
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
||||||
|
publicKey = config.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
||||||
|
};
|
||||||
|
|
||||||
|
vars.generators.openssh-rsa = lib.mkIf config.vars.sshd.hostKeys.rsa.enable {
|
||||||
|
files."ssh.id_rsa" = { };
|
||||||
|
files."ssh.id_rsa.pub".secret = false;
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.openssh
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
ssh-keygen -t rsa -b 4096 -N "" -f "$out"/ssh.id_rsa
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
vars.generators.openssh-cert = lib.mkIf (cfg.certificate.searchDomains != [ ]) {
|
||||||
|
files."ssh.id_ed25519-cert.pub".secret = false;
|
||||||
|
dependencies = [
|
||||||
|
"openssh"
|
||||||
|
"openssh-ca"
|
||||||
|
];
|
||||||
|
validation = {
|
||||||
|
inherit name;
|
||||||
|
domains = lib.genAttrs config.vars.sshd.certificate.searchDomains lib.id;
|
||||||
|
};
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.openssh
|
||||||
|
pkgs.jq
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
ssh-keygen \
|
||||||
|
-s $in/openssh-ca/id_ed25519 \
|
||||||
|
-I ${name} \
|
||||||
|
-h \
|
||||||
|
-n ${lib.concatMapStringsSep "," (d: "${name}.${d}") domains} \
|
||||||
|
$in/openssh/ssh.id_ed25519.pub
|
||||||
|
mv $in/openssh/ssh.id_ed25519-cert.pub "$out"/ssh.id_ed25519-cert.pub
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
44
generators/sshd/shared.nix
Normal file
44
generators/sshd/shared.nix
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.vars.sshd.certificate;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.vars.sshd.certificate = {
|
||||||
|
enable = lib.mkEnableOption "Add machines to the known hosts, enabling secure remote access to them over ssh.";
|
||||||
|
searchDomains = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "mydomain.com" ];
|
||||||
|
description = "List of domains to include in the certificate. This option will prepend the machine name in front of each domain before adding it to the certificate.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
vars.generators.openssh-ca =
|
||||||
|
lib.mkIf (config.vars.sshd.certificate.searchDomains != [ ])
|
||||||
|
{
|
||||||
|
share = true;
|
||||||
|
files.id_ed25519.deploy = false;
|
||||||
|
files."id_ed25519.pub" = {
|
||||||
|
deploy = false;
|
||||||
|
secret = false;
|
||||||
|
};
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.openssh
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.ssh.knownHosts.ssh-ca = lib.mkIf (config.vars.sshd.certificate.searchDomains != [ ]) {
|
||||||
|
certAuthority = true;
|
||||||
|
extraHostNames = builtins.map (domain: "*.${domain}") config.vars.sshd.certificate.searchDomains;
|
||||||
|
publicKey = config.vars.generators.openssh-ca.files."id_ed25519.pub".value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
22
generators/state-version/default.nix
Normal file
22
generators/state-version/default.nix
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
var = config.vars.generators.state-version.files.version or { };
|
||||||
|
cfg = config.vars.state-version;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.vars.state-version.enable = lib.mkEnableOption "Automatically generate the state version of the nixos installation.";
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
system.stateVersion = lib.mkDefault (lib.removeSuffix "\n" var.value);
|
||||||
|
|
||||||
|
vars.generators.state-version = {
|
||||||
|
files.version = {
|
||||||
|
secret = false;
|
||||||
|
value = lib.mkDefault config.system.nixos.release;
|
||||||
|
};
|
||||||
|
runtimeInputs = [ ];
|
||||||
|
script = ''
|
||||||
|
echo -n ${config.system.stateVersion} > "$out"/version
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
74
generators/user-password/default.nix
Normal file
74
generators/user-password/default.nix
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.vars.user-password;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
../options.nix
|
||||||
|
];
|
||||||
|
options.vars.user-password = {
|
||||||
|
enable = lib.mkEnableOption ''
|
||||||
|
Automatically generates and configures a password for a user.
|
||||||
|
|
||||||
|
This will set `mutableUsers` to `false`, meaning you can not manage user passwords through `passwd` anymore.
|
||||||
|
'';
|
||||||
|
users = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.submodule {
|
||||||
|
options = {
|
||||||
|
prompt = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = !config.vars.unattended;
|
||||||
|
example = true;
|
||||||
|
description = "Whether the user should be prompted.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
description = "The users for which to generate passwords.";
|
||||||
|
example = "{ alice = { }; }";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
users.mutableUsers = false;
|
||||||
|
users.users = lib.mapAttrs (userName: _: {
|
||||||
|
hashedPasswordFile = config.vars.generators."user-password-${userName}".files.user-password-hash.path;
|
||||||
|
isNormalUser = lib.mkDefault true;
|
||||||
|
}) cfg.users;
|
||||||
|
|
||||||
|
vars.generators = lib.mapAttrs (userName: user: {
|
||||||
|
"user-password-${userName}" = {
|
||||||
|
files.user-password-hash.neededFor = "users";
|
||||||
|
files.user-password-hash.restartUnits = lib.optional (config.services.userborn.enable) "userborn.service";
|
||||||
|
|
||||||
|
prompts = lib.mkIf user.prompt {
|
||||||
|
"user-password-${userName}" = {
|
||||||
|
type = "hidden";
|
||||||
|
persist = true;
|
||||||
|
description = "You can autogenerate a password, if you leave this prompt blank.";
|
||||||
|
files.user-password.deploy = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.xkcdpass
|
||||||
|
pkgs.mkpasswd
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
prompt_value=${if user.prompt then ''$(cat "$prompts"/user-password)'' else ""}
|
||||||
|
if [[ -n "''${prompt_value-}" ]]; then
|
||||||
|
echo "$prompt_value" | tr -d "\n" > "$out"/user-password
|
||||||
|
else
|
||||||
|
xkcdpass --numwords 3 --delimiter - --count 1 | tr -d "\n" > "$out"/user-password
|
||||||
|
fi
|
||||||
|
mkpasswd -s -m sha-512 < "$out"/user-password | tr -d "\n" > "$out"/user-password-hash
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}) cfg.users;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue