grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / video / mirakurun.nix
blobbdd30805dbe83a92912566d81b21d13e31c6260d
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.mirakurun;
7   mirakurun = pkgs.mirakurun;
8   username = config.users.users.mirakurun.name;
9   groupname = config.users.users.mirakurun.group;
10   settingsFmt = pkgs.formats.yaml {};
12   polkitRule = pkgs.writeTextDir "share/polkit-1/rules.d/10-mirakurun.rules" ''
13     polkit.addRule(function (action, subject) {
14       if (
15         (action.id == "org.debian.pcsc-lite.access_pcsc" ||
16           action.id == "org.debian.pcsc-lite.access_card") &&
17         subject.user == "${username}"
18       ) {
19         return polkit.Result.YES;
20       }
21     });
22   '';
24   {
25     options = {
26       services.mirakurun = {
27         enable = mkEnableOption "the Mirakurun DVR Tuner Server";
29         port = mkOption {
30           type = with types; nullOr port;
31           default = 40772;
32           description = ''
33             Port to listen on. If `null`, it won't listen on
34             any port.
35           '';
36         };
38         openFirewall = mkOption {
39           type = types.bool;
40           default = false;
41           description = ''
42             Open ports in the firewall for Mirakurun.
44             ::: {.warning}
45             Exposing Mirakurun to the open internet is generally advised
46             against. Only use it inside a trusted local network, or
47             consider putting it behind a VPN if you want remote access.
48             :::
49           '';
50         };
52         unixSocket = mkOption {
53           type = with types; nullOr path;
54           default = "/var/run/mirakurun/mirakurun.sock";
55           description = ''
56             Path to unix socket to listen on. If `null`, it
57             won't listen on any unix sockets.
58           '';
59         };
61         allowSmartCardAccess = mkOption {
62           type = types.bool;
63           default = true;
64           description = ''
65             Install polkit rules to allow Mirakurun to access smart card readers
66             which is commonly used along with tuner devices.
67           '';
68         };
70         serverSettings = mkOption {
71           type = settingsFmt.type;
72           default = {};
73           example = literalExpression ''
74             {
75               highWaterMark = 25165824;
76               overflowTimeLimit = 30000;
77             };
78           '';
79           description = ''
80             Options for server.yml.
82             Documentation:
83             <https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md>
84           '';
85         };
87         tunerSettings = mkOption {
88           type = with types; nullOr settingsFmt.type;
89           default = null;
90           example = literalExpression ''
91             [
92               {
93                 name = "tuner-name";
94                 types = [ "GR" "BS" "CS" "SKY" ];
95                 dvbDevicePath = "/dev/dvb/adapterX/dvrX";
96               }
97             ];
98           '';
99           description = ''
100             Options which are added to tuners.yml. If none is specified, it will
101             automatically be generated at runtime.
103             Documentation:
104             <https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md>
105           '';
106         };
108         channelSettings = mkOption {
109           type = with types; nullOr settingsFmt.type;
110           default = null;
111           example = literalExpression ''
112             [
113               {
114                 name = "channel";
115                 types = "GR";
116                 channel = "0";
117               }
118             ];
119           '';
120           description = ''
121             Options which are added to channels.yml. If none is specified, it
122             will automatically be generated at runtime.
124             Documentation:
125             <https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md>
126           '';
127         };
128       };
129     };
131     config = mkIf cfg.enable {
132       environment.systemPackages = [ mirakurun ] ++ optional cfg.allowSmartCardAccess polkitRule;
133       environment.etc = {
134         "mirakurun/server.yml".source = settingsFmt.generate "server.yml" cfg.serverSettings;
135         "mirakurun/tuners.yml" = mkIf (cfg.tunerSettings != null) {
136           source = settingsFmt.generate "tuners.yml" cfg.tunerSettings;
137           mode = "0644";
138           user = username;
139           group = groupname;
140         };
141         "mirakurun/channels.yml" = mkIf (cfg.channelSettings != null) {
142           source = settingsFmt.generate "channels.yml" cfg.channelSettings;
143           mode = "0644";
144           user = username;
145           group = groupname;
146         };
147       };
149       networking.firewall = mkIf cfg.openFirewall {
150         allowedTCPPorts = mkIf (cfg.port != null) [ cfg.port ];
151       };
153       users.users.mirakurun = {
154         description = "Mirakurun user";
155         group = "video";
156         isSystemUser = true;
158         # NPM insists on creating ~/.npm
159         home = "/var/cache/mirakurun";
160       };
162       services.mirakurun.serverSettings = {
163         logLevel = mkDefault 2;
164         path = mkIf (cfg.unixSocket != null) cfg.unixSocket;
165         port = mkIf (cfg.port != null) cfg.port;
166       };
168       systemd.tmpfiles.settings."10-mirakurun"."/etc/mirakurun".d = {
169         user = username;
170         group = groupname;
171       };
173       systemd.services.mirakurun = {
174         description = mirakurun.meta.description;
175         wantedBy = [ "multi-user.target" ];
176         after = [ "network.target" ];
177         serviceConfig = {
178           ExecStart = "${mirakurun}/bin/mirakurun start";
179           User = username;
180           Group = groupname;
181           CacheDirectory = "mirakurun";
182           RuntimeDirectory="mirakurun";
183           StateDirectory="mirakurun";
184           Nice = -10;
185           IOSchedulingClass = "realtime";
186           IOSchedulingPriority = 7;
187         };
189         environment = {
190           SERVER_CONFIG_PATH = "/etc/mirakurun/server.yml";
191           TUNERS_CONFIG_PATH = "/etc/mirakurun/tuners.yml";
192           CHANNELS_CONFIG_PATH = "/etc/mirakurun/channels.yml";
193           SERVICES_DB_PATH = "/var/lib/mirakurun/services.json";
194           PROGRAMS_DB_PATH = "/var/lib/mirakurun/programs.json";
195           LOGO_DATA_DIR_PATH = "/var/lib/mirakurun/logos";
196           NODE_ENV = "production";
197         };
199         restartTriggers = let
200           getconf = target: config.environment.etc."mirakurun/${target}.yml".source;
201           targets = [
202             "server"
203           ] ++ optional (cfg.tunerSettings != null) "tuners"
204             ++ optional (cfg.channelSettings != null) "channels";
205         in (map getconf targets);
206       };
207     };
208   }