summaryrefslogtreecommitdiff
path: root/custom
diff options
context:
space:
mode:
Diffstat (limited to 'custom')
-rw-r--r--custom/mpd.nix199
1 files changed, 199 insertions, 0 deletions
diff --git a/custom/mpd.nix b/custom/mpd.nix
new file mode 100644
index 00000000..8df2a955
--- /dev/null
+++ b/custom/mpd.nix
@@ -0,0 +1,199 @@
1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 name = "mpd";
8
9 uid = config.ids.uids.mpd;
10 gid = config.ids.gids.mpd;
11 cfg = config.services.mpd;
12
13 mpdConf = pkgs.writeText "mpd.conf" ''
14 music_directory "${cfg.musicDirectory}"
15 playlist_directory "${cfg.playlistDirectory}"
16 db_file "${cfg.dbFile}"
17 state_file "${cfg.dataDir}/state"
18 sticker_file "${cfg.dataDir}/sticker.sql"
19 log_file "syslog"
20 user "${cfg.user}"
21 group "${cfg.group}"
22
23 ${optionalString (cfg.network.listenAddress != "any") ''bind_to_address "${cfg.network.listenAddress}"''}
24 ${optionalString (cfg.network.port != 6600) ''port "${toString cfg.network.port}"''}
25
26 ${cfg.extraConfig}
27 '';
28
29 tcpAddress = {
30 options = {
31 address = mkOption {
32 type = with types; either (enum ["any"]) str;
33 example = "localhost";
34 };
35
36 port = mkOption {
37 type = types.int;
38 default = 6600;
39 };
40 };
41 };
42
43 listenStream = arg: if isString arg then arg else (optionalString (arg.address != "any") (arg.address + ":")) + toString arg.port;
44 bindAddress = arg: if isString arg then arg
45 else arg.address + ":" + toString arg.port;
46
47in {
48
49 disabledModules = [ "services/audio/mpd.nix" ];
50
51 ###### interface
52
53 options = {
54
55 services.mpd = {
56
57 enable = mkOption {
58 type = types.bool;
59 default = false;
60 description = ''
61 Whether to enable MPD, the music player daemon.
62 '';
63 };
64
65 startWhenNeeded = mkOption {
66 type = types.bool;
67 default = false;
68 description = ''
69 If set, <command>mpd</command> is socket-activated; that
70 is, instead of having it permanently running as a daemon,
71 systemd will start it on the first incoming connection.
72 '';
73 };
74
75 musicDirectory = mkOption {
76 type = with types; either path str;
77 default = "${cfg.dataDir}/music";
78 defaultText = ''''${dataDir}/music'';
79 description = ''
80 The directory where mpd reads music from.
81 '';
82 };
83
84 playlistDirectory = mkOption {
85 type = types.path;
86 default = "${cfg.dataDir}/playlists";
87 defaultText = ''''${dataDir}/playlists'';
88 description = ''
89 The directory where mpd stores playlists.
90 '';
91 };
92
93 extraConfig = mkOption {
94 type = types.lines;
95 default = "";
96 description = ''
97 Extra directives added to to the end of MPD's configuration file,
98 mpd.conf. Basic configuration like file location and uid/gid
99 is added automatically to the beginning of the file. For available
100 options see <literal>man 5 mpd.conf</literal>'.
101 '';
102 };
103
104 dataDir = mkOption {
105 type = types.path;
106 default = "/var/lib/${name}";
107 description = ''
108 The directory where MPD stores its state, tag cache,
109 playlists etc.
110 '';
111 };
112
113 user = mkOption {
114 type = types.str;
115 default = name;
116 description = "User account under which MPD runs.";
117 };
118
119 group = mkOption {
120 type = types.str;
121 default = name;
122 description = "Group account under which MPD runs.";
123 };
124
125 listenAddresses = mkOption {
126 type = with types; listOf (either (submodule tcpAddress) str);
127 default = [{ address = "127.0.0.1"; }];
128 };
129
130 dbFile = mkOption {
131 type = types.str;
132 default = "${cfg.dataDir}/tag_cache";
133 defaultText = ''''${dataDir}/tag_cache'';
134 description = ''
135 The path to MPD's database.
136 '';
137 };
138 };
139
140 };
141
142
143 ###### implementation
144
145 config = mkIf cfg.enable {
146
147 systemd.sockets.mpd = mkIf cfg.startWhenNeeded {
148 description = "Music Player Daemon Socket";
149 wantedBy = [ "sockets.target" ];
150 listenStreams = map listenStream cfg.listenAddresses;
151 socketConfig = {
152 Backlog = 5;
153 KeepAlive = true;
154 PassCredentials = true;
155 };
156 };
157
158 systemd.services.mpd = {
159 after = [ "network.target" "sound.target" ];
160 description = "Music Player Daemon";
161 wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target";
162
163 preStart = ''
164 mkdir -p "${cfg.dataDir}" && chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}"
165 mkdir -p "${cfg.playlistDirectory}" && chown -R ${cfg.user}:${cfg.group} "${cfg.playlistDirectory}"
166 '';
167 serviceConfig = {
168 User = "${cfg.user}";
169 PermissionsStartOnly = true;
170 ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon ${mpdConf}";
171 Type = "notify";
172 LimitRTPRIO = 50;
173 LimitRTTIME = "infinity";
174 ProtectSystem = true;
175 NoNewPrivileges = true;
176 ProtectKernelTunables = true;
177 ProtectControlGroups = true;
178 ProtectKernelModules = true;
179 RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_NETLINK";
180 RestrictNamespaces = true;
181 };
182 };
183
184 users.extraUsers = optionalAttrs (cfg.user == name) (singleton {
185 inherit uid;
186 inherit name;
187 group = cfg.group;
188 extraGroups = [ "audio" ];
189 description = "Music Player Daemon user";
190 home = "${cfg.dataDir}";
191 });
192
193 users.extraGroups = optionalAttrs (cfg.group == name) (singleton {
194 inherit name;
195 gid = gid;
196 });
197 };
198
199}