MPD with Nomad
I’d seen MPD before (well, it was ncmpcpp), but I gave it a try when I’d gotten sick of needing to stream every piece of content I wanted to consume. The setup didn’t seem hard, but I also wanted to take a dip into using service schedulers.
- Setting this up seemed like a solid night project,
- I’ve been using a lot of HashiCorp tooling in my day to day, so It’s great opportunity to finally learn and toy with Nomad,
- I was too indifferent to write a
.plist
file for launchd to auto-start MPD when my Macbook boots (plus launchd isn’t cross-platform), - Nomad’s
raw_exec
driver could be swapped out for an MPD Docker container later (possiblyeasily!)
Setup
Assuming MPD’s config is set up correctly, the Nomad jobspec is pretty straightforward:
job "mpd" {
type = "service"
# run on -dev datacenter
datacenters = ["dc1"]
meta {
# mpd config file location
MPD_CONFIG = "~/.config/mpd/mpd.conf"
}
group "daemon" {
task "server" {
# don't isolate the process
driver = "raw_exec"
# do the thing
config {
# use the mpd binary resolved by $PATH
command = "mpd"
# log stderr and don't fork to the background
args = [
"--no-daemon",
"--stderr",
"${NOMAD_META_MPD_CONFIG}",
]
}
}
}
}
Regarding the command args, --no-daemon
prevents MPD from auto-forking to the background, and --stderr
forces MPD to log event details to Stderr rather than omitting the logging entirely. I hadn’t planned to deploy an MPD service anywhere either, and so using a dev cluster was fine to start.
Assuming there’s a Nomad cluster running on 127.0.0.1:4646
(that way you can use defaults), schedule the MPD Nomad job as you would for any other:
t$ nomad run mpd.nomad
==> Monitoring evaluation "d36f7862"
Evaluation triggered by job "mpd"
Allocation "296eced2" created: node "f8146dbe", group "daemon"
Allocation "296eced2" status changed: "pending" -> "running"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "d36f7862" finished with status "complete"
t$ mpc status
Christopher Schwarzwalder & David Dorad & Iannis Ritter - Elevator Music (Original Mix)
[playing] #1/1 5:07/7:45 (66%)
volume:100% repeat: off random: off single: off consume: off
t$ nomad alloc logs --stderr 296
client: [0] opened from 127.0.0.1:51000
client: [1] opened from 127.0.0.1:51010
client: [1] closed
Be sure to use the --stderr
flag when looking at the logs: MPD is fairly quiet otherwise. Ncmpcpp auto-connected from another terminal I’d had open, hence the two separate clients. MPD and MPC functioned perfectly, so any legitimate MPD client should be unaffected.
Remote Streaming
If you’ve got a server, the next step is to set up remote access. The MPD entry on the Arch Wiki for configuring HTTP streaming steps in here.
Replace the existing audio_output
config (or add it as a new entry) in the mpd.conf
:
audio_output {
type "httpd"
name "mpd-server"
port "3456"
bitrate "128"
format "44100:16:1"
always_on "yes"
tags "yes"
}
…and after stopping and restarting the mpd
job MPD should load the new config and initialize the httpd
output device. By either hooking up a local MPD daemon to the remote server or opening the server-port combo in browser you can stream to almost anything 👍
The httpd
output capability also means that a containerized/Dockerized MPD server could be done exactly the same way without sharing the host’s hardware audio devices, which would be a nightmare for cross-platform support.
Future plans:
Containerizing MPD, there’s already a number of existing MPD Docker containers, like vimagick/mpd,- Health checks,
- Templated
.mpd.conf