diff --git a/clanServices/yggdrasil/default.nix b/clanServices/yggdrasil/default.nix new file mode 100644 index 000000000..ee588d087 --- /dev/null +++ b/clanServices/yggdrasil/default.nix @@ -0,0 +1,108 @@ +# Example clan service. See https://docs.clan.lol/guides/services/community/ +# for more details + +# The test for this module in ./tests/vm/default.nix shows an example of how +# the service is used. + +{ packages }: +{ ... }: +{ + _class = "clan.service"; + manifest.name = "clan-core/yggdrasil"; + manifest.description = "Yggdrasil VPN"; + + roles.default = { + # interface = + # { lib, ... }: + # { + # # Here we define the settings for this role. They will be accessible + # # via `roles.morning.settings` in the role + # + # options.greeting = lib.mkOption { + # type = lib.types.str; + # default = "Good morning"; + # description = "The greeting to use"; + # }; + # }; + # Maps over all instances and produces one result per instance. + perInstance = + { + # Role settings for this machine/instance + settings, + + # The name of this instance of the service + instanceName, + + # The current machine + machine, + + # All roles of this service, with their assigned machines + roles, + ... + }: + { + # Analog to 'perSystem' of flake-parts. + # For every instance of this service we will add a nixosModule to a morning-machine + nixosModule = + { config, pkgs, ... }: + { + + clan.core.vars.generators.yggdrasil = { + + files.privateKey = { }; + + runtimeInputs = with pkgs; [ + yggdrasil + jq + ]; + + script = '' + yggdrasil -genconf -json | jq 'to_entries|map(select(.key|endswith("Key")))|from_entries' > $out/privateKey + ''; + }; + + services.yggdrasil = { + persistentKeys = true; + enable = true; + }; + + systemd.services.yggdrasil.serviceConfig.BindReadOnlyPaths = [ + "${config.clan.core.vars.generators.yggdrasil.files.privateKey.path}:/var/lib/yggdrasil/keys.json" + ]; + + # Interaction examples what you could do here: + # - Get some settings of this machine + # settings.ipRanges + # + # - Get all evening names: + # allEveningNames = lib.attrNames roles.evening.machines + # + # - Get all roles of the machine: + # machine.roles + # + # - Get the settings that where applied to a specific evening machine: + # roles.evening.machines.peer1.settings + # environment.etc.hello.text = "${settings.greeting} World!"; + }; + }; + }; + + # This part gets applied to all machines, regardless of their role. + # perMachine = + # { machine, ... }: + # { + # nixosModule = + # { pkgs, ... }: + # { + # environment.systemPackages = [ + # (pkgs.writeShellScriptBin "greet-world" '' + # #!${pkgs.bash}/bin/bash + # set -euo pipefail + # + # cat /etc/hello + # echo " I'm ${machine.name}" + # '') + # ]; + # }; + # }; +} diff --git a/clanServices/yggdrasil/flake-module.nix b/clanServices/yggdrasil/flake-module.nix new file mode 100644 index 000000000..eb0e1a8e4 --- /dev/null +++ b/clanServices/yggdrasil/flake-module.nix @@ -0,0 +1,25 @@ +{ + self, + inputs, + lib, + ... +}: +let + module = lib.modules.importApply ./default.nix { + inherit (self) packages; + }; +in +{ + clan.modules = { + yggdrasil = module; + }; + perSystem = + { ... }: + { + clan.nixosTests.yggdrasil = { + imports = [ ./tests/vm/default.nix ]; + + clan.modules.yggdrasil = module; + }; + }; +} diff --git a/clanServices/yggdrasil/tests/vm/default.nix b/clanServices/yggdrasil/tests/vm/default.nix new file mode 100644 index 000000000..ac818a579 --- /dev/null +++ b/clanServices/yggdrasil/tests/vm/default.nix @@ -0,0 +1,41 @@ +{ + name = "yggdrasil"; + + clan = { + directory = ./.; + inventory = { + + machines.peer1 = { }; + + # machines.peer2 = { }; + + instances."yggdrasil" = { + module.name = "yggdrasil"; + module.input = "self"; + + # Assign the roles to the two machines + roles.default.machines.peer1 = { }; + + # roles.evening.machines.peer2 = { + # # Set roles settings for the peers, where we want to differ from + # # the role defaults + # settings = { + # greeting = "Good night"; + # }; + # }; + }; + }; + }; + + testScript = + { ... }: + '' + start_all() + + # value = peer1.succeed("greet-world") + # assert value.strip() == "Good morning World! I'm peer1", value + # + # value = peer2.succeed("greet-world") + # assert value.strip() == "Good night World! I'm peer2", value + ''; +} diff --git a/clanServices/yggdrasil/tests/vm/sops/users/admin/key.json b/clanServices/yggdrasil/tests/vm/sops/users/admin/key.json new file mode 100644 index 000000000..e408aa96b --- /dev/null +++ b/clanServices/yggdrasil/tests/vm/sops/users/admin/key.json @@ -0,0 +1,4 @@ +{ + "publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "type": "age" +}