From 84c1cb20bed0a0e1bcaf80dbf531fabe7613c039 Mon Sep 17 00:00:00 2001 From: pinpox Date: Wed, 4 Jun 2025 14:09:13 +0200 Subject: [PATCH] Migrate mycelium from clanModule to clanService --- checks/flake-module.nix | 3 + checks/mycelium/default.nix | 53 +++++++++++++++ checks/mycelium/sops/machines/server/key.json | 6 ++ .../sops/secrets/server-age.key/secret | 15 +++++ .../sops/secrets/server-age.key/users/admin | 1 + checks/mycelium/sops/users/admin/key.json | 4 ++ .../vars/per-machine/server/mycelium/ip/value | 1 + .../server/mycelium/key/machines/server | 1 + .../per-machine/server/mycelium/key/secret | 19 ++++++ .../server/mycelium/key/users/admin | 1 + .../per-machine/server/mycelium/pubkey/value | 1 + clanModules/mycelium/README.md | 2 +- clanServices/flake-module.nix | 1 + clanServices/mycelium/default.nix | 66 +++++++++++++++++++ clanServices/mycelium/flake-module.nix | 6 ++ docs/mkdocs.yml | 1 + 16 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 checks/mycelium/default.nix create mode 100755 checks/mycelium/sops/machines/server/key.json create mode 100644 checks/mycelium/sops/secrets/server-age.key/secret create mode 120000 checks/mycelium/sops/secrets/server-age.key/users/admin create mode 100644 checks/mycelium/sops/users/admin/key.json create mode 100644 checks/mycelium/vars/per-machine/server/mycelium/ip/value create mode 120000 checks/mycelium/vars/per-machine/server/mycelium/key/machines/server create mode 100644 checks/mycelium/vars/per-machine/server/mycelium/key/secret create mode 120000 checks/mycelium/vars/per-machine/server/mycelium/key/users/admin create mode 100644 checks/mycelium/vars/per-machine/server/mycelium/pubkey/value create mode 100644 clanServices/mycelium/default.nix create mode 100644 clanServices/mycelium/flake-module.nix diff --git a/checks/flake-module.nix b/checks/flake-module.nix index d38d972d2..ec15fb221 100644 --- a/checks/flake-module.nix +++ b/checks/flake-module.nix @@ -50,6 +50,9 @@ in # Heisenbridge test heisenbridge = import ./heisenbridge nixosTestArgs; + # Mycelium test + mycelium = import ./mycelium nixosTestArgs; + # Base Tests secrets = self.clanLib.test.baseTest ./secrets nixosTestArgs; borgbackup-legacy = self.clanLib.test.baseTest ./borgbackup-legacy nixosTestArgs; diff --git a/checks/mycelium/default.nix b/checks/mycelium/default.nix new file mode 100644 index 000000000..f601e74b4 --- /dev/null +++ b/checks/mycelium/default.nix @@ -0,0 +1,53 @@ +{ + pkgs, + nixosLib, + clan-core, + ... +}: +nixosLib.runTest ( + { ... }: + { + imports = [ + clan-core.modules.nixosVmTest.clanTest + ]; + + hostPkgs = pkgs; + + name = "mycelium"; + + clan = { + + test.useContainers = false; + directory = ./.; + modules."@clan/mycelium" = ../../clanServices/mycelium/default.nix; + inventory = { + machines.server = { }; + + instances = { + mycelium-test = { + module.name = "@clan/mycelium"; + roles.peer.machines."server".settings = { + openFirewall = true; + addHostedPublicNodes = true; + }; + }; + }; + }; + }; + + nodes = { + server = { }; + }; + + testScript = '' + start_all() + + # Check that mycelium service is running + server.wait_for_unit("mycelium") + server.succeed("systemctl status mycelium") + + # Check that mycelium is listening on its default port + server.succeed("${pkgs.iproute2}/bin/ss -tulpn | grep -q 'mycelium'") + ''; + } +) diff --git a/checks/mycelium/sops/machines/server/key.json b/checks/mycelium/sops/machines/server/key.json new file mode 100755 index 000000000..5543597d7 --- /dev/null +++ b/checks/mycelium/sops/machines/server/key.json @@ -0,0 +1,6 @@ +[ + { + "publickey": "age122lc4fvw2p22gcvwqeme5k49qxtjanqkl2xvr6qvf3r0zyh7scuqz28cam", + "type": "age" + } +] diff --git a/checks/mycelium/sops/secrets/server-age.key/secret b/checks/mycelium/sops/secrets/server-age.key/secret new file mode 100644 index 000000000..9d63a2541 --- /dev/null +++ b/checks/mycelium/sops/secrets/server-age.key/secret @@ -0,0 +1,15 @@ +{ + "data": "ENC[AES256_GCM,data:hLJS+CJllYM50KxKuiYamxBLGd9lwoeIFapP9mZAlVGH5DSenylcKUfsphxafASoB516qns2DznBoS9mWqg9uTsRZjk4WlR3x6A=,iv:uRiIpUKIiV3riNcBAWUqhZbE+Vb7lLMfU0C/TClVZ6M=,tag:4+nsMssiSyq9Iv7sDuWmoQ==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPUWFOMzluRmdOQXBmRjRN\ncXNSUlB5Z0t6dWYxNVkvMmhrN1FDdmxHcTNJCkhPL3BYMFFXMmU5ZGRqOC9KWEgv\nSHB5OUJqTk5Dd0tDTks1R1ZhYktrLzgKLS0tIHJIMlFRVWphZXlISmR3VUJKUjNk\ndWF4eCt6UHBrSndBay95RVJ3dldiaFkKCgYqrt0aCGRTaHycBoeqv/zeByu2ZZ3Z\nVfgxnD9liIQkS2wERbpk0/Yq9wkKgVxj+DZoWwHYhP0eKCw2UOorCA==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-06-04T11:54:59Z", + "mac": "ENC[AES256_GCM,data:xoeOz7FRCPJ18UTsfbY1x/N65pxbTsehT9Kv3MgEd6NQJn6FTvquaj3HEZ0KvIzStBz1FNOhSql9CZUFc4StYps05EbX61MMMnz6Nlj3xcTwuVQFabGoinxcXbCDSA+tAW7VqzVxumj6FMDg+r77gdcIApZjGJg4Z9ws2RZd3u4=,iv:U8IUDwmfg8Umob9mtKgGaKoIY4SKNL895BABJxzx5n8=,tag:tnMCx6D/17ZYgI6SgNS29A==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/checks/mycelium/sops/secrets/server-age.key/users/admin b/checks/mycelium/sops/secrets/server-age.key/users/admin new file mode 120000 index 000000000..9e21a9938 --- /dev/null +++ b/checks/mycelium/sops/secrets/server-age.key/users/admin @@ -0,0 +1 @@ +../../../users/admin \ No newline at end of file diff --git a/checks/mycelium/sops/users/admin/key.json b/checks/mycelium/sops/users/admin/key.json new file mode 100644 index 000000000..e408aa96b --- /dev/null +++ b/checks/mycelium/sops/users/admin/key.json @@ -0,0 +1,4 @@ +{ + "publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "type": "age" +} diff --git a/checks/mycelium/vars/per-machine/server/mycelium/ip/value b/checks/mycelium/vars/per-machine/server/mycelium/ip/value new file mode 100644 index 000000000..347f99246 --- /dev/null +++ b/checks/mycelium/vars/per-machine/server/mycelium/ip/value @@ -0,0 +1 @@ +52d:87c1:4222:b550:ee01:a7ae:254:5a66 diff --git a/checks/mycelium/vars/per-machine/server/mycelium/key/machines/server b/checks/mycelium/vars/per-machine/server/mycelium/key/machines/server new file mode 120000 index 000000000..2bd819ecb --- /dev/null +++ b/checks/mycelium/vars/per-machine/server/mycelium/key/machines/server @@ -0,0 +1 @@ +../../../../../../sops/machines/server \ No newline at end of file diff --git a/checks/mycelium/vars/per-machine/server/mycelium/key/secret b/checks/mycelium/vars/per-machine/server/mycelium/key/secret new file mode 100644 index 000000000..d698d0e8e --- /dev/null +++ b/checks/mycelium/vars/per-machine/server/mycelium/key/secret @@ -0,0 +1,19 @@ +{ + "data": "ENC[AES256_GCM,data:DGzl2G4H+NkwXq0fCUQS0+8FG1x9xoIsYvAgUxP4Qp8=,iv:CXOJVgYNthVOZ4vbdI3n4KLXSFVemzaoEnRGMC+m0i8=,tag:/u+pV3xWpUq0ZtAm6LKuGQ==,type:str]", + "sops": { + "age": [ + { + "recipient": "age122lc4fvw2p22gcvwqeme5k49qxtjanqkl2xvr6qvf3r0zyh7scuqz28cam", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZZHZjdXMwclBTeGthcGpM\nV1ArVy83akNHNEpXVFhoR1FWNlJUeHNKTW00CjJFTFZneFNrL0hDMXJpaTQ2M1ln\nTmdPMGhzeUp0NU55QnhCZEU2QVk1OG8KLS0tIDFhQmJhOHJsTjhYNEhITEw0WFgy\nWC9pTi9od0wyMWtZRVZJYWo0Nmo5SHMKDohnAAfrnGOiw55huMme2EEWE53N/feS\nutvbiTZh1ECHCi/uoK757fjnJ/WrQMSxUpctT9I8bpJRtbTqkx3XRw==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZeTZENGFpWndDbmdsWDRw\nMTBCVXg5Zkg2a2s5Yk1HSERIVlVQRXdUSUNnCnREbno0dEN0ZEgvOFNMRG1ReGx4\na0h1YUFuMkxBZXJUTE9xOUVUMitEalkKLS0tIFZMZ21qclRqUFR0dlAyMFkzdUNX\nNjRLTWVRVWtHSDlDakEzMmpRVWkyc0EKabm8mTKJVxQNTaIgU+8rb/xk9Dpg+Zjz\nb+wgD0+TlARlenMtIub8Y6N06ENOc20oovylfu+g7xV+EkvRPCd6tA==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-06-04T11:55:02Z", + "mac": "ENC[AES256_GCM,data:UIBaD/3mACgFzkajkFXz3oKai8IxpYQriR2t0mc5fL92P5ECloxCobY386TDZYOEVrDJ45Bw+IzqZbsCx/G9f1xCCTR2JvqygxYIsK3TpQPsboJzb9Cz3dBNBCXGboVykcg/NobEMaJBw1xtdAQBhuo8S7ymIuOPtGz0vPFJkf8=,iv:g0YAOBsRpgAOikKDMJDyOtcVx+0QwetfA8R6wQFH7lY=,tag:sfdFLjtiqFHdP/Qe1suBBQ==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/checks/mycelium/vars/per-machine/server/mycelium/key/users/admin b/checks/mycelium/vars/per-machine/server/mycelium/key/users/admin new file mode 120000 index 000000000..ca714e122 --- /dev/null +++ b/checks/mycelium/vars/per-machine/server/mycelium/key/users/admin @@ -0,0 +1 @@ +../../../../../../sops/users/admin \ No newline at end of file diff --git a/checks/mycelium/vars/per-machine/server/mycelium/pubkey/value b/checks/mycelium/vars/per-machine/server/mycelium/pubkey/value new file mode 100644 index 000000000..27bc22556 --- /dev/null +++ b/checks/mycelium/vars/per-machine/server/mycelium/pubkey/value @@ -0,0 +1 @@ +2125c6b039374467eaa3eaf552bd3e97f434d16006433cfbba3e6823c958b728 diff --git a/clanModules/mycelium/README.md b/clanModules/mycelium/README.md index 989ac9d0f..975288b6c 100644 --- a/clanModules/mycelium/README.md +++ b/clanModules/mycelium/README.md @@ -1,7 +1,7 @@ --- description = "End-2-end encrypted IPv6 overlay network" categories = ["System", "Network"] -features = [ "inventory" ] +features = [ "inventory", "deprecated" ] --- Mycelium is an IPv6 overlay network written in Rust. Each node that joins the overlay network will receive an overlay network IP in the 400::/7 range. diff --git a/clanServices/flake-module.nix b/clanServices/flake-module.nix index b3cdcc6a8..226355afe 100644 --- a/clanServices/flake-module.nix +++ b/clanServices/flake-module.nix @@ -6,6 +6,7 @@ ./ergochat/flake-module.nix ./garage/flake-module.nix ./heisenbridge/flake-module.nix + ./mycelium/flake-module.nix ./auto-upgrade/flake-module.nix ./hello-world/flake-module.nix ./wifi/flake-module.nix diff --git a/clanServices/mycelium/default.nix b/clanServices/mycelium/default.nix new file mode 100644 index 000000000..65737cff9 --- /dev/null +++ b/clanServices/mycelium/default.nix @@ -0,0 +1,66 @@ +{ ... }: +{ + _class = "clan.service"; + manifest.name = "clan-core/mycelium"; + manifest.description = "End-2-end encrypted IPv6 overlay network"; + manifest.categories = [ + "System" + "Network" + ]; + + roles.peer = { + interface = + { lib, ... }: + { + options = { + openFirewall = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Open the firewall for mycelium"; + }; + + addHostedPublicNodes = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Add hosted Public nodes"; + }; + }; + }; + + perInstance = + { settings, ... }: + { + nixosModule = + { + config, + pkgs, + lib, + ... + }: + { + services.mycelium = { + enable = true; + addHostedPublicNodes = lib.mkDefault settings.addHostedPublicNodes; + openFirewall = lib.mkDefault settings.openFirewall; + keyFile = config.clan.core.vars.generators.mycelium.files.key.path; + }; + + clan.core.vars.generators.mycelium = { + files.key = { }; + files.ip.secret = false; + files.pubkey.secret = false; + runtimeInputs = [ + pkgs.mycelium + pkgs.coreutils + pkgs.jq + ]; + script = '' + timeout 5 mycelium --key-file "$out"/key || : + mycelium inspect --key-file "$out"/key --json | jq -r .publicKey > "$out"/pubkey + mycelium inspect --key-file "$out"/key --json | jq -r .address > "$out"/ip + ''; + }; + }; + }; + }; +} diff --git a/clanServices/mycelium/flake-module.nix b/clanServices/mycelium/flake-module.nix new file mode 100644 index 000000000..d3687e5e7 --- /dev/null +++ b/clanServices/mycelium/flake-module.nix @@ -0,0 +1,6 @@ +{ lib, ... }: +{ + clan.modules = { + mycelium = lib.modules.importApply ./default.nix { }; + }; +} diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 337f30de9..5eed4c7a8 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -89,6 +89,7 @@ nav: - reference/clanServices/ergochat.md - reference/clanServices/garage.md - reference/clanServices/heisenbridge.md + - reference/clanServices/mycelium.md - reference/clanServices/hello-world.md - reference/clanServices/wifi.md - reference/clanServices/zerotier.md