Files
clan-core/clanServices/zerotier/default.nix
2025-09-16 17:24:11 +02:00

190 lines
5.1 KiB
Nix

{ ... }:
{
_class = "clan.service";
manifest.name = "clan-core/zerotier";
manifest.description = "Configuration of the secure and efficient Zerotier VPN";
manifest.categories = [ "Utility" ];
manifest.readme = builtins.readFile ./README.md;
roles.peer = {
perInstance =
{
instanceName,
roles,
lib,
...
}:
{
exports.networking = {
priority = lib.mkDefault 20;
# TODO add user space network support to clan-cli
module = "clan_lib.network.zerotier";
peers = lib.mapAttrs (name: machine: {
host.var = {
machine = name;
generator = "zerotier";
file = "zerotier-ip";
};
}) roles.peer.machines;
};
nixosModule =
{
config,
lib,
pkgs,
...
}:
{
imports = [
(import ./shared.nix {
inherit
instanceName
roles
config
lib
pkgs
;
})
];
};
};
};
roles.moon = {
interface =
{ lib, ... }:
{
options.stableEndpoints = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
Make this machine a moon.
Other machines can join this moon by adding this moon in their config.
It will be reachable under the given stable endpoints.
'';
example = ''
[ "1.2.3.4" "10.0.0.3/9993" "2001:abcd:abcd::3/9993" ]
'';
};
};
perInstance =
{
instanceName,
settings,
roles,
...
}:
{
nixosModule =
{
config,
lib,
pkgs,
...
}:
{
config.clan.core.networking.zerotier.moon.stableEndpoints = settings.stableEndpoints;
imports = [
(import ./shared.nix {
inherit
instanceName
roles
config
lib
pkgs
;
})
];
};
};
};
roles.controller = {
interface =
{ lib, ... }:
{
options.allowedIps = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Extra machines by their zerotier ip that the zerotier controller
should accept. These could be external machines.
'';
example = ''
[ "fd5d:bbe3:cbc5:fe6b:f699:935d:bbe3:cbc5" ]
'';
};
};
perInstance =
{
instanceName,
roles,
settings,
...
}:
{
nixosModule =
{
config,
lib,
pkgs,
...
}:
let
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
in
{
imports = [
(import ./shared.nix {
inherit
instanceName
roles
config
lib
pkgs
;
})
];
config = {
systemd.services.zerotier-inventory-autoaccept =
let
machines = uniqueStrings (
(lib.optionals (roles ? moon) (lib.attrNames roles.moon.machines))
++ (lib.optionals (roles ? controller) (lib.attrNames roles.controller.machines))
++ (lib.optionals (roles ? peer) (lib.attrNames roles.peer.machines))
);
networkIps = builtins.foldl' (
ips: name:
if
builtins.pathExists "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value"
then
ips
++ [
(builtins.readFile "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value")
]
else
ips
) [ ] machines;
allHostIPs = settings.allowedIps ++ networkIps;
in
{
wantedBy = [ "multi-user.target" ];
after = [ "zerotierone.service" ];
path = [ config.clan.core.clanPkgs.zerotierone ];
serviceConfig.ExecStart = pkgs.writeShellScript "zerotier-inventory-autoaccept" ''
${lib.concatMapStringsSep "\n" (host: ''
${config.clan.core.clanPkgs.zerotier-members}/bin/zerotier-members allow --member-ip ${host}
'') allHostIPs}
'';
};
clan.core.networking.zerotier.controller.enable = lib.mkDefault true;
};
};
};
};
}