Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
in {
nixosModules.default = { imports = [ ./options.nix ]; };
nixosModules.backend-on-machine = { imports = [ ./backends/on-machine.nix ]; };
nixosModules.generators = { imports = [ ./generators ]; };
# TODO fix tests
checks = forAllSystems (system: let
tests = {
Expand Down
11 changes: 11 additions & 0 deletions generators/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
imports = [
./disk-id
./garage
./machine-id
./root-password
./sshd
./state-version
./user-password
];
}
30 changes: 30 additions & 0 deletions generators/disk-id/default.nix
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions generators/disk-id/uuid4.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 59 additions & 0 deletions generators/garage/default.nix
Original file line number Diff line number Diff line change
@@ -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 changes: 46 additions & 0 deletions generators/machine-id/default.nix
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions generators/machine-id/uuid4.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions generators/options.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
lib,
...
}:
{
options.vars = {
unattended = lib.mkEnableOption "Whether to default to generating values unattended, rather than prompting for desired values.";
};
}
60 changes: 60 additions & 0 deletions generators/root-password/default.nix
Original file line number Diff line number Diff line change
@@ -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 changes: 6 additions & 0 deletions generators/sshd/client.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{ ... }:
{
imports = [
./shared.nix
];
}
6 changes: 6 additions & 0 deletions generators/sshd/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
imports = [
./client.nix
./server.nix
];
}
103 changes: 103 additions & 0 deletions generators/sshd/server.nix
Original file line number Diff line number Diff line change
@@ -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
'';
};
};
}
Loading