{ ... }: { _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; }; }; }; }; }