Start of icecast mpd nix article and cleanup
This commit is contained in:
parent
cc021ec002
commit
c2ce6c19f9
175
content/rambles/mpd-and-icecast-on-nix.md
Normal file
175
content/rambles/mpd-and-icecast-on-nix.md
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
---
|
||||||
|
title: "Mpd and Icecast on Nix"
|
||||||
|
date: "2022-11-06T22:11:10+01:00"
|
||||||
|
author: "$HUMANOID"
|
||||||
|
tags: ["nix", "linux"]
|
||||||
|
description: "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:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ 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:
|
||||||
|
```nix
|
||||||
|
{ config, pkgs, ... }: {
|
||||||
|
services.mpd = {
|
||||||
|
enable = true;
|
||||||
|
...
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
From here, there are a few rather basic options that you'll want to set:
|
||||||
|
```nix
|
||||||
|
...
|
||||||
|
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":
|
||||||
|
|
||||||
|
```nix
|
||||||
|
...
|
||||||
|
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" >}}
|
||||||
|
```conf
|
||||||
|
...
|
||||||
|
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`:
|
||||||
|
|
||||||
|
```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:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
...
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
|
@ -63,7 +63,7 @@ I ran DWM as my main window manger for over a year before having issues with
|
||||||
some fullscreen applications and the JetBrains suite, which I had to use for
|
some fullscreen applications and the JetBrains suite, which I had to use for
|
||||||
college activities.
|
college activities.
|
||||||
|
|
||||||
{{< img class="stickers" link="https://xkcd.com/1806/" src="/images/xkcd/borrow_your_laptop.png" >}}
|
{{< img link="https://xkcd.com/1806/" src="/images/xkcd/borrow_your_laptop.png" >}}
|
||||||
|
|
||||||
I decided to give AwesomeWM another shot after having figured out what I want
|
I decided to give AwesomeWM another shot after having figured out what I want
|
||||||
from a tiling window manger. This time I managed to get something that worked
|
from a tiling window manger. This time I managed to get something that worked
|
||||||
|
@ -113,7 +113,7 @@ and I decided to dive into learning the language with the goal of being able to
|
||||||
fully understand my monstrous 384 line config file (586 lines including the
|
fully understand my monstrous 384 line config file (586 lines including the
|
||||||
documentation in commented sections).
|
documentation in commented sections).
|
||||||
|
|
||||||
{{< img class="stickers" src="/images/config_length.png" >}}
|
{{< img src="/images/config_length.png" >}}
|
||||||
|
|
||||||
I don't fully understand it yet at the time of writing, but I do understand it
|
I don't fully understand it yet at the time of writing, but I do understand it
|
||||||
a hell of a lot better than when I produced most of those 300 lines.
|
a hell of a lot better than when I produced most of those 300 lines.
|
||||||
|
|
BIN
static/images/graphs/radio.png
Normal file
BIN
static/images/graphs/radio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -1 +1 @@
|
||||||
Subproject commit 8122d5eb1ae06319cfc007454cd1ad46658aef1c
|
Subproject commit 5251fa45a81337e7cf0a4d61f373d31d6c1ed1b7
|
Loading…
Reference in a new issue