mumble: migrate to inventory
This commit is contained in:
@@ -1,143 +1,102 @@
|
|||||||
(import ../lib/test-base.nix) (
|
{
|
||||||
{ ... }:
|
pkgs,
|
||||||
let
|
self,
|
||||||
common =
|
clanLib,
|
||||||
{ self, pkgs, ... }:
|
...
|
||||||
{
|
}:
|
||||||
imports = [
|
clanLib.test.makeTestClan {
|
||||||
self.clanModules.mumble
|
inherit pkgs self;
|
||||||
{
|
nixosTest = (
|
||||||
clan.services.mumble.user = "alice";
|
{ lib, ... }:
|
||||||
}
|
let
|
||||||
self.nixosModules.clanCore
|
common =
|
||||||
(self.inputs.nixpkgs + "/nixos/tests/common/x11.nix")
|
{ pkgs, modulesPath, ... }:
|
||||||
{
|
{
|
||||||
clan.core.settings.directory = ./.;
|
imports = [
|
||||||
environment.systemPackages = [ pkgs.killall ];
|
(modulesPath + "/../tests/common/x11.nix")
|
||||||
clan.core.facts.services.mumble.secret."mumble-key".path = "/etc/mumble-key";
|
];
|
||||||
clan.core.facts.services.mumble.public."mumble-cert".path = "/etc/mumble-cert";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
|
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 =
|
nodes.peer1 = common;
|
||||||
{ ... }:
|
nodes.peer2 = common;
|
||||||
{
|
|
||||||
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()
|
|
||||||
|
|
||||||
with subtest("Waiting for x"):
|
testScript = ''
|
||||||
peer1.wait_for_x()
|
start_all()
|
||||||
peer2.wait_for_x()
|
|
||||||
|
|
||||||
with subtest("Waiting for murmur"):
|
with subtest("Waiting for x"):
|
||||||
peer1.wait_for_unit("murmur.service")
|
peer1.wait_for_x()
|
||||||
peer2.wait_for_unit("murmur.service")
|
peer2.wait_for_x()
|
||||||
|
|
||||||
with subtest("Starting Mumble"):
|
with subtest("Waiting for murmur"):
|
||||||
# starting mumble is blocking
|
peer1.wait_for_unit("murmur.service")
|
||||||
peer1.execute("mumble >&2 &")
|
peer2.wait_for_unit("murmur.service")
|
||||||
peer2.execute("mumble >&2 &")
|
|
||||||
|
|
||||||
with subtest("Wait for Mumble"):
|
with subtest("Starting Mumble"):
|
||||||
peer1.wait_for_window(r"^Mumble$")
|
# starting mumble is blocking
|
||||||
peer2.wait_for_window(r"^Mumble$")
|
peer1.execute("mumble >&2 &")
|
||||||
|
peer2.execute("mumble >&2 &")
|
||||||
|
|
||||||
with subtest("Wait for certificate creation"):
|
with subtest("Wait for Mumble"):
|
||||||
peer1.wait_for_window(r"^Mumble$")
|
peer1.wait_for_window(r"^Mumble$")
|
||||||
peer1.sleep(3) # mumble is slow to register handlers
|
peer2.wait_for_window(r"^Mumble$")
|
||||||
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 server connect"):
|
with subtest("Wait for certificate creation"):
|
||||||
peer1.wait_for_window(r"^Mumble Server Connect$")
|
peer1.wait_for_window(r"^Mumble$")
|
||||||
peer2.wait_for_window(r"^Mumble Server Connect$")
|
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"):
|
with subtest("Wait for server connect"):
|
||||||
peer1.execute("killall .mumble-wrapped")
|
peer1.wait_for_window(r"^Mumble Server Connect$")
|
||||||
peer1.sleep(1)
|
peer2.wait_for_window(r"^Mumble Server Connect$")
|
||||||
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")
|
with subtest("Check validity of server certificates"):
|
||||||
peer2.sleep(1)
|
peer1.execute("killall .mumble-wrapped")
|
||||||
peer2.execute("mumble mumble://peer1 >&2 &")
|
peer1.sleep(1)
|
||||||
peer2.wait_for_window(r"^Mumble$")
|
peer1.execute("mumble mumble://peer2 >&2 &")
|
||||||
peer2.sleep(3) # mumble is slow to register handlers
|
peer1.wait_for_window(r"^Mumble$")
|
||||||
peer2.send_chars("\n")
|
peer1.sleep(3) # mumble is slow to register handlers
|
||||||
peer2.send_chars("\n")
|
peer1.send_chars("\n")
|
||||||
peer2.wait_for_text("Connected.")
|
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."
|
description = "Open Source, Low Latency, High Quality Voice Chat."
|
||||||
categories = ["Audio", "Social"]
|
categories = ["Audio", "Social"]
|
||||||
|
features = [ "inventory" ]
|
||||||
|
|
||||||
|
[constraints]
|
||||||
|
roles.server.min = 1
|
||||||
---
|
---
|
||||||
|
|
||||||
The mumble clan module gives you:
|
The mumble clan module gives you:
|
||||||
|
|
||||||
- True low latency voice communication.
|
- 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,
|
imports = [ ./roles/server.nix ];
|
||||||
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"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
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