diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index a7a31ba8576..a6839e02c4f 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -348,6 +348,7 @@ in #mailman = 316; # removed 2019-08-30 zigbee2mqtt = 317; # shadow = 318; # unused + hqplayer = 319; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -650,6 +651,7 @@ in #mailman = 316; # removed 2019-08-30 zigbee2mqtt = 317; shadow = 318; + hqplayer = 319; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4203c858272..64b0c83bbae 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -244,8 +244,9 @@ ./services/amqp/rabbitmq.nix ./services/audio/alsa.nix ./services/audio/botamusique.nix - ./services/audio/jack.nix + ./services/audio/hqplayerd.nix ./services/audio/icecast.nix + ./services/audio/jack.nix ./services/audio/jmusicbot.nix ./services/audio/liquidsoap.nix ./services/audio/mpd.nix diff --git a/nixos/modules/services/audio/hqplayerd.nix b/nixos/modules/services/audio/hqplayerd.nix new file mode 100644 index 00000000000..3a703c97c0f --- /dev/null +++ b/nixos/modules/services/audio/hqplayerd.nix @@ -0,0 +1,166 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.hqplayerd; + pkg = pkgs.hqplayerd; + # XXX: This is hard-coded in the distributed binary, don't try to change it. + stateDir = "/var/lib/hqplayer"; + configDir = "/etc/hqplayer"; +in +{ + options = { + services.hqplayerd = { + enable = mkEnableOption "HQPlayer Embedded"; + + licenseFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to the HQPlayer license key file. + + Without this, the service will run in trial mode and restart every 30 + minutes. + ''; + }; + + auth = { + username = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Username used for HQPlayer's WebUI. + + Without this you will need to manually create the credentials after + first start by going to http://your.ip/8088/auth + ''; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Password used for HQPlayer's WebUI. + + Without this you will need to manually create the credentials after + first start by going to http://your.ip/8088/auth + ''; + }; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Open TCP port 8088 in the firewall for the server. + ''; + }; + + user = mkOption { + type = types.str; + default = "hqplayer"; + description = '' + User account under which hqplayerd runs. + ''; + }; + + group = mkOption { + type = types.str; + default = "hqplayer"; + description = '' + Group account under which hqplayerd runs. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = (cfg.auth.username != null -> cfg.auth.password != null) + && (cfg.auth.password != null -> cfg.auth.username != null); + message = "You must set either both services.hqplayer.auth.username and password, or neither."; + } + ]; + + environment = { + etc = { + "hqplayer/hqplayerd4-key.xml" = mkIf (cfg.licenseFile != null) { source = cfg.licenseFile; }; + "modules-load.d/taudio2.conf".source = "${pkg}/etc/modules-load.d/taudio2.conf"; + }; + systemPackages = [ pkg ]; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ 8088 ]; + }; + + services.udev.packages = [ pkg ]; + + systemd = { + tmpfiles.rules = [ + "d ${configDir} 0755 ${cfg.user} ${cfg.group} - -" + "d ${stateDir} 0755 ${cfg.user} ${cfg.group} - -" + ]; + + services.hqplayerd = { + description = "HQPlayer daemon"; + wantedBy = [ "multi-user.target" ]; + requires = [ "network-online.target" "sound.target" "systemd-udev-settle.service" ]; + after = [ "network-online.target" "sound.target" "systemd-udev-settle.service" "local-fs.target" "remote-fs.target" "systemd-tmpfiles-setup.service" ]; + + unitConfig.ConditionPathExists = [ configDir stateDir ]; + + preStart = + let + blankCfg = pkgs.writeText "hqplayerd.xml" '' + + + + ''; + in + '' + cp -r "${pkg}/var/lib/hqplayer/web" "${stateDir}" + chmod -R u+wX "${stateDir}/web" + + if [ ! -f "${configDir}/hqplayerd.xml" ]; then + echo "creating blank config file" + install -m 0644 "${blankCfg}" "${configDir}/hqplayerd.xml" + fi + '' + optionalString (cfg.auth.username != null && cfg.auth.password != null) '' + ${pkg}/bin/hqplayerd -s ${cfg.auth.username} ${cfg.auth.password} + ''; + + serviceConfig = { + ExecStart = "${pkg}/bin/hqplayerd"; + + User = cfg.user; + Group = cfg.group; + + Restart = "on-failure"; + RestartSec = 5; + + Nice = -10; + IOSchedulingClass = "realtime"; + LimitMEMLOCK = "1G"; + LimitNICE = -10; + LimitRTPRIO = 98; + }; + }; + }; + + users.groups = mkIf (cfg.group == "hqplayer") { + hqplayer.gid = config.ids.gids.hqplayer; + }; + + users.users = mkIf (cfg.user == "hqplayer") { + hqplayer = { + description = "hqplayer daemon user"; + extraGroups = [ "audio" ]; + group = cfg.group; + uid = config.ids.uids.hqplayer; + }; + }; + }; +} diff --git a/pkgs/servers/hqplayerd/default.nix b/pkgs/servers/hqplayerd/default.nix index 594085d422e..76f8bde3e4e 100644 --- a/pkgs/servers/hqplayerd/default.nix +++ b/pkgs/servers/hqplayerd/default.nix @@ -17,11 +17,11 @@ stdenv.mkDerivation rec { pname = "hqplayerd"; - version = "4.24.2-63"; + version = "4.25.0-64"; src = fetchurl { url = "https://www.signalyst.eu/bins/${pname}/fc34/${pname}-${version}.fc34.x86_64.rpm"; - sha256 = "sha256-6JUgHDO+S73n/IVQhkmC0Nw4GQVzTLtiBbz/wZiflRg="; + sha256 = "sha256-KLP7g1SQzVKu9Hnptb6s0FwmLSjhlAINJoJskja+bDM="; }; unpackPhase = '' @@ -70,8 +70,8 @@ stdenv.mkDerivation rec { cp ./usr/share/doc/hqplayerd/* $out/share/doc/hqplayerd # misc service support files - mkdir -p $out/var/lib/hqplayerd - cp -r ./var/lib/hqplayer/web $out/var/lib/hqplayer + mkdir -p $out/var/lib/hqplayer + cp -r ./var/lib/hqplayer/web $out/var/lib/hqplayer/web runHook postInstall '';