1 import ../make-test-python.nix ({ lib, ... }:
3 snakeoil-keys = import ./snakeoil-keys.nix;
5 hosts = lib.attrNames snakeoil-keys;
7 subnetOf = name: config:
9 subnets = config.services.tinc.networks.myNetwork.hostSettings.${name}.subnets;
11 (builtins.head subnets).address;
13 makeTincHost = name: { subnet, extraConfig ? { } }: lib.mkMerge [
15 subnets = [{ address = subnet; }];
17 Ed25519PublicKey = snakeoil-keys.${name}.ed25519Public;
19 rsaPublicKey = snakeoil-keys.${name}.rsaPublic;
24 makeTincNode = { config, ... }: name: extraConfig: lib.mkMerge [
26 services.tinc.networks.myNetwork = {
29 builtins.toFile "rsa.priv" snakeoil-keys.${name}.rsaPrivate;
30 ed25519PrivateKeyFile =
31 builtins.toFile "ed25519.priv" snakeoil-keys.${name}.ed25519Private;
33 hostSettings = lib.mapAttrs makeTincHost {
36 # Only specify the addresses in the node's vlans, Tinc does not
37 # seem to try each one, unlike the documentation suggests...
38 extraConfig.addresses = map
39 (vlan: { address = "192.168.${toString vlan}.11"; port = 655; })
40 config.virtualisation.vlans;
42 dynamic1 = { subnet = "10.0.0.21"; };
43 dynamic2 = { subnet = "10.0.0.22"; };
47 networking.useDHCP = false;
49 networking.interfaces."tinc.myNetwork" = {
53 address = subnetOf name config;
58 # Prevents race condition between NixOS service and tinc creating the
60 # See: https://github.com/NixOS/nixpkgs/issues/27070
61 systemd.services."tinc.myNetwork" = {
62 after = [ "network-addresses-tinc.myNetwork.service" ];
63 requires = [ "network-addresses-tinc.myNetwork.service" ];
66 networking.firewall.allowedTCPPorts = [ 655 ];
67 networking.firewall.allowedUDPPorts = [ 655 ];
75 meta.maintainers = with lib.maintainers; [ minijackson ];
79 static = { ... } @ args:
80 makeTincNode args "static" {
81 virtualisation.vlans = [ 1 2 ];
83 networking.interfaces.eth1.ipv4.addresses = [{
84 address = "192.168.1.11";
88 networking.interfaces.eth2.ipv4.addresses = [{
89 address = "192.168.2.11";
95 dynamic1 = { ... } @ args:
96 makeTincNode args "dynamic1" {
97 virtualisation.vlans = [ 1 ];
100 dynamic2 = { ... } @ args:
101 makeTincNode args "dynamic2" {
102 virtualisation.vlans = [ 2 ];
110 static.wait_for_unit("tinc.myNetwork.service")
111 dynamic1.wait_for_unit("tinc.myNetwork.service")
112 dynamic2.wait_for_unit("tinc.myNetwork.service")
114 # Static is accessible by the other hosts
115 dynamic1.succeed("ping -c5 192.168.1.11")
116 dynamic2.succeed("ping -c5 192.168.2.11")
118 # The other hosts are in separate vlans
119 dynamic1.fail("ping -c5 192.168.2.11")
120 dynamic2.fail("ping -c5 192.168.1.11")
122 # Each host can ping themselves through Tinc
123 static.succeed("ping -c5 10.0.0.11")
124 dynamic1.succeed("ping -c5 10.0.0.21")
125 dynamic2.succeed("ping -c5 10.0.0.22")
127 # Static is accessible by the other hosts through Tinc
128 dynamic1.succeed("ping -c5 10.0.0.11")
129 dynamic2.succeed("ping -c5 10.0.0.11")
131 # Static can access the other hosts through Tinc
132 static.succeed("ping -c5 10.0.0.21")
133 static.succeed("ping -c5 10.0.0.22")
135 # The other hosts in separate vlans can access each other through Tinc
136 dynamic1.succeed("ping -c5 10.0.0.22")
137 dynamic2.succeed("ping -c5 10.0.0.21")