Lyrion Music Server (the rebranded Logitech Media Server) packaged with avahi-daemon and dbus so the AirPlay, Chromecast and UPnP bridge plugins actually work.
The upstream image
lmscommunity/lyrionmusicserver
does not ship avahi. Without it the following plugins are broken or
limited:
- ShairTunes2W (publishes squeeze players as AirPlay sinks for iOS,
macOS, PipeWire). Its bundled
shairport_helper-linux-x86_64v1.9.5 tries to publish mDNS itself, has a broken CLI, and exits withCan't start server. Withavahi-publish-servicein PATH the plugin uses it via D-Bus and the squeeze players appear as AirPlay sinks. - RaopBridge (AirPlay receivers as squeeze players), CastBridge (Chromecast), UPnPBridge (DLNA). These also need mDNS / SSDP to find or announce devices on the LAN.
- C-3PO transcoder. The plugin's environment check calls
findbin("ffmpeg"), which only looks in LMS's own bin dirs. The image installs ffmpeg from apt and symlinks it into the right place.
- everything from upstream
lmscommunity/lyrionmusicserver avahi-daemon,avahi-utils,libnss-mdnsdbus(avahi talks D-Bus)ffmpeg, symlinked into/lms/Bin/<arch>/so C-3PO can find it- node 22 LTS at
/usr/bin/node, copied from the officialnode:22-bookworm-slimimage. needed by yt-dlp's JavaScript challenge solver. debian bookworm only ships node 18 which yt-dlp rejects as "unsupported", causing YouTube playback to fail with "Signature solving failed" on most videos. - an entrypoint wrapper that starts dbus and avahi, waits for both to register on the system bus, and hands off to the upstream start-container
podman pull ghcr.io/alexanderadam/lyrionmusicserver_avahi:latest
docker pull ghcr.io/alexanderadam/lyrionmusicserver_avahi:latestTags match the upstream Lyrion version, for example 9.1.1. There is
also latest which points at the newest upstream version that has been
built.
mDNS, SSDP and AirPlay multicast do not cross the default container bridge, so the image only works with host networking. This applies to podman and docker both.
podman run --rm -d \
--name lyrion \
--network=host \
--security-opt seccomp=unconfined \
-v ./config:/config \
-v ./music:/music:ro \
-v ./playlists:/playlists \
ghcr.io/alexanderadam/lyrionmusicserver_avahi:latestservices:
lyrion:
image: ghcr.io/alexanderadam/lyrionmusicserver_avahi:latest
network_mode: host
security_opt:
- seccomp=unconfined
volumes:
- ./config:/config
- ./music:/music:ro
- ./playlists:/playlists
restart: unless-stoppedOnly needed on hosts older than kernel 5.3 with a container runtime
older than late 2021 (docker < 20.10.10 or equivalent podman). On
those, the default seccomp profile returns EPERM for the unknown
clone3 syscall instead of ENOSYS, so modern glibc never falls back to
clone() and pthread_create inside shairport_helper silently never
spawns the worker threads. The helper opens its HTTP listener, then LMS
times out after 15 seconds with "Can't connect to server".
If your host is on a recent kernel and a recent runtime, drop the
seccomp=unconfined line. Better security defaults, same behaviour.
podman build -t lyrionmusicserver-avahi:local -f Containerfile .
docker build -t lyrionmusicserver-avahi:local -f Containerfile .To target a specific Lyrion version:
podman build \
--build-arg LYRION_VERSION=9.1.1 \
-t lyrionmusicserver-avahi:9.1.1 \
-f Containerfile .To pin the avahi advertise interface at build time (otherwise avahi defaults apply, which advertise on every visible nic):
podman build \
--build-arg AVAHI_ALLOW_INTERFACES=eth0 \
-t lyrionmusicserver-avahi:local \
-f Containerfile ..github/workflows/build.yml runs once a day. It:
- Lists the semver tags on Docker Hub for
lmscommunity/lyrionmusicserver. - Lists the tags already present on ghcr for this image.
- For every upstream tag that is missing on ghcr, builds with
--build-arg LYRION_VERSION=<tag>and pushes under the same tag. - The newest semver also gets the
latesttag.
So the version of this image always matches the upstream Lyrion version it is based on.
A push to main that touches the Containerfile, the entrypoint, or
the workflow itself also rebuilds the newest upstream tag, so wrapper
changes ship without waiting for the next upstream release.
You can also trigger a build by hand from the Actions tab with a specific version.
avahi-daemon needs a running D-Bus system bus to be useful, and neither
of them is started by the upstream image's start-container. The
wrapper at entrypoint.sh:
- Sets up
/run/dbusand a machine id if missing. - Starts a system D-Bus daemon.
- Starts avahi-daemon in the background.
- Hands off to the original upstream entrypoint
(
/usr/bin/start-container.orig).
If you want to see what upstream's entrypoint does, it is preserved at
/usr/bin/start-container.orig.
- A specific avahi
allow-interfaces=setting. Pin it at build time with theAVAHI_ALLOW_INTERFACESbuild arg if you need to. - Anything related to the LMS prefs or music directory. Mount them in as volumes like with the upstream image.
- Plugin preinstallation. Install through the LMS web UI as usual.
The wrapper bits (Containerfile, entrypoint, workflow) are MIT, see
LICENSE. The base image
lmscommunity/lyrionmusicserver
keeps its own licensing. Lyrion Music Server itself is GPL, see the
upstream project.