mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-09 19:13:26 +03:00
broadcast-box: init at 0-unstable-2025-06-04 (#288443)
This commit is contained in:
commit
f53da6c507
7 changed files with 381 additions and 0 deletions
|
@ -20,6 +20,8 @@
|
|||
- [LACT](https://github.com/ilya-zlobintsev/LACT), a GPU monitoring and configuration tool, can now be enabled through [services.lact.enable](#opt-services.lact.enable).
|
||||
Note that for LACT to work properly on AMD GPU systems, you need to enable [hardware.amdgpu.overdrive.enable](#opt-hardware.amdgpu.overdrive.enable).
|
||||
|
||||
- [Broadcast Box](https://github.com/Glimesh/broadcast-box), a WebRTC broadcast server. Available as [services.broadcast-box](options.html#opt-services.broadcast-box.enable).
|
||||
|
||||
- [SuiteNumérique Docs](https://github.com/suitenumerique/docs), a collaborative note taking, wiki and documentation web platform and alternative to Notion or Outline. Available as [services.lasuite-docs](#opt-services.lasuite-docs.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-25.11-incompatibilities}
|
||||
|
|
|
@ -1491,6 +1491,7 @@
|
|||
./services/ttys/getty.nix
|
||||
./services/ttys/gpm.nix
|
||||
./services/ttys/kmscon.nix
|
||||
./services/video/broadcast-box.nix
|
||||
./services/video/epgstation/default.nix
|
||||
./services/video/frigate.nix
|
||||
./services/video/go2rtc/default.nix
|
||||
|
|
274
nixos/modules/services/video/broadcast-box.nix
Normal file
274
nixos/modules/services/video/broadcast-box.nix
Normal file
|
@ -0,0 +1,274 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
mkIf
|
||||
mkEnableOption
|
||||
mkPackageOption
|
||||
mkOption
|
||||
attrNames
|
||||
types
|
||||
match
|
||||
optional
|
||||
optionals
|
||||
toInt
|
||||
last
|
||||
splitString
|
||||
allUnique
|
||||
concatStringsSep
|
||||
all
|
||||
filter
|
||||
mapAttrs
|
||||
any
|
||||
getExe
|
||||
maintainers
|
||||
;
|
||||
inherit (cfg) settings;
|
||||
cfg = config.services.broadcast-box;
|
||||
|
||||
addressToPort = address: toInt (last (splitString ":" address));
|
||||
httpPort = cfg.web.port;
|
||||
tcpMuxPort = addressToPort settings.TCP_MUX_ADDRESS;
|
||||
httpRedirect = settings.ENABLE_HTTP_REDIRECT or (settings.HTTPS_REDIRECT_PORT != null);
|
||||
|
||||
udpPorts =
|
||||
optional (settings.UDP_MUX_PORT != null) settings.UDP_MUX_PORT
|
||||
++ optional (settings.UDP_WHEP_PORT != null) settings.UDP_WHEP_PORT
|
||||
++ optional (settings.UDP_WHIP_PORT != null) settings.UDP_WHIP_PORT;
|
||||
tcpPorts = optional (settings.TCP_MUX_ADDRESS != null) tcpMuxPort;
|
||||
webPorts = [ httpPort ] ++ optional httpRedirect settings.HTTPS_REDIRECT_PORT;
|
||||
in
|
||||
{
|
||||
options.services.broadcast-box = {
|
||||
enable = mkEnableOption "Broadcast Box";
|
||||
package = mkPackageOption pkgs "broadcast-box" { };
|
||||
|
||||
web = {
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "127.0.0.1";
|
||||
description = ''
|
||||
Host address the HTTP server listens on. By default the server
|
||||
listens on all interfaces.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Port the HTTP server listens on.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkEnableOption ''
|
||||
opening the HTTP server port and, if enabled, the HTTPS redirect server
|
||||
port in the firewall.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkEnableOption ''
|
||||
opening WebRTC traffic ports in the firewall. Randomly selected ports
|
||||
will not be opened.
|
||||
'';
|
||||
|
||||
settings = mkOption {
|
||||
visible = "shallow";
|
||||
|
||||
type = types.submodule {
|
||||
freeformType =
|
||||
with types;
|
||||
attrsOf (
|
||||
nullOr (oneOf [
|
||||
bool
|
||||
int
|
||||
str
|
||||
])
|
||||
);
|
||||
options = {
|
||||
TCP_MUX_ADDRESS = mkOption {
|
||||
type = with types; nullOr (strMatching ".*:[0-9]+");
|
||||
default = null;
|
||||
};
|
||||
|
||||
DISABLE_STATUS = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
UDP_MUX_PORT = mkOption {
|
||||
type = with types; nullOr port;
|
||||
default = null;
|
||||
};
|
||||
|
||||
UDP_WHEP_PORT = mkOption {
|
||||
type = with types; nullOr port;
|
||||
default = null;
|
||||
};
|
||||
|
||||
UDP_WHIP_PORT = mkOption {
|
||||
type = with types; nullOr port;
|
||||
default = null;
|
||||
};
|
||||
|
||||
ENABLE_HTTP_REDIRECT = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
HTTPS_REDIRECT_PORT = mkOption {
|
||||
type = with types; nullOr port;
|
||||
default = if settings.ENABLE_HTTP_REDIRECT then 80 else null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
default = {
|
||||
DISABLE_STATUS = true;
|
||||
};
|
||||
|
||||
example = {
|
||||
DISABLE_STATUS = true;
|
||||
INCLUDE_PUBLIC_IP_IN_NAT_1_TO_1_IP = true;
|
||||
UDP_MUX_PORT = 3000;
|
||||
};
|
||||
|
||||
description = ''
|
||||
Attribute set of environment variables.
|
||||
|
||||
<https://github.com/Glimesh/broadcast-box#environment-variables>
|
||||
|
||||
:::{.warning}
|
||||
The status API exposes stream keys so {env}`DISABLE_STATUS` is enabled
|
||||
by default.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !(settings ? HTTP_ADDRESS);
|
||||
message = ''
|
||||
The Broadcast Box `HTTP_ADDRESS` variable should not be used. Instead
|
||||
use the `host` and `port` options.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = httpRedirect -> settings ? SSL_CERT && settings ? SSL_KEY;
|
||||
message = ''
|
||||
The Broadcast Box `ENABLE_HTTP_REDIRECT` variable requires `SSL_CERT`
|
||||
and `SSL_KEY` to be configured.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = httpRedirect -> httpPort == 443;
|
||||
message = ''
|
||||
Broadcast Box HTTP redirect only works if the HTTP server listen port
|
||||
is 443.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = allUnique (tcpPorts ++ webPorts);
|
||||
message = ''
|
||||
Broadcast Box configuration contains duplicate TCP ports.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = all (name: (match "[A-Z0-9_]+" name) != null) (attrNames settings);
|
||||
message =
|
||||
let
|
||||
offenders = filter (name: (match "[A-Z0-9_]+" name) == null) (attrNames settings);
|
||||
in
|
||||
''
|
||||
Broadcast Box `settings` attribute names must be in uppercase snake
|
||||
case. Invalid attribute name(s): `${concatStringsSep ", " offenders}`
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.broadcast-box = {
|
||||
description = "Broadcast Box";
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
startLimitBurst = 3;
|
||||
startLimitIntervalSec = 180;
|
||||
|
||||
environment =
|
||||
(mapAttrs (
|
||||
_: value:
|
||||
if (builtins.typeOf value == "bool") then
|
||||
if !value then null else "true"
|
||||
else if (builtins.typeOf value == "int") then
|
||||
toString value
|
||||
else
|
||||
value
|
||||
) cfg.settings)
|
||||
// {
|
||||
APP_ENV = "nixos";
|
||||
HTTP_ADDRESS = cfg.web.host + ":" + toString cfg.web.port;
|
||||
};
|
||||
|
||||
serviceConfig =
|
||||
let
|
||||
priviledgedPort = any (p: p > 0 && p < 1024) (udpPorts ++ tcpPorts ++ webPorts);
|
||||
in
|
||||
{
|
||||
ExecStart = "${getExe cfg.package}";
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
|
||||
DynamicUser = true;
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateUsers = !priviledgedPort;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectClock = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProcSubset = "pid";
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
];
|
||||
CapabilityBoundingSet = if priviledgedPort then [ "CAP_NET_BIND_SERVICE" ] else "";
|
||||
AmbientCapabilities = mkIf priviledgedPort [ "CAP_NET_BIND_SERVICE" ];
|
||||
DeviceAllow = "";
|
||||
MemoryDenyWriteExecute = true;
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = optionals cfg.openFirewall tcpPorts ++ optionals cfg.web.openFirewall webPorts;
|
||||
allowedUDPPorts = optionals cfg.openFirewall udpPorts;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ JManch ];
|
||||
}
|
|
@ -264,6 +264,7 @@ in
|
|||
bpf = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./bpf.nix { };
|
||||
bpftune = runTest ./bpftune.nix;
|
||||
breitbandmessung = runTest ./breitbandmessung.nix;
|
||||
broadcast-box = runTest ./broadcast-box.nix;
|
||||
brscan5 = runTest ./brscan5.nix;
|
||||
btrbk = runTest ./btrbk.nix;
|
||||
btrbk-doas = runTest ./btrbk-doas.nix;
|
||||
|
|
21
nixos/tests/broadcast-box.nix
Normal file
21
nixos/tests/broadcast-box.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
name = "broadcast-box";
|
||||
meta = { inherit (pkgs.broadcast-box.meta) maintainers; };
|
||||
|
||||
nodes.machine = {
|
||||
services.broadcast-box = {
|
||||
enable = true;
|
||||
web = {
|
||||
host = "127.0.0.1";
|
||||
port = 8080;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("broadcast-box.service")
|
||||
machine.wait_for_open_port(8080)
|
||||
machine.succeed("curl --fail http://localhost:8080/")
|
||||
'';
|
||||
}
|
13
pkgs/by-name/br/broadcast-box/allow-no-env.patch
Normal file
13
pkgs/by-name/br/broadcast-box/allow-no-env.patch
Normal file
|
@ -0,0 +1,13 @@
|
|||
diff --git a/main.go b/main.go
|
||||
index 1814da0..2befc13 100644
|
||||
--- a/main.go
|
||||
+++ b/main.go
|
||||
@@ -175,6 +175,8 @@ func main() {
|
||||
if os.Getenv("APP_ENV") == "development" {
|
||||
log.Println("Loading `" + envFileDev + "`")
|
||||
return godotenv.Load(envFileDev)
|
||||
+ } else if os.Getenv("APP_ENV") == "nixos" {
|
||||
+ return nil
|
||||
} else {
|
||||
if _, err := os.Stat("./web/build"); os.IsNotExist(err) {
|
||||
return noBuildDirectoryErr
|
69
pkgs/by-name/br/broadcast-box/package.nix
Normal file
69
pkgs/by-name/br/broadcast-box/package.nix
Normal file
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
lib,
|
||||
nixosTests,
|
||||
fetchFromGitHub,
|
||||
buildNpmPackage,
|
||||
buildGoModule,
|
||||
}:
|
||||
let
|
||||
name = "broadcast-box";
|
||||
version = "0-unstable-2025-06-04";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
repo = "broadcast-box";
|
||||
owner = "Glimesh";
|
||||
rev = "a091f147f750759084a2c9d25a12e815e2feebf8";
|
||||
hash = "sha256-Evhye+DYtFM/VjxqmhH5kU32khvEFUxTUgH9DXytIbo=";
|
||||
};
|
||||
|
||||
frontend = buildNpmPackage {
|
||||
inherit version;
|
||||
pname = "${name}-web";
|
||||
src = "${src}/web";
|
||||
npmDepsHash = "sha256-e1cCezmF20Q6JEXwPb1asRSXuC/GGaR+ImvrTabLl5c=";
|
||||
preBuild = ''
|
||||
# The VITE_API_PATH environment variable is needed
|
||||
cp "${src}/.env.production" ../
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r build $out
|
||||
'';
|
||||
};
|
||||
in
|
||||
buildGoModule {
|
||||
inherit version src frontend;
|
||||
pname = name;
|
||||
vendorHash = "sha256-Jpee7UmG9AB9SOoTv2fPP2l5BmkDPPdciGFu9Naq9h8=";
|
||||
proxyVendor = true; # fixes darwin/linux hash mismatch
|
||||
|
||||
patches = [ ./allow-no-env.patch ];
|
||||
postPatch = ''
|
||||
substituteInPlace main.go \
|
||||
--replace-fail './web/build' '${placeholder "out"}/share'
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share
|
||||
cp -r $frontend/build/* $out/share
|
||||
|
||||
install -Dm755 $GOPATH/bin/broadcast-box -t $out/bin
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) broadcast-box;
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "WebRTC broadcast server";
|
||||
homepage = "https://github.com/Glimesh/broadcast-box";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ JManch ];
|
||||
platforms = lib.platforms.unix;
|
||||
mainProgram = "broadcast-box";
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue