Files
clan-core/clanServices/zerotier/shared.nix

73 lines
2.1 KiB
Nix

{
clanLib,
lib,
config,
pkgs,
roles,
instanceName,
...
}:
let
controllerMachine = builtins.head (lib.attrNames roles.controller.machines or { });
networkId = clanLib.vars.getPublicValue {
flake = config.clan.core.settings.directory;
machine = controllerMachine;
generator = "zerotier";
file = "zerotier-network-id";
default = null;
};
moons = lib.attrNames (roles.moon.machines or { });
moonIps = builtins.foldl' (
ips: name:
let
moonIp = clanLib.vars.getPublicValue {
flake = config.clan.core.settings.directory;
machine = name;
generator = "zerotier";
file = "zerotier-ip";
default = null;
};
in
if moonIp != null then ips ++ [ moonIp ] else ips
) [ ] moons;
in
{
config = {
clan.core.networking.zerotier.networkId = networkId;
clan.core.networking.zerotier.name = instanceName;
systemd.services.zerotierone.serviceConfig.ExecStartPost = lib.mkIf (moonIps != [ ]) (
lib.mkAfter [
"+${pkgs.writeScript "orbit-moons-by-ip" ''
#!${pkgs.python3.interpreter}
import json
import ipaddress
import subprocess
def compute_member_id(ipv6_addr: str) -> str:
addr = ipaddress.IPv6Address(ipv6_addr)
addr_bytes = bytearray(addr.packed)
# Extract the bytes corresponding to the member_id (node_id)
node_id_bytes = addr_bytes[10:16]
node_id = int.from_bytes(node_id_bytes, byteorder="big")
member_id = format(node_id, "x").zfill(10)[-10:]
return member_id
def main() -> None:
ips = json.loads(${builtins.toJSON (builtins.toJSON moonIps)})
for ip in ips:
member_id = compute_member_id(ip)
res = subprocess.run(["zerotier-cli", "orbit", member_id, member_id])
if res.returncode != 0:
print(f"Failed to add {member_id} to orbit")
if __name__ == "__main__":
main()
''}"
]
);
};
}