1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.hqplayerd;
7 pkg = pkgs.hqplayerd;
8 # XXX: This is hard-coded in the distributed binary, don't try to change it.
9 stateDir = "/var/lib/hqplayer";
10 configDir = "/etc/hqplayer";
11in
12{
13 options = {
14 services.hqplayerd = {
15 enable = mkEnableOption "HQPlayer Embedded";
16
17 auth = {
18 username = mkOption {
19 type = types.nullOr types.str;
20 default = null;
21 description = ''
22 Username used for HQPlayer's WebUI.
23
24 Without this you will need to manually create the credentials after
25 first start by going to http://your.ip/8088/auth
26 '';
27 };
28
29 password = mkOption {
30 type = types.nullOr types.str;
31 default = null;
32 description = ''
33 Password used for HQPlayer's WebUI.
34
35 Without this you will need to manually create the credentials after
36 first start by going to http://your.ip/8088/auth
37 '';
38 };
39 };
40
41 licenseFile = mkOption {
42 type = types.nullOr types.path;
43 default = null;
44 description = ''
45 Path to the HQPlayer license key file.
46
47 Without this, the service will run in trial mode and restart every 30
48 minutes.
49 '';
50 };
51
52 openFirewall = mkOption {
53 type = types.bool;
54 default = false;
55 description = ''
56 Opens ports needed for the WebUI and controller API.
57 '';
58 };
59
60 config = mkOption {
61 type = types.nullOr types.lines;
62 default = null;
63 description = ''
64 HQplayer daemon configuration, written to /etc/hqplayer/hqplayerd.xml.
65
66 Refer to share/doc/hqplayerd/readme.txt in the hqplayerd derivation for possible values.
67 '';
68 };
69 };
70 };
71
72 config = mkIf cfg.enable {
73 assertions = [
74 {
75 assertion = (cfg.auth.username != null -> cfg.auth.password != null)
76 && (cfg.auth.password != null -> cfg.auth.username != null);
77 message = "You must set either both services.hqplayer.auth.username and password, or neither.";
78 }
79 ];
80
81 environment = {
82 etc = {
83 "hqplayer/hqplayerd.xml" = mkIf (cfg.config != null) { source = pkgs.writeText "hqplayerd.xml" cfg.config; };
84 "hqplayer/hqplayerd4-key.xml" = mkIf (cfg.licenseFile != null) { source = cfg.licenseFile; };
85 "modules-load.d/taudio2.conf".source = "${pkg}/etc/modules-load.d/taudio2.conf";
86 };
87 systemPackages = [ pkg ];
88 };
89
90 networking.firewall = mkIf cfg.openFirewall {
91 allowedTCPPorts = [ 8088 4321 ];
92 };
93
94 services.udev.packages = [ pkg ];
95
96 systemd = {
97 tmpfiles.rules = [
98 "d ${configDir} 0755 hqplayer hqplayer - -"
99 "d ${stateDir} 0755 hqplayer hqplayer - -"
100 "d ${stateDir}/home 0755 hqplayer hqplayer - -"
101 ];
102
103 packages = [ pkg ];
104
105 services.hqplayerd = {
106 wantedBy = [ "multi-user.target" ];
107 after = [ "systemd-tmpfiles-setup.service" ];
108
109 environment.HOME = "${stateDir}/home";
110
111 unitConfig.ConditionPathExists = [ configDir stateDir ];
112
113 restartTriggers = optionals (cfg.config != null) [ config.environment.etc."hqplayer/hqplayerd.xml".source ];
114
115 preStart = ''
116 cp -r "${pkg}/var/lib/hqplayer/web" "${stateDir}"
117 chmod -R u+wX "${stateDir}/web"
118
119 if [ ! -f "${configDir}/hqplayerd.xml" ]; then
120 echo "creating initial config file"
121 install -m 0644 "${pkg}/etc/hqplayer/hqplayerd.xml" "${configDir}/hqplayerd.xml"
122 fi
123 '' + optionalString (cfg.auth.username != null && cfg.auth.password != null) ''
124 ${pkg}/bin/hqplayerd -s ${cfg.auth.username} ${cfg.auth.password}
125 '';
126 };
127 };
128
129 users.groups = {
130 hqplayer.gid = config.ids.gids.hqplayer;
131 };
132
133 users.users = {
134 hqplayer = {
135 description = "hqplayer daemon user";
136 extraGroups = [ "audio" ];
137 group = "hqplayer";
138 uid = config.ids.uids.hqplayer;
139 };
140 };
141 };
142}