Skip to content

Navidrome

Navidrome is a self-hosted music server and streamer. It provides a web-based interface for browsing and playing your music library from any browser or Subsonic-compatible app.

The simplest path doesn’t need any Navidrome-side configuration at all. Navidrome streams audio to the browser or Subsonic client on your laptop/desktop as usual, and that machine is routed to the odio node via PulseAudio TCP. The audio plays locally from the client’s perspective, but it lands on the odio node’s HiFiBerry instead of the client’s speakers.

This assumes a Linux client running PulseAudio, or PipeWire with pipewire-pulse, since that’s what lets the machine target a remote PulseAudio sink. The client also needs to be on the same local network as the odio node, PulseAudio TCP is not meant to cross the internet (unencrypted, LAN-only).

This is the Desktop & Laptop use case applied to Navidrome, nothing Navidrome-specific, any application on a machine routed to an odio node behaves the same way.

Navidrome’s jukebox mode plays audio through a local mpv process on the Navidrome host instead of streaming to the browser. Pointed at an odio node via PulseAudio TCP, Navidrome becomes a full-fledged music server that drives the node’s DAC directly, remote-controlled from any Subsonic-compatible client.

odio exposes a network PulseAudio sink. Setting PULSE_SERVER on the Navidrome process (or container) to the odio node’s IP is enough for mpv to route audio there. No odio-side configuration needed beyond having the PulseAudio TCP sink enabled.

mpv enumerates PulseAudio sinks by their PulseAudio name. With PULSE_SERVER pointing at your odio node, run:

Terminal window
PULSE_SERVER=192.168.x.x mpv --audio-device=help

See mpv’s audio output documentation for the device naming convention. Pick the entry that matches your node’s DAC, it will look something like pulse/alsa_output.platform-soc_sound.stereo-fallback.

In navidrome.toml (or config.toml, depending on your setup), declare the jukebox devices and pick a default:

Jukebox.Enabled = true
Jukebox.Devices = [
[ "auto", "auto" ],
[ "pulse", "pulse/alsa_output.platform-soc_sound.stereo-fallback" ],
]
Jukebox.Default = "pulse"

Running Navidrome in Docker works the same way, PULSE_SERVER is passed as an environment variable. Example docker-compose.yml:

services:
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
user: 1000:29 # should own the config/data volumes
restart: unless-stopped
environment:
ND_CONFIGFILE: "/config/config.toml"
PULSE_SERVER: "192.168.1.6"
volumes:
- "./config:/config"
- "./data:/data"
- "/path/to/Music:/music:ro"
networks:
- web

With PULSE_SERVER set, the mpv process inside the container streams straight to the odio node, no extra networking plumbing required.