diff options
Diffstat (limited to 'nixos/modules/services/video/mirakurun.nix')
-rw-r--r-- | nixos/modules/services/video/mirakurun.nix | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/nixos/modules/services/video/mirakurun.nix b/nixos/modules/services/video/mirakurun.nix new file mode 100644 index 00000000000..35303b2332c --- /dev/null +++ b/nixos/modules/services/video/mirakurun.nix @@ -0,0 +1,204 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.mirakurun; + mirakurun = pkgs.mirakurun; + username = config.users.users.mirakurun.name; + groupname = config.users.users.mirakurun.group; + settingsFmt = pkgs.formats.yaml {}; + + polkitRule = pkgs.writeTextDir "share/polkit-1/rules.d/10-mirakurun.rules" '' + polkit.addRule(function (action, subject) { + if ( + (action.id == "org.debian.pcsc-lite.access_pcsc" || + action.id == "org.debian.pcsc-lite.access_card") && + subject.user == "${username}" + ) { + return polkit.Result.YES; + } + }); + ''; +in + { + options = { + services.mirakurun = { + enable = mkEnableOption "the Mirakurun DVR Tuner Server"; + + port = mkOption { + type = with types; nullOr port; + default = 40772; + description = '' + Port to listen on. If <literal>null</literal>, it won't listen on + any port. + ''; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Open ports in the firewall for Mirakurun. + + <warning> + <para> + Exposing Mirakurun to the open internet is generally advised + against. Only use it inside a trusted local network, or + consider putting it behind a VPN if you want remote access. + </para> + </warning> + ''; + }; + + unixSocket = mkOption { + type = with types; nullOr path; + default = "/var/run/mirakurun/mirakurun.sock"; + description = '' + Path to unix socket to listen on. If <literal>null</literal>, it + won't listen on any unix sockets. + ''; + }; + + allowSmartCardAccess = mkOption { + type = types.bool; + default = true; + description = '' + Install polkit rules to allow Mirakurun to access smart card readers + which is commonly used along with tuner devices. + ''; + }; + + serverSettings = mkOption { + type = settingsFmt.type; + default = {}; + example = literalExpression '' + { + highWaterMark = 25165824; + overflowTimeLimit = 30000; + }; + ''; + description = '' + Options for server.yml. + + Documentation: + <link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/> + ''; + }; + + tunerSettings = mkOption { + type = with types; nullOr settingsFmt.type; + default = null; + example = literalExpression '' + [ + { + name = "tuner-name"; + types = [ "GR" "BS" "CS" "SKY" ]; + dvbDevicePath = "/dev/dvb/adapterX/dvrX"; + } + ]; + ''; + description = '' + Options which are added to tuners.yml. If none is specified, it will + automatically be generated at runtime. + + Documentation: + <link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/> + ''; + }; + + channelSettings = mkOption { + type = with types; nullOr settingsFmt.type; + default = null; + example = literalExpression '' + [ + { + name = "channel"; + types = "GR"; + channel = "0"; + } + ]; + ''; + description = '' + Options which are added to channels.yml. If none is specified, it + will automatically be generated at runtime. + + Documentation: + <link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/> + ''; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ mirakurun ] ++ optional cfg.allowSmartCardAccess polkitRule; + environment.etc = { + "mirakurun/server.yml".source = settingsFmt.generate "server.yml" cfg.serverSettings; + "mirakurun/tuners.yml" = mkIf (cfg.tunerSettings != null) { + source = settingsFmt.generate "tuners.yml" cfg.tunerSettings; + mode = "0644"; + user = username; + group = groupname; + }; + "mirakurun/channels.yml" = mkIf (cfg.channelSettings != null) { + source = settingsFmt.generate "channels.yml" cfg.channelSettings; + mode = "0644"; + user = username; + group = groupname; + }; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = mkIf (cfg.port != null) [ cfg.port ]; + }; + + users.users.mirakurun = { + description = "Mirakurun user"; + group = "video"; + isSystemUser = true; + }; + + services.mirakurun.serverSettings = { + logLevel = mkDefault 2; + path = mkIf (cfg.unixSocket != null) cfg.unixSocket; + port = mkIf (cfg.port != null) cfg.port; + }; + + systemd.tmpfiles.rules = [ + "d '/etc/mirakurun' - ${username} ${groupname} - -" + ]; + + systemd.services.mirakurun = { + description = mirakurun.meta.description; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = "${mirakurun}/bin/mirakurun-start"; + User = username; + Group = groupname; + RuntimeDirectory="mirakurun"; + StateDirectory="mirakurun"; + Nice = -10; + IOSchedulingClass = "realtime"; + IOSchedulingPriority = 7; + }; + + environment = { + SERVER_CONFIG_PATH = "/etc/mirakurun/server.yml"; + TUNERS_CONFIG_PATH = "/etc/mirakurun/tuners.yml"; + CHANNELS_CONFIG_PATH = "/etc/mirakurun/channels.yml"; + SERVICES_DB_PATH = "/var/lib/mirakurun/services.json"; + PROGRAMS_DB_PATH = "/var/lib/mirakurun/programs.json"; + NODE_ENV = "production"; + }; + + restartTriggers = let + getconf = target: config.environment.etc."mirakurun/${target}.yml".source; + targets = [ + "server" + ] ++ optional (cfg.tunerSettings != null) "tuners" + ++ optional (cfg.channelSettings != null) "channels"; + in (map getconf targets); + }; + }; + } |