diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 5ce521657c93..3c86eb2f1a6e 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -42,6 +42,8 @@ - [Bat](https://github.com/sharkdp/bat), a {manpage}`cat(1)` clone with wings. Available as [programs.bat](options.html#opt-programs.bat). +- [µStreamer](https://github.com/pikvm/ustreamer), a lightweight MJPEG-HTTP streamer. Available as [services.ustreamer](options.html#opt-services.ustreamer). + - [Whoogle Search](https://github.com/benbusby/whoogle-search), a self-hosted, ad-free, privacy-respecting metasearch engine. Available as [services.whoogle-search](options.html#opt-services.whoogle-search.enable). - [agorakit](https://github.com/agorakit/agorakit), an organization tool for citizens' collectives. Available with [services.agorakit](options.html#opt-services.agorakit.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 2bfb963c19df..c06f8601830b 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1416,6 +1416,7 @@ ./services/video/mirakurun.nix ./services/video/photonvision.nix ./services/video/mediamtx.nix + ./services/video/ustreamer.nix ./services/video/v4l2-relayd.nix ./services/video/wivrn.nix ./services/wayland/cage.nix diff --git a/nixos/modules/services/video/ustreamer.nix b/nixos/modules/services/video/ustreamer.nix new file mode 100644 index 000000000000..d32818fa3ab3 --- /dev/null +++ b/nixos/modules/services/video/ustreamer.nix @@ -0,0 +1,110 @@ +{ + config, + lib, + pkgs, + utils, + ... +}: +let + inherit (lib) + getExe + mkEnableOption + mkIf + mkOption + mkPackageOption + optionals + types + ; + + cfg = config.services.ustreamer; +in +{ + options.services.ustreamer = { + enable = mkEnableOption "µStreamer, a lightweight MJPEG-HTTP streamer"; + + package = mkPackageOption pkgs "ustreamer" { }; + + autoStart = mkOption { + description = '' + Wether to start µStreamer on boot. Disabling this will use socket + activation. The service will stop gracefully after some inactivity. + Disabling this will set `--exit-on-no-clients=300` + ''; + type = types.bool; + default = true; + example = false; + }; + + listenAddress = mkOption { + description = '' + Address to expose the HTTP server. This accepts values for + ListenStream= defined in {manpage}`systemd.socket(5)` + ''; + type = types.str; + default = "0.0.0.0:8080"; + example = "/run/ustreamer.sock"; + }; + + device = mkOption { + description = '' + The v4l2 device to stream. + ''; + type = types.path; + default = "/dev/video0"; + example = "/dev/v4l/by-id/usb-0000_Dummy_abcdef-video-index0"; + }; + + extraArgs = mkOption { + description = '' + Extra arguments to pass to `ustreamer`. See {manpage}`ustreamer(1)` + ''; + type = with types; listOf str; + default = [ ]; + example = [ "--resolution=1920x1080" ]; + }; + }; + + config = mkIf cfg.enable { + services.ustreamer.extraArgs = + [ + "--device=${cfg.device}" + ] + ++ optionals (!cfg.autoStart) [ + "--exit-on-no-clients=300" + ]; + + systemd.services."ustreamer" = { + description = "µStreamer, a lightweight MJPEG-HTTP streamer"; + after = [ "network.target" ]; + requires = [ "ustreamer.socket" ]; + wantedBy = mkIf cfg.autoStart [ "multi-user.target" ]; + serviceConfig = { + ExecStart = utils.escapeSystemdExecArgs ( + [ + (getExe cfg.package) + "--systemd" + ] + ++ cfg.extraArgs + ); + Restart = if cfg.autoStart then "always" else "on-failure"; + + DynamicUser = true; + SupplementaryGroups = [ "video" ]; + + NoNewPrivileges = true; + ProcSubset = "pid"; + ProtectProc = "noaccess"; + ProtectClock = "yes"; + DeviceAllow = [ cfg.device ]; + }; + }; + + systemd.sockets."ustreamer" = { + wantedBy = [ "sockets.target" ]; + partOf = [ "ustreamer.service" ]; + socketConfig = { + ListenStream = cfg.listenAddress; + }; + }; + }; +}