diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2018-04-21 13:07:12 +0200 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2018-04-21 13:07:12 +0200 |
commit | 544c87716cb912dad3cc9568781470dcde5c64d2 (patch) | |
tree | f1d1a0a06a4d129b003a3f0483327cfe9eda3763 | |
parent | e00cfe41ebeb8c3a2d4142160013aa1590d5eb7f (diff) | |
download | nixos-544c87716cb912dad3cc9568781470dcde5c64d2.tar nixos-544c87716cb912dad3cc9568781470dcde5c64d2.tar.gz nixos-544c87716cb912dad3cc9568781470dcde5c64d2.tar.bz2 nixos-544c87716cb912dad3cc9568781470dcde5c64d2.tar.xz nixos-544c87716cb912dad3cc9568781470dcde5c64d2.zip |
Touch up mpd
-rw-r--r-- | bragi.nix | 49 | ||||
-rw-r--r-- | custom/mpd.nix | 199 |
2 files changed, 224 insertions, 24 deletions
@@ -10,6 +10,7 @@ in rec { | |||
10 | ./users.nix | 10 | ./users.nix |
11 | ./custom/unit-status-mail.nix | 11 | ./custom/unit-status-mail.nix |
12 | ./custom/trivmix-service.nix | 12 | ./custom/trivmix-service.nix |
13 | ./custom/mpd.nix | ||
13 | ./utils/nix/module.nix | 14 | ./utils/nix/module.nix |
14 | ]; | 15 | ]; |
15 | 16 | ||
@@ -84,27 +85,29 @@ in rec { | |||
84 | }; | 85 | }; |
85 | 86 | ||
86 | nixpkgs.config = { | 87 | nixpkgs.config = { |
87 | packageOverrides = oldPkgs: with oldPkgs; { | 88 | overlays = [ |
88 | haskellPackages = haskellPackages.override { | 89 | (selfPkgs: superPkgs: with superPkgs; { |
89 | overrides = self: super: with self; { | 90 | haskellPackages = haskellPackages.override { |
90 | encoding = haskell.lib.overrideCabal encoding ( oldAttrs: { | 91 | overrides = self: super: with self; { |
91 | src = fetchFromGitHub { owner = "pngwjpgh"; repo = "encoding"; rev = "extended-version-bounds"; sha256 = "0pzxixp384a1ywzj56pl7xc4ln7i9x6mq8spqjwcs80y0pgfpp9s"; }; | 92 | encoding = haskell.lib.overrideCabal encoding ( oldAttrs: { |
92 | }); | 93 | src = fetchFromGitHub { owner = "pngwjpgh"; repo = "encoding"; rev = "extended-version-bounds"; sha256 = "0pzxixp384a1ywzj56pl7xc4ln7i9x6mq8spqjwcs80y0pgfpp9s"; }; |
93 | inherit | 94 | }); |
94 | (lib.mapAttrs (name: haskell.lib.dontCheck) super) | 95 | inherit |
95 | Glob filelock hedgehog; | 96 | (lib.mapAttrs (name: haskell.lib.dontCheck) super) |
96 | inherit | 97 | Glob filelock hedgehog; |
97 | (callPackage ./custom/thermoprint { inherit runCommand makeWrapper; extraPackages = (p: with p; [ persistent-postgresql ]); }) | 98 | inherit |
98 | thermoprint-spec thermoprint-bbcode thermoprint-client thermoprint-server thermoprint-webgui tprint bbcode; | 99 | (callPackage ./custom/thermoprint { inherit runCommand makeWrapper; extraPackages = (p: with p; [ persistent-postgresql ]); }) |
100 | thermoprint-spec thermoprint-bbcode thermoprint-client thermoprint-server thermoprint-webgui tprint bbcode; | ||
101 | }; | ||
99 | }; | 102 | }; |
100 | }; | ||
101 | 103 | ||
102 | jack2Full = jack2Full.override { dbus = null; }; | 104 | jack2Full = jack2Full.override { dbus = null; }; |
103 | 105 | ||
104 | mpd = mpd.override { gmeSupport = false; pulseaudioSupport = false; }; | 106 | mpd = mpd.override { gmeSupport = false; pulseaudioSupport = false; }; |
105 | 107 | ||
106 | inherit (pkgs.haskellPackages) thermoprint-server thermoprint-webgui tprint; | 108 | inherit (pkgs.haskellPackages) thermoprint-server thermoprint-webgui tprint; |
107 | }; | 109 | }) |
110 | ]; | ||
108 | 111 | ||
109 | allowUnfree = true; | 112 | allowUnfree = true; |
110 | }; | 113 | }; |
@@ -225,14 +228,12 @@ in rec { | |||
225 | services.mpd = { | 228 | services.mpd = { |
226 | enable = true; | 229 | enable = true; |
227 | musicDirectory = "smb://odin.asgard.yggdrasil/media/music"; | 230 | musicDirectory = "smb://odin.asgard.yggdrasil/media/music"; |
228 | network.listenAddress = "any"; # Just so the module won't produce a bind_to_adress line | 231 | listenAddresses = [ |
232 | { address = "any"; } | ||
233 | "/var/lib/mpd/socket" | ||
234 | ]; | ||
235 | startWhenNeeded = true; | ||
229 | extraConfig = '' | 236 | extraConfig = '' |
230 | bind_to_address "bragi.bragisheimr.yggdrasil" | ||
231 | bind_to_address "bragi.asgard.yggdrasil" | ||
232 | bind_to_address "localhost" | ||
233 | |||
234 | bind_to_address "/var/lib/mpd/socket" | ||
235 | |||
236 | audio_output { | 237 | audio_output { |
237 | name "JACK" | 238 | name "JACK" |
238 | type "jack" | 239 | type "jack" |
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 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
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 | |||
47 | in { | ||
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 | } | ||