{ clanLib, ... }: { _class = "clan.service"; manifest.name = "apple-network"; manifest.description = "This service will create an instance of `atalkd` for each peer to talk to Apple machines over Apple Talk protocol and automatically connect each peer using vxlan over Yggdrasil network to achieve Apple Talk over internet experience"; manifest.readme = builtins.readFile ./README.md; manifest.categories = [ "Network" ]; roles.peer = { description = "A gateway machine that allow classic Apple machines to connect to other Apple machines over the internet"; interface = { lib, ... }: { options = { zone_name = lib.mkOption { type = with lib.types; str; description = "Zone name for Apple Talk protocol"; default = "Default"; }; }; }; perInstance = { roles, settings, ... }: { nixosModule = { lib, config, pkgs, ... }: let vxlanPort = 4789; getYggdrasilIP = machineName: if config.clan.core.vars.generators.yggdrasil.files.address ? value then clanLib.getPublicValue { flake = config.clan.core.settings.directory; machine = machineName; generator = "yggdrasil"; file = "address"; default = null; } else throw "clanService/yggdrasil is required"; noSelfPeers = builtins.filter (peerName: peerName != config.clan.core.settings.machine.name) ( lib.mapAttrsToList (machineName: _: machineName) roles.peer.machines ); sortedPeers = builtins.sort (x: y: x < y) ( lib.mapAttrsToList (machineName: _: machineName) roles.peer.machines ); getMachineIndex = machineName: lib.lists.findFirstIndex (x: x == machineName) null sortedPeers; selfVXAddress = "192.168.254.${ lib.toString ((getMachineIndex config.clan.core.settings.machine.name) + 1) }/24"; in { services.atalkd = { enable = true; interfaces = { vxlan.config = '' -router -phase 2 -net 1 -zone "${settings.zone_name}" ''; }; }; networking.useNetworkd = true; networking.firewall.interfaces."ygg".allowedUDPPorts = [ vxlanPort ]; boot.kernelModules = [ "vxlan" ]; systemd.network.netdevs = builtins.listToAttrs ( map ( peerName: (lib.nameValuePair "10-apl-vxlan-${peerName}" { enable = true; netdevConfig = { Name = "vxlan-${peerName}"; Kind = "vxlan"; }; vxlanConfig = { VNI = (getMachineIndex config.clan.core.settings.machine.name) + (getMachineIndex peerName); Remote = getYggdrasilIP peerName; DestinationPort = vxlanPort; Independent = true; }; }) ) noSelfPeers ) // { "10-apl-vxlan" = { enable = true; netdevConfig = { Kind = "bridge"; Name = "vxlan"; }; bridgeConfig = { STP = true; }; }; }; systemd.network.networks = builtins.listToAttrs ( map ( peerName: (lib.nameValuePair "10-apl-vxlan-${peerName}" { enable = true; matchConfig.Name = "vxlan-${peerName}"; networkConfig.Bridge = "vxlan"; }) ) noSelfPeers ) // { "10-apl-vxlan" = { enable = true; matchConfig.Name = "vxlan"; address = [ selfVXAddress ]; }; }; environment.systemPackages = [ pkgs.netatalk pkgs.bridge-utils ]; }; }; }; }