at 22.05-pre 6.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 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 {}; 11 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 ''; 23in 24 { 25 options = { 26 services.mirakurun = { 27 enable = mkEnableOption mirakurun.meta.description; 28 29 port = mkOption { 30 type = with types; nullOr port; 31 default = 40772; 32 description = '' 33 Port to listen on. If <literal>null</literal>, it won't listen on 34 any port. 35 ''; 36 }; 37 38 openFirewall = mkOption { 39 type = types.bool; 40 default = false; 41 description = '' 42 Open ports in the firewall for Mirakurun. 43 44 <warning> 45 <para> 46 Exposing Mirakurun to the open internet is generally advised 47 against. Only use it inside a trusted local network, or 48 consider putting it behind a VPN if you want remote access. 49 </para> 50 </warning> 51 ''; 52 }; 53 54 unixSocket = mkOption { 55 type = with types; nullOr path; 56 default = "/var/run/mirakurun/mirakurun.sock"; 57 description = '' 58 Path to unix socket to listen on. If <literal>null</literal>, it 59 won't listen on any unix sockets. 60 ''; 61 }; 62 63 allowSmartCardAccess = mkOption { 64 type = types.bool; 65 default = true; 66 description = '' 67 Install polkit rules to allow Mirakurun to access smart card readers 68 which is commonly used along with tuner devices. 69 ''; 70 }; 71 72 serverSettings = mkOption { 73 type = settingsFmt.type; 74 default = {}; 75 example = literalExpression '' 76 { 77 highWaterMark = 25165824; 78 overflowTimeLimit = 30000; 79 }; 80 ''; 81 description = '' 82 Options for server.yml. 83 84 Documentation: 85 <link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/> 86 ''; 87 }; 88 89 tunerSettings = mkOption { 90 type = with types; nullOr settingsFmt.type; 91 default = null; 92 example = literalExpression '' 93 [ 94 { 95 name = "tuner-name"; 96 types = [ "GR" "BS" "CS" "SKY" ]; 97 dvbDevicePath = "/dev/dvb/adapterX/dvrX"; 98 } 99 ]; 100 ''; 101 description = '' 102 Options which are added to tuners.yml. If none is specified, it will 103 automatically be generated at runtime. 104 105 Documentation: 106 <link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/> 107 ''; 108 }; 109 110 channelSettings = mkOption { 111 type = with types; nullOr settingsFmt.type; 112 default = null; 113 example = literalExpression '' 114 [ 115 { 116 name = "channel"; 117 types = "GR"; 118 channel = "0"; 119 } 120 ]; 121 ''; 122 description = '' 123 Options which are added to channels.yml. If none is specified, it 124 will automatically be generated at runtime. 125 126 Documentation: 127 <link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/> 128 ''; 129 }; 130 }; 131 }; 132 133 config = mkIf cfg.enable { 134 environment.systemPackages = [ mirakurun ] ++ optional cfg.allowSmartCardAccess polkitRule; 135 environment.etc = { 136 "mirakurun/server.yml".source = settingsFmt.generate "server.yml" cfg.serverSettings; 137 "mirakurun/tuners.yml" = mkIf (cfg.tunerSettings != null) { 138 source = settingsFmt.generate "tuners.yml" cfg.tunerSettings; 139 mode = "0644"; 140 user = username; 141 group = groupname; 142 }; 143 "mirakurun/channels.yml" = mkIf (cfg.channelSettings != null) { 144 source = settingsFmt.generate "channels.yml" cfg.channelSettings; 145 mode = "0644"; 146 user = username; 147 group = groupname; 148 }; 149 }; 150 151 networking.firewall = mkIf cfg.openFirewall { 152 allowedTCPPorts = mkIf (cfg.port != null) [ cfg.port ]; 153 }; 154 155 users.users.mirakurun = { 156 description = "Mirakurun user"; 157 group = "video"; 158 isSystemUser = true; 159 }; 160 161 services.mirakurun.serverSettings = { 162 logLevel = mkDefault 2; 163 path = mkIf (cfg.unixSocket != null) cfg.unixSocket; 164 port = mkIf (cfg.port != null) cfg.port; 165 }; 166 167 systemd.tmpfiles.rules = [ 168 "d '/etc/mirakurun' - ${username} ${groupname} - -" 169 ]; 170 171 systemd.services.mirakurun = { 172 description = mirakurun.meta.description; 173 wantedBy = [ "multi-user.target" ]; 174 after = [ "network.target" ]; 175 serviceConfig = { 176 ExecStart = "${mirakurun}/bin/mirakurun-start"; 177 User = username; 178 Group = groupname; 179 RuntimeDirectory="mirakurun"; 180 StateDirectory="mirakurun"; 181 Nice = -10; 182 IOSchedulingClass = "realtime"; 183 IOSchedulingPriority = 7; 184 }; 185 186 environment = { 187 SERVER_CONFIG_PATH = "/etc/mirakurun/server.yml"; 188 TUNERS_CONFIG_PATH = "/etc/mirakurun/tuners.yml"; 189 CHANNELS_CONFIG_PATH = "/etc/mirakurun/channels.yml"; 190 SERVICES_DB_PATH = "/var/lib/mirakurun/services.json"; 191 PROGRAMS_DB_PATH = "/var/lib/mirakurun/programs.json"; 192 NODE_ENV = "production"; 193 }; 194 195 restartTriggers = let 196 getconf = target: config.environment.etc."mirakurun/${target}.yml".source; 197 targets = [ 198 "server" 199 ] ++ optional (cfg.tunerSettings != null) "tuners" 200 ++ optional (cfg.channelSettings != null) "channels"; 201 in (map getconf targets); 202 }; 203 }; 204 }