diff --git a/checks/mumble/default.nix b/checks/mumble/default.nix index 912943270..081b5ea75 100644 --- a/checks/mumble/default.nix +++ b/checks/mumble/default.nix @@ -1,143 +1,102 @@ -(import ../lib/test-base.nix) ( - { ... }: - let - common = - { self, pkgs, ... }: - { - imports = [ - self.clanModules.mumble - { - clan.services.mumble.user = "alice"; - } - self.nixosModules.clanCore - (self.inputs.nixpkgs + "/nixos/tests/common/x11.nix") - { - clan.core.settings.directory = ./.; - environment.systemPackages = [ pkgs.killall ]; - clan.core.facts.services.mumble.secret."mumble-key".path = "/etc/mumble-key"; - clan.core.facts.services.mumble.public."mumble-cert".path = "/etc/mumble-cert"; - } - ]; +{ + pkgs, + self, + clanLib, + ... +}: +clanLib.test.makeTestClan { + inherit pkgs self; + nixosTest = ( + { lib, ... }: + let + common = + { pkgs, modulesPath, ... }: + { + imports = [ + (modulesPath + "/../tests/common/x11.nix") + ]; + clan.services.mumble.user = "alice"; + environment.systemPackages = [ pkgs.killall ]; + }; + machines = [ + "peer1" + "peer2" + ]; + in + { + name = "mumble"; + + clan = { + directory = ./.; + inventory = { + machines = lib.genAttrs machines (_: { }); + services = { + mumble.default = { + roles.server.machines = machines; + }; + }; + }; }; - in - { - name = "mumble"; - enableOCR = true; + enableOCR = true; - nodes.peer1 = - { ... }: - { - imports = [ - common - { - environment.etc = { - "mumble-key".source = ./peer_1/peer_1_test_key; - "mumble-cert".source = ./peer_1/peer_1_test_cert; - }; - systemd.tmpfiles.settings."vmsecrets" = { - "/var/lib/murmur/sslKey" = { - C.argument = "${./peer_1/peer_1_test_key}"; - z = { - mode = "0400"; - user = "murmur"; - }; - }; - "/var/lib/murmur/sslCert" = { - C.argument = "${./peer_1/peer_1_test_cert}"; - z = { - mode = "0400"; - user = "murmur"; - }; - }; - }; - clan.core.facts.services.mumble.secret."mumble-key".path = "/etc/mumble-key"; - clan.core.facts.services.mumble.public."mumble-cert".path = "/etc/mumble-cert"; - } - ]; - }; - nodes.peer2 = - { ... }: - { - imports = [ - common - { - environment.etc = { - "mumble-key".source = ./peer_2/peer_2_test_key; - "mumble-cert".source = ./peer_2/peer_2_test_cert; - }; - systemd.tmpfiles.settings."vmsecrets" = { - "/var/lib/murmur/sslKey" = { - C.argument = "${./peer_2/peer_2_test_key}"; - z = { - mode = "0400"; - user = "murmur"; - }; - }; - "/var/lib/murmur/sslCert" = { - C.argument = "${./peer_2/peer_2_test_cert}"; - z = { - mode = "0400"; - user = "murmur"; - }; - }; - }; - } - ]; - }; - testScript = '' - start_all() + nodes.peer1 = common; + nodes.peer2 = common; - with subtest("Waiting for x"): - peer1.wait_for_x() - peer2.wait_for_x() + testScript = '' + start_all() - with subtest("Waiting for murmur"): - peer1.wait_for_unit("murmur.service") - peer2.wait_for_unit("murmur.service") + with subtest("Waiting for x"): + peer1.wait_for_x() + peer2.wait_for_x() - with subtest("Starting Mumble"): - # starting mumble is blocking - peer1.execute("mumble >&2 &") - peer2.execute("mumble >&2 &") + with subtest("Waiting for murmur"): + peer1.wait_for_unit("murmur.service") + peer2.wait_for_unit("murmur.service") - with subtest("Wait for Mumble"): - peer1.wait_for_window(r"^Mumble$") - peer2.wait_for_window(r"^Mumble$") + with subtest("Starting Mumble"): + # starting mumble is blocking + peer1.execute("mumble >&2 &") + peer2.execute("mumble >&2 &") - with subtest("Wait for certificate creation"): - peer1.wait_for_window(r"^Mumble$") - peer1.sleep(3) # mumble is slow to register handlers - peer1.send_chars("\n") - peer1.send_chars("\n") - peer2.wait_for_window(r"^Mumble$") - peer2.sleep(3) # mumble is slow to register handlers - peer2.send_chars("\n") - peer2.send_chars("\n") + with subtest("Wait for Mumble"): + peer1.wait_for_window(r"^Mumble$") + peer2.wait_for_window(r"^Mumble$") - with subtest("Wait for server connect"): - peer1.wait_for_window(r"^Mumble Server Connect$") - peer2.wait_for_window(r"^Mumble Server Connect$") + with subtest("Wait for certificate creation"): + peer1.wait_for_window(r"^Mumble$") + peer1.sleep(3) # mumble is slow to register handlers + peer1.send_chars("\n") + peer1.send_chars("\n") + peer2.wait_for_window(r"^Mumble$") + peer2.sleep(3) # mumble is slow to register handlers + peer2.send_chars("\n") + peer2.send_chars("\n") - with subtest("Check validity of server certificates"): - peer1.execute("killall .mumble-wrapped") - peer1.sleep(1) - peer1.execute("mumble mumble://peer2 >&2 &") - peer1.wait_for_window(r"^Mumble$") - peer1.sleep(3) # mumble is slow to register handlers - peer1.send_chars("\n") - peer1.send_chars("\n") - peer1.wait_for_text("Connected.") + with subtest("Wait for server connect"): + peer1.wait_for_window(r"^Mumble Server Connect$") + peer2.wait_for_window(r"^Mumble Server Connect$") - peer2.execute("killall .mumble-wrapped") - peer2.sleep(1) - peer2.execute("mumble mumble://peer1 >&2 &") - peer2.wait_for_window(r"^Mumble$") - peer2.sleep(3) # mumble is slow to register handlers - peer2.send_chars("\n") - peer2.send_chars("\n") - peer2.wait_for_text("Connected.") - ''; - } -) + with subtest("Check validity of server certificates"): + peer1.execute("killall .mumble-wrapped") + peer1.sleep(1) + peer1.execute("mumble mumble://peer2 >&2 &") + peer1.wait_for_window(r"^Mumble$") + peer1.sleep(3) # mumble is slow to register handlers + peer1.send_chars("\n") + peer1.send_chars("\n") + peer1.wait_for_text("Connected.") + + peer2.execute("killall .mumble-wrapped") + peer2.sleep(1) + peer2.execute("mumble mumble://peer1 >&2 &") + peer2.wait_for_window(r"^Mumble$") + peer2.sleep(3) # mumble is slow to register handlers + peer2.send_chars("\n") + peer2.send_chars("\n") + peer2.wait_for_text("Connected.") + ''; + } + ); +} diff --git a/clanModules/mumble/README.md b/clanModules/mumble/README.md index 552a9e2d1..a33b99714 100644 --- a/clanModules/mumble/README.md +++ b/clanModules/mumble/README.md @@ -1,7 +1,12 @@ --- description = "Open Source, Low Latency, High Quality Voice Chat." categories = ["Audio", "Social"] +features = [ "inventory" ] + +[constraints] +roles.server.min = 1 --- + The mumble clan module gives you: - True low latency voice communication. diff --git a/clanModules/mumble/default.nix b/clanModules/mumble/default.nix index 2cca556ad..ab24e1e49 100644 --- a/clanModules/mumble/default.nix +++ b/clanModules/mumble/default.nix @@ -1,122 +1,6 @@ +# Dont import this file +# It is only here for backwards compatibility. +# Dont author new modules with this file. { - lib, - config, - pkgs, - ... -}: -let - dir = config.clan.core.settings.directory; - machineDir = dir + "/vars/per-machine"; - machinesFileSet = builtins.readDir machineDir; - machines = lib.mapAttrsToList (name: _: name) machinesFileSet; - machineJson = builtins.toJSON machines; - certificateMachinePath = machines: machineDir + "/${machines}" + "/mumble/mumble-cert/value"; - certificatesUnchecked = builtins.map ( - machine: - let - fullPath = certificateMachinePath machine; - in - if builtins.pathExists fullPath then machine else null - ) machines; - certificate = lib.filter (machine: machine != null) certificatesUnchecked; - machineCert = builtins.map ( - machine: (lib.nameValuePair machine (builtins.readFile (certificateMachinePath machine))) - ) certificate; - machineCertJson = builtins.toJSON machineCert; - -in -{ - options.clan.services.mumble = { - user = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - example = "alice"; - description = "The user mumble should be set up for."; - }; - }; - - config = { - services.murmur = { - enable = true; - logDays = -1; - registerName = config.clan.core.settings.machine.name; - openFirewall = true; - bonjour = true; - sslKey = "/var/lib/murmur/sslKey"; - sslCert = "/var/lib/murmur/sslCert"; - }; - - clan.core.state.mumble.folders = [ - "/var/lib/mumble" - "/var/lib/murmur" - ]; - - systemd.tmpfiles.rules = [ - "d '/var/lib/mumble' 0770 '${config.clan.services.mumble.user}' 'users' - -" - ]; - - systemd.tmpfiles.settings."murmur" = { - "/var/lib/murmur/sslKey" = { - C.argument = config.clan.core.vars.generators.mumble.files.mumble-key.path; - Z = { - mode = "0400"; - user = "murmur"; - }; - }; - "/var/lib/murmur/sslCert" = { - C.argument = config.clan.core.vars.generators.mumble.files.mumble-cert.path; - Z = { - mode = "0400"; - user = "murmur"; - }; - }; - }; - - environment.systemPackages = - let - mumbleCfgDir = "/var/lib/mumble"; - mumbleDatabasePath = "${mumbleCfgDir}/mumble.sqlite"; - mumbleCfgPath = "/var/lib/mumble/mumble_settings.json"; - populate-channels = pkgs.writers.writePython3 "mumble-populate-channels" { - libraries = [ - pkgs.python3Packages.cryptography - pkgs.python3Packages.pyopenssl - ]; - flakeIgnore = [ - # We don't live in the dark ages anymore. - # Languages like Python that are whitespace heavy will overrun - # 79 characters.. - "E501" - ]; - } (builtins.readFile ./mumble-populate-channels.py); - mumble = pkgs.writeShellScriptBin "mumble" '' - set -xeu - mkdir -p ${mumbleCfgDir} - pushd "${mumbleCfgDir}" - XDG_DATA_HOME=${mumbleCfgDir} - XDG_DATA_DIR=${mumbleCfgDir} - ${populate-channels} --ensure-config '${mumbleCfgPath}' --db-location ${mumbleDatabasePath} - ${populate-channels} --machines '${machineJson}' --username ${config.clan.core.settings.machine.name} --db-location ${mumbleDatabasePath} - ${populate-channels} --servers '${machineCertJson}' --username ${config.clan.core.settings.machine.name} --db-location ${mumbleDatabasePath} --cert True - ${pkgs.mumble}/bin/mumble --config ${mumbleCfgPath} "$@" - popd - ''; - in - [ mumble ]; - - clan.core.vars.generators.mumble = { - migrateFact = "mumble"; - files.mumble-key = { }; - files.mumble-cert.secret = false; - runtimeInputs = [ - pkgs.coreutils - pkgs.openssl - ]; - script = '' - openssl genrsa -out "$out/mumble-key" 2048 - openssl req -new -x509 -key "$out/mumble-key" -out "$out/mumble-cert" - ''; - }; - }; - + imports = [ ./roles/server.nix ]; } diff --git a/clanModules/mumble/mumble-populate-channels.py b/clanModules/mumble/roles/mumble-populate-channels.py similarity index 100% rename from clanModules/mumble/mumble-populate-channels.py rename to clanModules/mumble/roles/mumble-populate-channels.py diff --git a/clanModules/mumble/roles/server.nix b/clanModules/mumble/roles/server.nix new file mode 100644 index 000000000..479a502b3 --- /dev/null +++ b/clanModules/mumble/roles/server.nix @@ -0,0 +1,123 @@ +{ + lib, + config, + pkgs, + ... +}: +let + dir = config.clan.core.settings.directory; + # TODO: this should actually use the inventory to figure out which machines to use. + machineDir = dir + "/vars/per-machine"; + machinesFileSet = builtins.readDir machineDir; + machines = lib.mapAttrsToList (name: _: name) machinesFileSet; + machineJson = builtins.toJSON machines; + certificateMachinePath = machines: machineDir + "/${machines}" + "/mumble/mumble-cert/value"; + certificatesUnchecked = builtins.map ( + machine: + let + fullPath = certificateMachinePath machine; + in + if builtins.pathExists fullPath then machine else null + ) machines; + certificate = lib.filter (machine: machine != null) certificatesUnchecked; + machineCert = builtins.map ( + machine: (lib.nameValuePair machine (builtins.readFile (certificateMachinePath machine))) + ) certificate; + machineCertJson = builtins.toJSON machineCert; + +in +{ + options.clan.services.mumble = { + user = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + example = "alice"; + description = "The user mumble should be set up for."; + }; + }; + + config = { + services.murmur = { + enable = true; + logDays = -1; + registerName = config.clan.core.settings.machine.name; + openFirewall = true; + bonjour = true; + sslKey = "/var/lib/murmur/sslKey"; + sslCert = "/var/lib/murmur/sslCert"; + }; + + clan.core.state.mumble.folders = [ + "/var/lib/mumble" + "/var/lib/murmur" + ]; + + systemd.tmpfiles.rules = [ + "d '/var/lib/mumble' 0770 '${config.clan.services.mumble.user}' 'users' - -" + ]; + + systemd.tmpfiles.settings."murmur" = { + "/var/lib/murmur/sslKey" = { + C.argument = config.clan.core.vars.generators.mumble.files.mumble-key.path; + Z = { + mode = "0400"; + user = "murmur"; + }; + }; + "/var/lib/murmur/sslCert" = { + C.argument = config.clan.core.vars.generators.mumble.files.mumble-cert.path; + Z = { + mode = "0400"; + user = "murmur"; + }; + }; + }; + + environment.systemPackages = + let + mumbleCfgDir = "/var/lib/mumble"; + mumbleDatabasePath = "${mumbleCfgDir}/mumble.sqlite"; + mumbleCfgPath = "/var/lib/mumble/mumble_settings.json"; + populate-channels = pkgs.writers.writePython3 "mumble-populate-channels" { + libraries = [ + pkgs.python3Packages.cryptography + pkgs.python3Packages.pyopenssl + ]; + flakeIgnore = [ + # We don't live in the dark ages anymore. + # Languages like Python that are whitespace heavy will overrun + # 79 characters.. + "E501" + ]; + } (builtins.readFile ./mumble-populate-channels.py); + mumble = pkgs.writeShellScriptBin "mumble" '' + set -xeu + mkdir -p ${mumbleCfgDir} + pushd "${mumbleCfgDir}" + XDG_DATA_HOME=${mumbleCfgDir} + XDG_DATA_DIR=${mumbleCfgDir} + ${populate-channels} --ensure-config '${mumbleCfgPath}' --db-location ${mumbleDatabasePath} + ${populate-channels} --machines '${machineJson}' --username ${config.clan.core.settings.machine.name} --db-location ${mumbleDatabasePath} + ${populate-channels} --servers '${machineCertJson}' --username ${config.clan.core.settings.machine.name} --db-location ${mumbleDatabasePath} --cert True + ${pkgs.mumble}/bin/mumble --config ${mumbleCfgPath} "$@" + popd + ''; + in + [ mumble ]; + + clan.core.vars.generators.mumble = { + migrateFact = "mumble"; + files.mumble-key = { }; + files.mumble-cert.secret = false; + runtimeInputs = [ + pkgs.coreutils + pkgs.openssl + ]; + script = '' + openssl genrsa -out "$out/mumble-key" 2048 + openssl req -new -x509 -key "$out/mumble-key" -out "$out/mumble-cert" + ''; + }; + }; + +}