1{ pkgs, lib, config, utils, ... }:
2
3with lib;
4
5let
6 cfg = config.services.gmediarender;
7in
8{
9 options.services.gmediarender = {
10 enable = mkEnableOption "the gmediarender DLNA renderer";
11
12 audioDevice = mkOption {
13 type = types.nullOr types.str;
14 default = null;
15 description = ''
16 The audio device to use.
17 '';
18 };
19
20 audioSink = mkOption {
21 type = types.nullOr types.str;
22 default = null;
23 description = ''
24 The audio sink to use.
25 '';
26 };
27
28 friendlyName = mkOption {
29 type = types.nullOr types.str;
30 default = null;
31 description = ''
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 = ''
40 A default volume attenuation (in dB) for the endpoint.
41 '';
42 };
43
44 package = mkPackageOption pkgs "gmediarender" {
45 default = "gmrender-resurrect";
46 };
47
48 port = mkOption {
49 type = types.nullOr types.port;
50 default = null;
51 description = "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 = ''
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 wants = [ "network-online.target" ];
68 after = [ "network-online.target" ];
69 wantedBy = [ "multi-user.target" ];
70 description = "gmediarender server daemon";
71 environment = {
72 XDG_CACHE_HOME = "%t/gmediarender";
73 };
74 serviceConfig = {
75 DynamicUser = true;
76 User = "gmediarender";
77 Group = "gmediarender";
78 SupplementaryGroups = [ "audio" ];
79 ExecStart =
80 "${cfg.package}/bin/gmediarender " +
81 optionalString (cfg.audioDevice != null) ("--gstout-audiodevice=${utils.escapeSystemdExecArg cfg.audioDevice} ") +
82 optionalString (cfg.audioSink != null) ("--gstout-audiosink=${utils.escapeSystemdExecArg cfg.audioSink} ") +
83 optionalString (cfg.friendlyName != null) ("--friendly-name=${utils.escapeSystemdExecArg cfg.friendlyName} ") +
84 optionalString (cfg.initialVolume != 0) ("--initial-volume=${toString cfg.initialVolume} ") +
85 optionalString (cfg.port != null) ("--port=${toString cfg.port} ") +
86 optionalString (cfg.uuid != null) ("--uuid=${utils.escapeSystemdExecArg cfg.uuid} ");
87 Restart = "always";
88 RuntimeDirectory = "gmediarender";
89
90 # Security options:
91 CapabilityBoundingSet = "";
92 LockPersonality = true;
93 MemoryDenyWriteExecute = true;
94 NoNewPrivileges = true;
95 # PrivateDevices = true;
96 PrivateTmp = true;
97 PrivateUsers = true;
98 ProcSubset = "pid";
99 ProtectClock = true;
100 ProtectControlGroups = true;
101 ProtectHome = true;
102 ProtectHostname = true;
103 ProtectKernelLogs = true;
104 ProtectKernelModules = true;
105 ProtectKernelTunables = true;
106 ProtectProc = "invisible";
107 RestrictNamespaces = true;
108 RestrictRealtime = true;
109 RestrictSUIDSGID = true;
110 SystemCallArchitectures = "native";
111 SystemCallFilter = [ "@system-service" "~@privileged" ];
112 UMask = 066;
113 };
114 };
115 };
116 };
117}