1{ pkgs, lib, config, utils, ... }:
2
3with lib;
4
5let
6 cfg = config.services.gmediarender;
7in
8{
9 options.services.gmediarender = {
10 enable = mkEnableOption (mdDoc "the gmediarender DLNA renderer");
11
12 audioDevice = mkOption {
13 type = types.nullOr types.str;
14 default = null;
15 description = mdDoc ''
16 The audio device to use.
17 '';
18 };
19
20 audioSink = mkOption {
21 type = types.nullOr types.str;
22 default = null;
23 description = mdDoc ''
24 The audio sink to use.
25 '';
26 };
27
28 friendlyName = mkOption {
29 type = types.nullOr types.str;
30 default = null;
31 description = mdDoc ''
32 A "friendly name" for identifying the endpoint.
33 '';
34 };
35
36 initialVolume = mkOption {
37 type = types.nullOr types.int;
38 default = 0;
39 description = mdDoc ''
40 A default volume attenuation (in dB) for the endpoint.
41 '';
42 };
43
44 package = mkPackageOptionMD pkgs "gmediarender" {
45 default = "gmrender-resurrect";
46 };
47
48 port = mkOption {
49 type = types.nullOr types.port;
50 default = null;
51 description = mdDoc "Port that will be used to accept client connections.";
52 };
53
54 uuid = mkOption {
55 type = types.nullOr types.str;
56 default = null;
57 description = mdDoc ''
58 A UUID for uniquely identifying the endpoint. If you have
59 multiple renderers on your network, you MUST set this.
60 '';
61 };
62 };
63
64 config = mkIf cfg.enable {
65 systemd = {
66 services.gmediarender = {
67 after = [ "network-online.target" ];
68 wantedBy = [ "multi-user.target" ];
69 description = "gmediarender server daemon";
70 environment = {
71 XDG_CACHE_HOME = "%t/gmediarender";
72 };
73 serviceConfig = {
74 DynamicUser = true;
75 User = "gmediarender";
76 Group = "gmediarender";
77 SupplementaryGroups = [ "audio" ];
78 ExecStart =
79 "${cfg.package}/bin/gmediarender " +
80 optionalString (cfg.audioDevice != null) ("--gstout-audiodevice=${utils.escapeSystemdExecArg cfg.audioDevice} ") +
81 optionalString (cfg.audioSink != null) ("--gstout-audiosink=${utils.escapeSystemdExecArg cfg.audioSink} ") +
82 optionalString (cfg.friendlyName != null) ("--friendly-name=${utils.escapeSystemdExecArg cfg.friendlyName} ") +
83 optionalString (cfg.initialVolume != 0) ("--initial-volume=${toString cfg.initialVolume} ") +
84 optionalString (cfg.port != null) ("--port=${toString cfg.port} ") +
85 optionalString (cfg.uuid != null) ("--uuid=${utils.escapeSystemdExecArg cfg.uuid} ");
86 Restart = "always";
87 RuntimeDirectory = "gmediarender";
88
89 # Security options:
90 CapabilityBoundingSet = "";
91 LockPersonality = true;
92 MemoryDenyWriteExecute = true;
93 NoNewPrivileges = true;
94 # PrivateDevices = true;
95 PrivateTmp = true;
96 PrivateUsers = true;
97 ProcSubset = "pid";
98 ProtectClock = true;
99 ProtectControlGroups = true;
100 ProtectHome = true;
101 ProtectHostname = true;
102 ProtectKernelLogs = true;
103 ProtectKernelModules = true;
104 ProtectKernelTunables = true;
105 ProtectProc = "invisible";
106 RestrictNamespaces = true;
107 RestrictRealtime = true;
108 RestrictSUIDSGID = true;
109 SystemCallArchitectures = "native";
110 SystemCallFilter = [ "@system-service" "~@privileged" ];
111 UMask = 066;
112 };
113 };
114 };
115 };
116}