mumble: migrate to inventory
This commit is contained in:
@@ -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.")
|
||||
'';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 ];
|
||||
}
|
||||
|
||||
123
clanModules/mumble/roles/server.nix
Normal file
123
clanModules/mumble/roles/server.nix
Normal file
@@ -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"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user