at 18.03-beta 5.4 kB view raw
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 29in { 30 31 ###### interface 32 33 options = { 34 35 services.mpd = { 36 37 enable = mkOption { 38 type = types.bool; 39 default = false; 40 description = '' 41 Whether to enable MPD, the music player daemon. 42 ''; 43 }; 44 45 startWhenNeeded = mkOption { 46 type = types.bool; 47 default = false; 48 description = '' 49 If set, <command>mpd</command> is socket-activated; that 50 is, instead of having it permanently running as a daemon, 51 systemd will start it on the first incoming connection. 52 ''; 53 }; 54 55 musicDirectory = mkOption { 56 type = types.path; 57 default = "${cfg.dataDir}/music"; 58 defaultText = ''''${dataDir}/music''; 59 description = '' 60 The directory where mpd reads music from. 61 ''; 62 }; 63 64 playlistDirectory = mkOption { 65 type = types.path; 66 default = "${cfg.dataDir}/playlists"; 67 defaultText = ''''${dataDir}/playlists''; 68 description = '' 69 The directory where mpd stores playlists. 70 ''; 71 }; 72 73 extraConfig = mkOption { 74 type = types.lines; 75 default = ""; 76 description = '' 77 Extra directives added to to the end of MPD's configuration file, 78 mpd.conf. Basic configuration like file location and uid/gid 79 is added automatically to the beginning of the file. For available 80 options see <literal>man 5 mpd.conf</literal>'. 81 ''; 82 }; 83 84 dataDir = mkOption { 85 type = types.path; 86 default = "/var/lib/${name}"; 87 description = '' 88 The directory where MPD stores its state, tag cache, 89 playlists etc. 90 ''; 91 }; 92 93 user = mkOption { 94 type = types.str; 95 default = name; 96 description = "User account under which MPD runs."; 97 }; 98 99 group = mkOption { 100 type = types.str; 101 default = name; 102 description = "Group account under which MPD runs."; 103 }; 104 105 network = { 106 107 listenAddress = mkOption { 108 type = types.str; 109 default = "127.0.0.1"; 110 example = "any"; 111 description = '' 112 The address for the daemon to listen on. 113 Use <literal>any</literal> to listen on all addresses. 114 ''; 115 }; 116 117 port = mkOption { 118 type = types.int; 119 default = 6600; 120 description = '' 121 This setting is the TCP port that is desired for the daemon to get assigned 122 to. 123 ''; 124 }; 125 126 }; 127 128 dbFile = mkOption { 129 type = types.str; 130 default = "${cfg.dataDir}/tag_cache"; 131 defaultText = ''''${dataDir}/tag_cache''; 132 description = '' 133 The path to MPD's database. 134 ''; 135 }; 136 }; 137 138 }; 139 140 141 ###### implementation 142 143 config = mkIf cfg.enable { 144 145 systemd.sockets.mpd = mkIf cfg.startWhenNeeded { 146 description = "Music Player Daemon Socket"; 147 wantedBy = [ "sockets.target" ]; 148 listenStreams = [ 149 "${optionalString (cfg.network.listenAddress != "any") "${cfg.network.listenAddress}:"}${toString cfg.network.port}" 150 ]; 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}