at master 2.6 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 utils, 6 ... 7}: 8let 9 inherit (lib) 10 getExe 11 mkEnableOption 12 mkIf 13 mkOption 14 mkPackageOption 15 optionals 16 types 17 ; 18 19 cfg = config.services.ustreamer; 20in 21{ 22 options.services.ustreamer = { 23 enable = mkEnableOption "µStreamer, a lightweight MJPEG-HTTP streamer"; 24 25 package = mkPackageOption pkgs "ustreamer" { }; 26 27 autoStart = mkOption { 28 description = '' 29 Wether to start µStreamer on boot. Disabling this will use socket 30 activation. The service will stop gracefully after some inactivity. 31 Disabling this will set `--exit-on-no-clients=300` 32 ''; 33 type = types.bool; 34 default = true; 35 example = false; 36 }; 37 38 listenAddress = mkOption { 39 description = '' 40 Address to expose the HTTP server. This accepts values for 41 ListenStream= defined in {manpage}`systemd.socket(5)` 42 ''; 43 type = types.str; 44 default = "0.0.0.0:8080"; 45 example = "/run/ustreamer.sock"; 46 }; 47 48 device = mkOption { 49 description = '' 50 The v4l2 device to stream. 51 ''; 52 type = types.path; 53 default = "/dev/video0"; 54 example = "/dev/v4l/by-id/usb-0000_Dummy_abcdef-video-index0"; 55 }; 56 57 extraArgs = mkOption { 58 description = '' 59 Extra arguments to pass to `ustreamer`. See {manpage}`ustreamer(1)` 60 ''; 61 type = with types; listOf str; 62 default = [ ]; 63 example = [ "--resolution=1920x1080" ]; 64 }; 65 }; 66 67 config = mkIf cfg.enable { 68 services.ustreamer.extraArgs = [ 69 "--device=${cfg.device}" 70 ] 71 ++ optionals (!cfg.autoStart) [ 72 "--exit-on-no-clients=300" 73 ]; 74 75 systemd.services."ustreamer" = { 76 description = "µStreamer, a lightweight MJPEG-HTTP streamer"; 77 after = [ "network.target" ]; 78 requires = [ "ustreamer.socket" ]; 79 wantedBy = mkIf cfg.autoStart [ "multi-user.target" ]; 80 serviceConfig = { 81 ExecStart = utils.escapeSystemdExecArgs ( 82 [ 83 (getExe cfg.package) 84 "--systemd" 85 ] 86 ++ cfg.extraArgs 87 ); 88 Restart = if cfg.autoStart then "always" else "on-failure"; 89 90 DynamicUser = true; 91 SupplementaryGroups = [ "video" ]; 92 93 NoNewPrivileges = true; 94 ProcSubset = "pid"; 95 ProtectProc = "noaccess"; 96 ProtectClock = "yes"; 97 DeviceAllow = [ cfg.device ]; 98 }; 99 }; 100 101 systemd.sockets."ustreamer" = { 102 wantedBy = [ "sockets.target" ]; 103 partOf = [ "ustreamer.service" ]; 104 socketConfig = { 105 ListenStream = cfg.listenAddress; 106 }; 107 }; 108 }; 109}