5.9 KiB
title | date | author | tags | description | ||
---|---|---|---|---|---|---|
Mpd and Icecast on Nix | 2022-11-06T22:11:10+01:00 | $HUMANOID |
|
Ramble about setting up MPD + Icecast on NixOS |
Introduction
For quite some time now, I've been wanting to move my home server from Debian to NixOS. There were a few things that kept me from starting with the migration. The main one being that the Debian installation still worked reasonably well. I only had occasional hickups in regards to the two USB disks hooked up to my Raspberry Pi 4. Every now and then they'd disappear. My guess is that it was due to power draw as it would consistently happen when putting heavy IO loads on either disk. One of these disks is home to my music collection and used by my internet radio setup (in other words, the main thing I listen to when at home). And this nicely brings my to my next issue.
{{< img class="stickers" src="/images/graphs/radio.png" mouse="Flowchart demonstrating software stack">}}
This radio consists of an MPD instance streaming to an Icecast2 instance, being reverse proxied through an NGINX instance (future plans include managing the music collection through Git Annex...). I have tried setting up MPD on NixOS in the past, but couldn't get it to work for some odd reason. I don't remember why I never managed it. I just know that I gave up after a few hours. Today I decided to spend as much time as necessary to get at least the MPD + Icecast2 portion to work. The rest of this post will be detailing how I went about setting configuring MPD + Icecast2 on NixOS as there were a few non-obvious things I bumped into.
Setting up MPD
To prevent my /etc/nixos/configuration.nix
from ballooning into absurdity,
you'll want to create something like a /etc/nixos/services/radio.nix
file
containing everything related to the radio stack. This file is then imported in
/etc/nixos/configration.nix
in the imports
section as follows:
{ config, pkgs, ... }: {
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
./drives.nix
./services/radio.nix
...
];
...
}
The first thing you'll want to do is enable the MPD service:
{ config, pkgs, ... }: {
services.mpd = {
enable = true;
...
From here, there are a few rather basic options that you'll want to set:
...
musicDirectory = "/path/to/music-collection/";
network.listenAddress = "any"; # not quite sure if this is needed
...
At the extraConfig
section is where things get interesting. Here I assumed you
could point Nix to an existing config file with (builtins.readFile /path/to/mpd.conf)
but it seems I am wrong. It doesn't throw any errors when
switching to a new build, but it doesn't read the given config file either. I'm
probably missing something here. Please shout at me if you happen to know what
it is.
Regardless, you're going to want to add at least one audio output method. Since
we're going to make MPD talk to Icecast2, we're going to add audio_output
section of type "shout":
...
musicDirectory = "/path/to/music-collection/";
extraConfig = ''
audio_output {
type "shout"
encoder "vorbis" # FOSS codec for the win
name "My Shouty Stream"
host "<name found in the networking.hostName variable>"
port "8000" # or use whatever meme you like
mount "/mpd.ogg"
password "hunter2"
quality "5.0"
format "44100:16:2"
genre "Rythmic Noise!"
protocol "icecast2"
}
'';
};
...
Please don't take this snippet as gospel and read through the MPD configuration.
Whatever is found in extraConfig
will be directly given to MPD as if through
/etc/mpd.conf
on e.g. Debian. For instance, if you only locally want to listen
to your music through say PulseAudio, than you'll need a corresponding output
section.
{{< start-details summary="Example PulseAudio configuration I have on my laptop" >}}
...
audio_output {
type "pulse"
name "Pulse output"
audio_output_format "44100:16:2"
samplerate_converter "Medium Sinc Interpolator"
mixer_type "software"
replaygain "album"
volume_normalization "no"
}
...
{{< end-details >}}
Mounting a music disk
In order to automount a disk on NixOS, add an expression something like the
following (indirectly) in your /etc/nixos/configration.nix
:
fileSystems."/srv/music" = {
device = "/dev/sdb1"; # assuming that sdb1 is the partition with your music on it
# device = "/dev/disk/by-label/Sauserer"; # or ideally, if you have a labelled disk
fsType = "ext4"; # assuming it has a ext4 filesystem on it
};
I have my drives listed in /etc/nixos/drives.nix
and import that in my
configration.nix
Setting up Icecast2
The next step is to set up Icecast2. Same as with MPD, the first thing you'll want to do is enable it:
...
services.icecast = {
enable = true;
extraConf = ''
<location>Floating around in an example configuration snippet on the internet</location>
<admin>icemaster@localhost</admin>
<authentication>
<source-password>hunter2</source-password>
<relay-password>even-more-super-secret-password</relay-password>
</authentication>
<limits>
<clients>100</clients>
<sources>2</sources>
<queue-size>524288</queue-size>
<client-timeout>30</client-timeout>
<header-timeout>15</header-timeout>
<source-timeout>10</source-timeout>
<burst-on-connect>1</burst-on-connect>
<burst-size>65535</burst-size>
</limits>
'';
hostname = "hostname:8000";
listen.port = 8000;
admin.password = "it gives me a headache that I can't get Nix to read this from a file";
};
}