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