Migrate borgbackup module to vars

This commit is contained in:
Pablo Ovelleiro Corral
2025-01-13 22:38:13 +01:00
committed by Jörg Thalheim
parent 89890d34af
commit 038083bece
9 changed files with 64 additions and 45 deletions

View File

@@ -62,14 +62,14 @@
user = "root"; user = "root";
}; };
}; };
"/etc/secrets/borgbackup.ssh" = { "/etc/secrets/borgbackup/borgbackup.ssh" = {
C.argument = "${../lib/ssh/privkey}"; C.argument = "${../lib/ssh/privkey}";
z = { z = {
mode = "0400"; mode = "0400";
user = "root"; user = "root";
}; };
}; };
"/etc/secrets/borgbackup.repokey" = { "/etc/secrets/borgbackup/borgbackup.repokey" = {
C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345"); C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345");
z = { z = {
mode = "0400"; mode = "0400";
@@ -78,8 +78,7 @@
}; };
}; };
clan.core.facts.secretStore = "vm"; clan.core.facts.secretStore = "vm";
# TODO: set this backend as well, once we have implemented it. clan.core.vars.settings.secretStore = "vm";
#clan.core.vars.settings.secretStore = "vm";
environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ]; environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ];
environment.etc.install-closure.source = "${closureInfo}/store-paths"; environment.etc.install-closure.source = "${closureInfo}/store-paths";

View File

@@ -21,14 +21,14 @@
clan.core.state.testState.folders = [ "/etc/state" ]; clan.core.state.testState.folders = [ "/etc/state" ];
environment.etc.state.text = "hello world"; environment.etc.state.text = "hello world";
systemd.tmpfiles.settings."vmsecrets" = { systemd.tmpfiles.settings."vmsecrets" = {
"/etc/secrets/borgbackup.ssh" = { "/etc/secrets/borgbackup/borgbackup.ssh" = {
C.argument = "${../lib/ssh/privkey}"; C.argument = "${../lib/ssh/privkey}";
z = { z = {
mode = "0400"; mode = "0400";
user = "root"; user = "root";
}; };
}; };
"/etc/secrets/borgbackup.repokey" = { "/etc/secrets/borgbackup/borgbackup.repokey" = {
C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345"); C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345");
z = { z = {
mode = "0400"; mode = "0400";
@@ -36,7 +36,8 @@
}; };
}; };
}; };
clan.core.facts.secretStore = "vm"; # clan.core.facts.secretStore = "vm";
clan.core.vars.settings.secretStore = "vm";
clan.borgbackup.destinations.test.repo = "borg@localhost:."; clan.borgbackup.destinations.test.repo = "borg@localhost:.";
} }

View File

@@ -63,9 +63,9 @@ in
rsh = lib.mkOption { rsh = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "ssh -i ${ default = "ssh -i ${
config.clan.core.facts.services.borgbackup.secret."borgbackup.ssh".path config.clan.core.vars.generators.borgbackup.files."borgbackup.ssh".path
} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=Yes"; } -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=Yes";
defaultText = "ssh -i \${config.clan.core.facts.services.borgbackup.secret.\"borgbackup.ssh\".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"; defaultText = "ssh -i \${config.clan.core.vars.generators.borgbackup.files.\"borgbackup.ssh\".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
description = "the rsh to use for the backup"; description = "the rsh to use for the backup";
}; };
}; };
@@ -126,7 +126,7 @@ in
encryption = { encryption = {
mode = "repokey"; mode = "repokey";
passCommand = "cat ${config.clan.core.facts.services.borgbackup.secret."borgbackup.repokey".path}"; passCommand = "cat ${config.clan.core.vars.generators.borgbackup.files."borgbackup.repokey".path}";
}; };
prune.keep = { prune.keep = {
@@ -177,20 +177,21 @@ in
}) })
]; ];
# Facts generation. So the client can authenticate to the server clan.core.vars.generators.borgbackup = {
clan.core.facts.services.borgbackup = {
public."borgbackup.ssh.pub" = { }; files."borgbackup.ssh.pub".secret = false;
secret."borgbackup.ssh" = { }; files."borgbackup.ssh" = { };
secret."borgbackup.repokey" = { }; files."borgbackup.repokey" = { };
generator.path = [
pkgs.openssh migrateFact = "borgbackup";
runtimeInputs = [
pkgs.coreutils pkgs.coreutils
pkgs.openssh
pkgs.xkcdpass pkgs.xkcdpass
]; ];
generator.script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$secrets"/borgbackup.ssh ssh-keygen -t ed25519 -N "" -f $out/borgbackup.ssh
mv "$secrets"/borgbackup.ssh.pub "$facts"/borgbackup.ssh.pub xkcdpass -n 4 -d - > $out/borgbackup.repokey
xkcdpass -n 4 -d - > "$secrets"/borgbackup.repokey
''; '';
}; };

View File

@@ -1,7 +1,7 @@
{ config, lib, ... }: { config, lib, ... }:
let let
dir = config.clan.core.settings.directory; dir = config.clan.core.settings.directory;
machineDir = dir + "/machines/"; machineDir = dir + "/vars/per-machine/";
machineName = config.clan.core.settings.machine.name; machineName = config.clan.core.settings.machine.name;
# Instances might be empty, if the module is not used via the inventory # Instances might be empty, if the module is not used via the inventory
@@ -33,7 +33,8 @@ in
}; };
config.services.borgbackup.repos = config.services.borgbackup.repos =
let let
borgbackupIpMachinePath = machines: machineDir + machines + "/facts/borgbackup.ssh.pub"; borgbackupIpMachinePath = machine: machineDir + machine + "/borgbackup/borgbackup.ssh.pub/value";
machinesMaybeKey = builtins.map ( machinesMaybeKey = builtins.map (
machine: machine:
let let
@@ -44,7 +45,7 @@ in
else else
lib.warn '' lib.warn ''
Machine ${machine} does not have a borgbackup key at ${fullPath}, Machine ${machine} does not have a borgbackup key at ${fullPath},
run `clan facts generate ${machine}` to generate it. run `clan var generate ${machine}` to generate it.
'' null '' null
) allClients; ) allClients;

23
flake.lock generated
View File

@@ -42,11 +42,11 @@
}, },
"nixos-facter-modules": { "nixos-facter-modules": {
"locked": { "locked": {
"lastModified": 1734596637, "lastModified": 1736931726,
"narHash": "sha256-MRqwVAe3gsb88u4ME1UidmZFVCx+FEnoob0zkpO9DMY=", "narHash": "sha256-aY55yiifyo1XPPpbpH0kWlV1g2dNGBlx6622b7OK8ks=",
"owner": "numtide", "owner": "numtide",
"repo": "nixos-facter-modules", "repo": "nixos-facter-modules",
"rev": "536472754982bf03079b4b4e0261838a760587c0", "rev": "fa11d87b61b2163efbb9aed7b7a5ae0299e5ab9c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -57,11 +57,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1736657626, "lastModified": 1736881310,
"narHash": "sha256-FWlPMUzp0lkQBdhKlPqtQdqmp+/C+1MBiEytaYfrCTY=", "narHash": "sha256-5BlVeikKoJVrUXBdr1kSrcRQ8o20Kl+ZU2pEzpE5sUw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2f9e2f85cb14a46410a1399aa9ea7ecf433e422e", "rev": "733994ea06585b76621073160e87b0bfac7fc5ae",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -89,15 +89,16 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1736515725, "lastModified": 1736953253,
"narHash": "sha256-4P99yL8vGehwzytkpP87eklBePt6aqeEC5JFsIzhfUs=", "narHash": "sha256-shJxzy7qypjq9hpETQ3gJsBZXO5E3KR0INca/xwiVp4=",
"owner": "Mic92", "owner": "pinpox",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "f214c1b76c347a4e9c8fb68c73d4293a6820d125", "rev": "a7c6e64401b6dde13c0de90230cb64087c9d9693",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "Mic92", "owner": "pinpox",
"ref": "lazy-assertions",
"repo": "sops-nix", "repo": "sops-nix",
"type": "github" "type": "github"
} }

View File

@@ -12,7 +12,7 @@
nixos-facter-modules.url = "github:numtide/nixos-facter-modules"; nixos-facter-modules.url = "github:numtide/nixos-facter-modules";
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:pinpox/sops-nix/lazy-assertions";
sops-nix.inputs.nixpkgs.follows = "nixpkgs"; sops-nix.inputs.nixpkgs.follows = "nixpkgs";
systems.url = "github:nix-systems/default"; systems.url = "github:nix-systems/default";

View File

@@ -6,8 +6,6 @@
}: }:
let let
inherit (lib) flip;
inherit (import ./funcs.nix { inherit lib; }) collectFiles; inherit (import ./funcs.nix { inherit lib; }) collectFiles;
machineName = config.clan.core.settings.machine.name; machineName = config.clan.core.settings.machine.name;
@@ -38,16 +36,18 @@ in
}; };
config.sops = lib.mkIf (config.clan.core.vars.settings.secretStore == "sops") { config.sops = lib.mkIf (config.clan.core.vars.settings.secretStore == "sops") {
secrets = lib.listToAttrs ( secrets = lib.listToAttrs (
flip map vars (secret: { map (secret: {
name = "vars/${secret.generator}/${secret.name}"; name = "vars/${secret.generator}/${secret.name}";
value = { value = {
inherit (secret) owner group neededForUsers; inherit (secret) owner group neededForUsers;
sopsFile = secretPath secret; sopsFile = secretPath secret;
format = "binary"; format = "binary";
}; };
}) }) (builtins.filter (x: builtins.pathExists (secretPath x)) vars)
); );
# To get proper error messages about missing secrets we need a dummy secret file that is always present # To get proper error messages about missing secrets we need a dummy secret file that is always present
defaultSopsFile = lib.mkIf config.sops.validateSopsFiles ( defaultSopsFile = lib.mkIf config.sops.validateSopsFiles (
lib.mkDefault (builtins.toString (pkgs.writeText "dummy.yaml" "")) lib.mkDefault (builtins.toString (pkgs.writeText "dummy.yaml" ""))

View File

@@ -32,7 +32,7 @@ class Prompt:
name=data["name"], name=data["name"],
description=data["description"], description=data["description"],
prompt_type=PromptType(data["type"]), prompt_type=PromptType(data["type"]),
create_file=data.get("persist", data["createFile"]), create_file=data.get("persist", data["persist"]),
previous_value=data.get("previousValue"), previous_value=data.get("previousValue"),
) )

View File

@@ -18,7 +18,8 @@ from fixtures_flakes import FlakeForTest
if TYPE_CHECKING: if TYPE_CHECKING:
from age_keys import KeyPair from age_keys import KeyPair
from clan_cli.machines.facts import machine_get_fact # from clan_cli.vars.var import machine_get_fact
from clan_cli.machines.machines import Machine as MachineMachine
from helpers import cli from helpers import cli
@@ -86,10 +87,25 @@ def test_add_module_to_inventory(
set_inventory(inventory, base_path, "Add borgbackup service") set_inventory(inventory, base_path, "Add borgbackup service")
cmd = ["facts", "generate", "--flake", str(test_flake_with_core.path), "machine1"] # cmd = ["facts", "generate", "--flake", str(test_flake_with_core.path), "machine1"]
cmd = ["vars", "generate", "--flake", str(test_flake_with_core.path), "machine1"]
cli.run(cmd) cli.run(cmd)
ssh_key = machine_get_fact(base_path, "machine1", "borgbackup.ssh.pub") machine = MachineMachine(
name="machine1", flake=FlakeId(str(test_flake_with_core.path))
)
generator = None
for gen in machine.vars_generators:
if gen.name == "borgbackup":
generator = gen
break
assert generator
ssh_key = machine.public_vars_store.get(generator, "borgbackup.ssh.pub")
cmd = nix_eval( cmd = nix_eval(
[ [
@@ -100,4 +116,4 @@ def test_add_module_to_inventory(
proc = run_no_stdout(cmd) proc = run_no_stdout(cmd)
res = json.loads(proc.stdout.strip()) res = json.loads(proc.stdout.strip())
assert res["machine1"]["authorizedKeys"] == [ssh_key] assert res["machine1"]["authorizedKeys"] == [ssh_key.decode()]