labgrid.coordinator.service: Provide the service (#492469)

This commit is contained in:
Sandro
2026-03-06 15:18:21 +00:00
committed by GitHub
4 changed files with 164 additions and 0 deletions
+1
View File
@@ -604,6 +604,7 @@
./services/development/hoogle.nix
./services/development/jupyter/default.nix
./services/development/jupyterhub/default.nix
./services/development/labgrid/coordinator.nix
./services/development/livebook.nix
./services/development/lorri.nix
./services/development/nixseparatedebuginfod2.nix
@@ -0,0 +1,96 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.labgrid.coordinator;
in
{
meta = {
maintainers = with lib.maintainers; [
aiyion
emantor
];
};
options = {
services.labgrid.coordinator = {
bindAddress = lib.mkOption {
default = "0.0.0.0";
type = lib.types.str;
description = "Bind address for the labgrid coordinator.";
};
debug = lib.mkOption {
default = false;
type = with lib.types; bool;
description = ''
Whether to enable debug mode.
'';
};
enable = lib.mkEnableOption "Labgrid Coordinator";
openFirewall = lib.mkOption {
default = false;
type = with lib.types; bool;
description = ''
Whether to automatically open the coordinator listen port in the firewall.
'';
};
package = lib.mkPackageOption pkgs [ "python3Packages" "labgrid" ] { };
port = lib.mkOption {
default = 20408;
type = lib.types.port;
description = "Coordinator port to bind to.";
};
};
};
config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
systemd.services.labgrid-coordinator = {
after = [ "network-online.target" ];
description = "Labgrid Coordinator";
serviceConfig = {
Environment = ''"PYTHONUNBUFFERED=1"'';
ExecStart = "${lib.getBin cfg.package}/bin/labgrid-coordinator ${lib.optionalString cfg.debug "--debug"} --listen ${cfg.bindAddress}:${toString cfg.port}";
Restart = "on-failure";
DynamicUser = "yes";
StateDirectory = "labgrid-coordinator";
WorkingDirectory = "/var/lib/labgrid-coordinator";
CapabilityBoundingSet = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictRealtime = true;
RestrictAddressFamilies = "AF_INET AF_INET6";
RestrictNamespaces = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
};
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
};
};
}
+1
View File
@@ -853,6 +853,7 @@ in
inherit runTest;
inherit (pkgs) lib;
};
labgrid = runTest ./labgrid.nix;
lact = runTest ./lact.nix;
ladybird = runTest ./ladybird.nix;
languagetool = runTest ./languagetool.nix;
+66
View File
@@ -0,0 +1,66 @@
{ pkgs, ... }:
{
name = "Labgrid";
meta.maintainers = with pkgs.lib.maintainers; [
aiyion
emantor
];
nodes.coordinator =
{ pkgs, ... }:
{
services.labgrid.coordinator.enable = true;
services.labgrid.coordinator.openFirewall = true;
};
nodes.client =
{ pkgs, ... }:
{
environment.variables = {
LG_COORDINATOR = "coordinator:20408";
};
environment.systemPackages = [ pkgs.python3Packages.labgrid ];
};
testScript =
{ nodes, ... }:
#python
''
def assert_contains(haystack, needle):
if needle not in haystack:
print("The haystack that will cause the following exception is:")
print("---")
print(haystack)
print("---")
raise Exception(f"Expected string '{needle}' was not found")
with subtest("Wait for coordinator startup"):
coordinator.start()
coordinator.wait_for_unit("labgrid-coordinator.service")
coordinator.wait_for_open_port(20408)
with subtest("Connect from client"):
client.start()
out = client.succeed("labgrid-client resources")
with subtest("Create place"):
client.succeed("labgrid-client -p testplace create")
out = client.succeed("labgrid-client places")
assert_contains(out, "testplace")
# Give the coordinator enough time to persist place creation
coordinator.wait_until_succeeds("grep -q testplace /var/lib/labgrid-coordinator/places.yaml")
with subtest("Test coordinator persistence"):
coordinator.shutdown()
coordinator.start()
coordinator.wait_for_unit("labgrid-coordinator.service")
coordinator.wait_for_open_port(20408)
out = client.succeed("labgrid-client places")
assert_contains(out, "testplace")
with subtest("Check systemd hardening does not degrade unnoticed"):
exact_threshold = 11
out = coordinator.fail(f"systemd-analyze security labgrid-coordinator.service --threshold={exact_threshold-1}")
out = coordinator.succeed(f"systemd-analyze security labgrid-coordinator.service --threshold={exact_threshold}")
'';
}