Rouen + HQPWeb

A music-discovery companion and full-screen wall display for Roon — random-album browsing, a shelf of covers to flick through, instant whole-library search, rich label & artist pages, and seamless playback with Roon Server at the heart. A Rouen is a duck — MusicD is short for Music Duck. Called MusicD Remote until v1.8.74; install commands, the image and the data volume keep their musicd-remote names.

+ HQPWeb. For a Roon that plays through HQPlayer, Rouen has hqpweb built in — statelycurmudgeon's web controller for HQPlayer, and their hard work, carried here with thanks under its MIT licence. What it does and how to use it →

v1.9.66 Docker MIT licence Pairs with your Roon Core over the network

Features

Everything talks to your existing Roon Core through the official extension API — or, with the optional native mode, as Roon's own apps do — and the app never changes your library files. An optional read-only /music mount adds file-tag labels, release dates, local waveforms, the local-files badge and the format filters. Tap i on any feature for how to set it up and use it.

🎛️Native modeNew

Rouen talks to your Roon Core the way Roon's own apps do, both ways. Your library is the Core's own album list. A heart in Rouen is Roon's favourite. Listen later is one list shared with Roon. Dynamic Playlists are Roon's smart playlists, with their covers, and playlists made in Rouen are Roon's own. Add to library uses Roon's own search, and play, pause, skip, seek, volume, mute, shuffle, repeat and Roon Radio go straight to the Core. New in v1.9.66: each zone's crossfade, volume levelling and sleep timer, its DSP in a window of its own (each item on or off; Headroom, Crossfeed and Sample rate conversion's settings; Parametric EQ bands), and Edit for any of Roon's smart playlists, in Rouen's Focus editor. A status board in Settings → Native mode shows a green, red or grey light for each, and why when one fails; the official extension API is the fallback for everything.

🔭More around every album

Below the review in every album: More by the artist and the records they appear on, from your library, then Similar artists and Similar albums from Last.fm — three of each, with More for the rest. Last.fm is read-only: a free key, no sign-in, nothing scrobbled. Also new: Random Album asks before it plays (Play now, Play next or Queue), Random album radio doesn't play an album again within six months, and Smart Picks start on Nowhere — ask me rather than going straight into your library. Fixed in v1.9.2: with a genre filter on, an album opened from an artist's page no longer answers "Album not found".

📚Shelf

Flick through your collection the way you once flicked through a rack of CDs or records — made for a tablet on a stand or a TV. A shelf of covers turns under your finger: a short swipe moves one album, swipe and hold keeps it turning, and a hard flick spins it to land on an album three seconds later (a shelf of three or fewer just steps). Tap the front cover and the case turns over to show its tracks. Three looks — Covers on a glossy shelf, Spines in a CD rack, and a Carousel. Choose what is on it by Genre, by Artist letter (A–Z, # and 1–9) or Random; with nothing chosen it is the whole library, A → Z by artist. Play now, Play next, Add to queue under the front cover, and it opens on the record that is playing. Along the bottom is the mini player, flat: play/pause, the position, the zone and its volume — tap the playing record to bring it to the front.

New in v1.9.4–v1.9.7: turn a case over and hold a track to choose it — its number becomes a tick — then tap more to add them, and Play now, Play next or Queue from the popup under the cover (⌘/Ctrl-click and Shift-click with a mouse). A track list too long for the back unfolds below the case as a booklet, with pages for a box set, and each disc of a set has its own heading. The queue is a pane on the right — tap a track to come to play from there — and small tabs at the edges fold the choices away to the left and the queue to the right; the covers grow with every side folded, so with both away the shelf has the whole screen.

📺Remote ⇄ wall display

☰ → Wall display turns the remote into the wall display for its zone, and ‹ Remote in its top-left corner brings it back exactly as you left it — always on screen now, faint, and one tap: off-white over a dark screen, grey over a light artist photo. Shelf › sits opposite it, top right. A screensaver timer switches to the display after 1 to 60 minutes untouched — per device and off unless you choose it. It waits while Settings, a sheet or a selection is open.

🎚️HQPlayer control, from hqpweb

statelycurmudgeon's hqpweb, built in: a screen in the side menu for HQPlayer's 1x and Nx filters, its modulator or dither and presets, with Signalyst's ratings. Every change is read back; one that stops playback or that HQPlayer can't keep up with is put back by itself and remembered. A guide (beta) says where to start for your DAC, and Find your DAC looks it up. Several HQPlayers — found on your network or added by address — and several DACs behind one HQPlayer, each with its own answers, learned failures and presets.

💾Backup & restore

Back up your settings, playlists and Dynamic Playlists, Listen later, and API keys and sign-ins — any of the four. Backups are kept on the server (your last 10, plus 5 taken before a restore) and each can be downloaded. A restore keeps a copy of how things were first, restarts the server, and the page reloads by itself. A downloaded backup can be restored from the file.

⏭️Play next, everywhere

Play now, Play next, Queue on every track in the album view, and Play next in the selection menu for selected tracks and albums and in the album's ⋯ menu. What you choose plays straight after the current track — selected tracks in album order, selected albums in the order you picked them.

📱Album view & mini player

On tablets and desktops About this album sits under the cover, beside the tracks, and on a tablet the album view fills the screen. The mini player is taller with bigger buttons on touch screens, and on a desktop it is a card in the corner that can be dragged anywhere. Now playing shows the whole cover, framed, and the seek bar is a brass level meter where a track has no waveform.

🎛️UI Settings & label search

Make the app fit the screen it is on: text size for album and artist names and for each grid screen's title, a grid layout of Auto, 3 columns, 2 columns or List, and a tile size from −50% to +50% for album and label tiles everywhere. The Labels screen gains a search and a #–Z / Z–# order button, Home Screen rows drag smoothly into place, and a Smart Pick opens its album in your library or on your default streaming service.

🐳A ready-made image

Install with one docker run — nothing to download or build — from ghcr.io/meltface-80/musicd-remote, built for x86 and 64-bit ARM: PCs and NAS boxes, a Raspberry Pi 4 or 5 on a 64-bit OS, Apple Silicon Macs. Updates stay one tap in the app, and switching an existing install needs no reinstall: remove the old container and run the image with the same volume, and your Roon pairing and history carry over.

🔄Your library, followed in seconds

Add albums in Roon and they are in the app within about a minute, with no rescan. While the app or the wall display is open it checks Roon every 30 seconds (every 3 minutes when nobody is looking) with three tiny calls that cost the Core almost nothing, follows a change until Roon settles, then reads the library once — so a big import costs one pass, not one per album. The side menu says when the library was last checked.

🧭Simpler navigation

The ☰ menu button is Home's; on every other screen the brass ‹ takes its place — back to the album or screen you came from on an artist page (or a label opened from an album), Home anywhere else. A shorter side menu — Pitchfork, Labels, Qobuz, Tidal, Listen later, Discover, Dynamic Playlists, Playlists, Wall display, Shelf, HQPlayer, then Rescan library and Settings — with Random albums and Smart Picks opening from their Home rows and Import at the top of the Playlists screen. Settings is grouped as Services, Playback, Wall Display, HQPlayer, Setup and Updates (with Backup & restore since v1.8.84); Setup holds Smart Picks, Record labels, Home Screen, UI Settings, Share Card, Discover and API Keys. On a phone every page opens full screen with its title pinned; on a tablet or desktop the list is a side panel.

🕒Listen later

Put an album aside to play another time — from its ⋯ menu, from a selection of albums on any wall, or with + Listen later on a Smart Pick. Roon's own Listen later can't be reached from an extension, so this is the app's own list: kept on the server, the same on every device, and safe across a library rescan. Albums you own play straight from it; a Smart Pick that isn't in your library yet can be added in one tap or opened in Qobuz or TIDAL. It tidies itself: an album comes off once every track has been played through since you put it aside, on any zone, from any app.

↔️Previous & next album

Swipe the album card sideways, tap the chevrons on the cover's edges, or use the arrow keys to step to the albums either side — on the screen you opened it from, whether that's a Home row, the Library wall, or an artist or label page. Close the card and you land on the album you stepped to.

📡Live screens

Every screen keeps itself up to date. Home, the Library and Not played walls, the Queue, the album, artist and label pages, Smart Picks and Discover refresh themselves when something changes — a play, a release date found, a setting changed on another device. In place: your scroll position stays, nothing flashes “Loading…”, and nothing moves while your finger is on it.

🧭Discover

New records by the artists you actually listen to. Read from your play history rather than your library, and ranked by how many separate days you played an act rather than by play count. Albums only, from the last two months, never a record you already have — and a remaster is refused only when the title says so and the act has an older release under the same name. Every row goes somewhere: in your Roon library it queues, otherwise it opens in your default streaming service. Uses Deezer's public catalogue and never touches your Roon Core.

📤Share card

Tap Share on any album or on Now playing and the record gets a card of its own — artwork, artist, title, release date and label, a description, and the Pitchfork score with its Best New Music flag where there is one. Underneath: where to hear it (Qobuz, TIDAL, Spotify, Apple Music, Amazon Music, Deezer, Bandcamp — and Qobuz opens the Qobuz app) and where to read about it (Wikipedia, Pitchfork and AllMusic for the album; Wikipedia and AllMusic for the artist if you want them). And “If you like this” suggests three acts worth hearing next, weighed by what you play — two you haven't heard near the acts you play most, and one you know with a record you don't own yet, each saying why. One in your Roon library is queued; one that isn't opens in your default service.

〰️Waveform

The seek bar on Now playing and the wall display's progress strip draw the shape of the track you're listening to — where the quiet intro ends, where the loud middle is. Every bar is the level of its slice of the track, measured from both channels at full rate, and the shape sits under the playhead at every point in the track. Each track is analysed once and stored, and the next one in the queue is prepared while the current one plays. Works for local files and for Qobuz and TIDAL streams — Roon sends those straight to your endpoint and never to an extension, so the track is fetched from the service with your own account, turned into 4,000 loudness values and discarded. The audio you are listening to is never touched, no audio is written to disk, and Roon still handles all playback. Anything the app can't identify keeps the plain bar.

Waveforms drawn for several 24-bit/192 kHz Qobuz albums, in real time. Each track is fetched, measured and discarded before it is needed; the stream Roon is playing is never read.

🎵Album discovery

A screen of random albums with filtering; Album of the day — the same album on every device from 00:01 until it is played anywhere, then a new one at the next 00:01; Random Album, one tap to choose an album you haven't heard in 12 months, then Play now, Play next or Queue (its disc turns slowly and spins up while it chooses); Not played in 6 months, which starts once there are six months of your listening to go on; and Label of the week. The database learns what you've heard and resurfaces forgotten albums.

📚Rich library browsing

Browse by album, artist, genre, record label, decade or tag — or open the Library row on Home and scroll your entire collection, with Sort and Focus, as a grid or a list (UI Settings). Dynamic Playlists and your playlists live in the side menu, with Import at the top of the Playlists screen. Tap an artist in an album to see all their albums, and the brass ‹ at the top left takes you back. Artwork is cached on the server, so even a large library scrolls smoothly without waiting on your Core.

🔍Powerful search

Instant whole-library search by album, artist or record label. When Qobuz or TIDAL is connected their catalogue results are added, along with Pitchfork reviews — browse the streaming catalogues and add favourites straight into your Roon library.

💿Detailed album pages

Edge-to-edge artwork, track listing with per-track Play now and Queue, release date, label, every credited artist as a link, a description of the record, and the Pitchfork score with a link to the review where there is one. Below it: more by the artist, the records they appear on, and similar artists and albums from Last.fm.

📺Full-screen wall display

Turn a TV or tablet into a now-playing display: big artwork, artist photography, biographies, reviews and “More from” grids from your library you can tap to play, with automatic rotation or one mode pinned.

🏷Record label explorer

Label of the week, label logos via Discogs and FanArt.tv, label merging with undo, every release from a selected label, and labels taken from your folder names if your library is filed that way.

📻Random Album Radio

When the queue finishes, the app picks another whole album and keeps the music flowing indefinitely. An album the radio played is not played by it again for six months, and among the rest it prefers ones you haven't played in 30 days.

▶Playback integration

Play or queue albums and tracks, multi-select, seek, shuffle, repeat and volume, move the queue between zones, group zones and power devices.

🎨Two themes, one look

Graphite and Brass (the default) and Brass light, both meeting the AA contrast standard: a greeting and today's date at the top of Home, section titles in small brass capitals, rounder covers, a mini player with a level meter and toasts that sit above it, and a ✓ in every API key box once the key has been accepted.

🔄Automatic updates

Checks GitHub for a new release at startup and every 7 days, with one-tap updates installed in place — on every install, the ready-made Docker image included.

Rouen + HQPWeb

For a Roon that plays through HQPlayer, Rouen has hqpweb built in — the web controller for HQPlayer by statelycurmudgeon. Rouen's HQPlayer screen is their work: how HQPlayer is talked to, every change checked and undone when it stops playback, the filter guide (the ratings in it are Signalyst's own), the modulator and dither guide and its sources, Find your DAC, presets, and finding and keeping several HQPlayers. Rouen carries it with thanks, under hqpweb's MIT licence, in Rouen's own look.

hqpweb's repository: github.com/statelycurmudgeon/hqpweb — its own README, changelog and releases, and the place to report anything about the HQPlayer side. Neither hqpweb nor Rouen plays music: both talk to HQPlayer through its published control protocol (TCP port 4321), and Roon sends HQPlayer the music.

Using it in Rouen

You need HQPlayer with control from the network allowed, on a computer the Rouen server can reach on TCP 4321. hqpweb has been tested with HQPlayer Desktop 5 and HQPlayer 6 Embedded; Desktop 6 and Windows are untested.

  1. Switch it on. ☰ → Settings → HQPlayer → HQPlayer control. It is off by default, and while it is off nothing connects to anything.
  2. Add your HQPlayer. Under Your HQPlayers, tap Find HQPlayers and Add the one you want — or type its address under Add by address (port 4321 unless you changed it), tap Test, then Add. Find uses multicast, so it sees HQPlayers on the Rouen server's own network, and only when Rouen runs with --network host (the standard install does). On macOS with Docker Desktop, on Unraid's br0, or for an HQPlayer on another VLAN, add it by address.
  3. Open ☰ → HQPlayer. Tap 1x filter, Nx filter or Modulator (Dither in PCM) to choose; a ✓ marks what HQPlayer reports is running. A choice HQPlayer's rules say won't play, or one that failed here before, is marked before you tap it. Undo puts back the last change; Presets saves and applies whole sets.
  4. Use the guide. Answer Your setup in Settings → HQPlayer, or the questions on the Modulator sheet's Guide tab; Find your DAC is under the PCM question in Settings → HQPlayer → Your setup.
  5. More than one HQPlayer? Add each one and switch with the HQPlayer picker at the top of the HQPlayer screen.
  6. More than one DAC behind one HQPlayer? Under Settings → HQPlayer → DACs, name each one with Add a DAC, and whenever you switch DACs in HQPlayer itself, choose the same one with the DAC picker — HQPlayer can't tell another app which DAC it is using. The guide's answers, the settings learned not to work and a DAC's own presets follow your choice.
Left to Roon and Rouen, on purpose: the volume (Rouen's own volume control is the one to use; a preset never raises HQPlayer's volume more than 6 dB at once, the automatic undo never raises it, and Undo returns to a louder level only if nobody has moved it since), play, pause, skip and seek, and setting the output rate and mode by hand (the guide's rate-and-modulator pairs and its Switch to PCM are the ways in). HQPlayer's profiles and output device can't be switched from Rouen or hqpweb — its control protocol doesn't allow it; use HQPlayer's own Client or HQPlayer Embedded's web page. No login: anyone who can reach Rouen or hqpweb can change HQPlayer, as anyone who can reach port 4321 already can — keep them on a network you trust, never on the internet.

Using hqpweb on its own

hqpweb also runs by itself, without Rouen, as a page of its own on port 4380 — everything above (named DACs arrive in its next release), plus HQPlayer's own volume, the output rate and mode, convolution, matrix profile, polarity, the 20 kHz filter, adaptive volume, seeking in files HQPlayer plays itself, and an optional link to Roon. It is in beta. These steps are from hqpweb's README (0.1.0-beta.3), which is always the current version.

  1. Docker on a machine that can reach HQPlayer on TCP 4321 (amd64 or arm64 — a Raspberry Pi 4/5, an ARM NAS, Apple Silicon).
  2. Run it with Docker Compose — save the first box as docker-compose.yml in a new folder and run docker compose up -d there — or with the docker run in the second (Synology, Unraid, Portainer).
  3. Open http://<that machine's IP>:4380 and go to Settings → General → Add to add your HQPlayer's address (leave the name blank to use HQPlayer's own). On a phone, Add to Home Screen makes it a full-screen app.
  4. Roon (optional): in hqpweb's Settings → Roon, switch it on and Find the Core (or enter its address, port 9330); in Roon → Settings → Extensions, enable hqpweb; then back in Settings → Roon, pick the Roon zone that feeds each HQPlayer. Its container must reach the Core on TCP 9330, and each install of hqpweb needs its own approval in Roon.
name: hqpweb
services:
  controller:
    image: ghcr.io/statelycurmudgeon/hqpweb:latest
    container_name: hqpweb
    restart: unless-stopped
    init: true
    ports:
      - "4380:4380"
    volumes:
      - config:/config # your instances, presets and settings
volumes:
  config:
docker run -d --name hqpweb --restart unless-stopped --init \
  -p 4380:4380 -v hqpweb_config:/config \
  ghcr.io/statelycurmudgeon/hqpweb:latest
Updating: docker compose pull && docker compose up -d — or docker pull ghcr.io/statelycurmudgeon/hqpweb:latest, then docker rm -f hqpweb and the same docker run; the hqpweb_config volume keeps your settings. Skim hqpweb's changelog first. Finding HQPlayers ("Scan now") uses multicast, so it needs host networking (Linux only) — hqpweb's README shows the override file that turns it on. Its other options (the image version to stay on, port, interface, host names behind a reverse proxy) are there too. Rouen uses port 3399 and hqpweb 4380, so the two don't collide on one machine.

Not affiliated with, endorsed by, or supported by Signalyst. HQPlayer is a trademark of its owner, used here only to identify compatible software.

Install with Docker

Pick where you're running the app, fill in the details, and copy the generated command. On Linux the app uses host networking so it can auto-discover your Roon Core; once it's running you enable it in Roon → Settings → Extensions.

A container runs on UTC unless told otherwise, which moves Album of the day (it turns over on the wrong midnight, and so does the “already played today” check that hides it) and the hour Smart Picks switches. The not played in 6 months and 12 months windows count elapsed time, not calendar days, so they read the same in any zone. Pre-filled from this browser.
All three are optional — Discogs and FanArt.tv improve label logos and artwork, Last.fm adds similar artists and albums to the album view. See API keys below for where to get them. You can skip them here and paste them into Settings after first launch instead; a key saved there always wins over one set at install.
# Run it — --pull always fetches the current release every time this runs
docker run -d \
  --name musicd-remote \
  --pull always \
  --restart unless-stopped \
  --network host \
  -e TZ=Etc/UTC \
  -v musicd-remote-data:/app/data \
  -v "/your/path/to/Music:/music:ro" \
  ghcr.io/meltface-80/musicd-remote:latest

Installing v1.9.66 (checking for the latest release…). If your user isn't in the docker group, prefix the docker commands with sudo. Needs Docker 20.10 or later, the first whose docker run takes --pull.

One volume to rule them all. The musicd-remote-data volume holds your Roon pairing, play history and label cache — never rename it once created. A different name silently starts empty (Roon asks you to authorize again and your history is gone). Upgrading from v1.6.31 or earlier? Move your data once with the copy step in the Updating guide.
Already running Rouen (or MusicD Remote, its old name)? Nothing to uninstall and nothing to re-pair: docker stop musicd-remote && docker rm musicd-remote, then run the command above with the same volume. Your Roon pairing, history and settings carry over. From then on, updates are one tap in the app.

Unraid

Roon never shows Rouen under Settings → Extensions? On Unraid the usual cause is the network, not the app.

Why. On Unraid, Roon Server normally runs on the br0 custom network (macvlan/ipvlan) with an IP address of its own, which is what RAAT needs. A container on --network host sits on Unraid's own interface instead, and Unraid's kernel keeps the two apart: the discovery broadcast never reaches the Core, and by default the host cannot even open a connection to a br0 address. The fix is to put Rouen on br0 too, with its own free IP, and tell it where the Core is with ROON_CORE_IP, which connects straight to the Core instead of discovering it.

  1. Pick two addresses. ROON_CORE_IP is your Roon Core container's br0 IP (Roon → Settings → General shows it). Rouen needs a different one: a free address on your LAN, outside your router's DHCP range. The examples use 192.168.1.50 for Roon and 192.168.1.60 for Rouen.
  2. Run it with Compose (the Docker Compose Manager plugin) or docker run, below. Change the music path to your share and name: br0 to your custom network's name if it differs.
  3. Open the app at Rouen's own address, http://192.168.1.60:3399 (not the Unraid server's), then click Enable in Roon → Settings → Extensions.
services:
  musicd-remote:
    image: ghcr.io/meltface-80/musicd-remote:latest
    pull_policy: always
    container_name: musicd-remote
    restart: unless-stopped
    networks:
      br0_net:
        ipv4_address: 192.168.1.60   # a free address for Rouen
    environment:
      TZ: "Europe/London"
      ROON_CORE_IP: "192.168.1.50"   # your Roon Core's br0 address
    volumes:
      - /mnt/user/appdata/musicd-remote:/app/data
      - /mnt/user/data/media/music:/music:ro

networks:
  br0_net:
    external: true
    name: br0   # your Unraid custom network
docker run -d \
  --name musicd-remote \
  --pull always \
  --restart unless-stopped \
  --network br0 \
  --ip 192.168.1.60 \
  -e TZ=Europe/London \
  -e ROON_CORE_IP=192.168.1.50 \
  -v /mnt/user/appdata/musicd-remote:/app/data \
  -v /mnt/user/data/media/music:/music:ro \
  ghcr.io/meltface-80/musicd-remote:latest
Check it reached the Core. Once Rouen is enabled in Roon, docker logs musicd-remote shows [roon] paired with core …. A line [roon] cannot reach Roon Core at 192.168.1.50:9330 — retrying every 10s means the address is wrong or blocked; it keeps retrying, so nothing needs restarting once it is fixed. The image has no ping; this tests the Core's port from inside the container:
docker exec musicd-remote node -e "require('net').connect(9330,'192.168.1.50').on('connect',()=>{console.log('reachable');process.exit()}).on('error',e=>{console.log(e.message);process.exit(1)})"
Rather keep host networking? Set ROON_CORE_IP anyway, and let the host reach br0: Settings → Docker, stop the Docker service, set Host access to custom networks to Enabled, start it again. The app is then on the Unraid server's own address.
Your data. These examples keep Rouen's data in /mnt/user/appdata/musicd-remote, Unraid's usual place. If you already ran it with the musicd-remote-data volume, use -v musicd-remote-data:/app/data instead (or copy the volume's contents into the folder first), or Roon will ask you to authorize Rouen again and your history starts empty.

Thanks to the Unraid user who worked this out and shared it.

API keys

All free, all optional — but they significantly improve artwork and label coverage, and Last.fm adds similar artists and albums to every album page. Paste each one into the app under ☰ → Settings → Setup → API Keys, then Save — the box shows a ✓ once the service has accepted the key. Label logos also need Settings → Setup → Record labels switched on.

Free

FanArt.tv

Record-label logos for labels that have a MusicBrainz MBID, and the wall display's artist photos.

  1. Register (or sign in) at fanart.tv/get-an-api-key and request a personal API key
  2. Follow the on-screen prompts — the key is shown on that page once you're logged in
  3. Copy the key
  4. In the app: ☰ → Settings → Setup → API Keys → paste into FanArt.tv key → Save (a ✓ shows it works)
Free

Discogs

Finds label names that iTunes and MusicBrainz miss, and fetches label logos.

  1. Sign in (or register) at discogs.com
  2. Settings → Developers → Generate new token
  3. Copy the token
  4. In the app: ☰ → Settings → Setup → API Keys → paste into Discogs token → Save (a ✓ shows it works)
Free

Last.fm

Similar artists and similar albums at the foot of every album page — opened in the app when they are in your library, on Last.fm when not. Read-only — nothing is scrobbled.

  1. Sign in at last.fm, or sign up free — any Last.fm account will do
  2. Open last.fm/api/account/create (the Get an API account link on last.fm/api)
  3. Fill in your email, an application name (e.g. Rouen) and a short description; the callback URL and homepage can be left empty
  4. Submit, then copy the API key — not the shared secret, which isn't needed
  5. In the app: ☰ → Settings → Setup → API Keys → paste into Last.fm key → Save (a ✓ shows it works)

Lost it? Your keys are listed at last.fm/api/accounts.

Environment variables

Everything the container understands — the configurator above sets the ones you need.

VariableDefaultPurpose
PORT3399HTTP port for this app
ROON_CORE_IP(discover)Roon Core address for setups where multicast discovery can't reach it — macOS / Docker Desktop, or a Core on its own network such as Unraid's br0 (see Unraid). The extension then connects straight to the Core
ROON_CORE_PORT9330Roon Core API port used with ROON_CORE_IP — only change it if your Core runs its API on a non-standard port
MUSIC_DIR/musicWhere the optional read-only music mount lives inside the container — the scan reads everything under it, so several folders can be mounted as subdirectories. Used for file-tag labels, release dates, local waveforms, the local-files badge and the format filters
TZEtc/UTCThe container's local time. Sets when Album of the day turns over (00:01) and the hour Smart Picks and Discover run. The 6- and 12-month "not played" windows are counted in absolute time and are unaffected
RRA_DISCOGS_KEY(unset)Seeds the Discogs token on a fresh data volume, so label logos work from the first scan. A token saved in Settings wins over it, and an env-seeded one is not written to disk — unset the variable and the key is gone
RRA_FANART_KEY(unset)Seeds the FanArt.tv key the same way
RRA_LASTFM_KEY(unset)Seeds the Last.fm API key the same way
RRA_DEBUGon in DockerVerbose logging (timestamps, Roon API call traces with durations). On by default inside Docker — 0 for quiet logs

First run

The container is up — four steps and you're listening.

  1. Enable the extension in Roon. Roon → Settings → Extensions — Rouen (publisher MusicD) appears there once the container is running. Click Enable.
  2. Open the app. Browse to http://<your-server-ip>:3399 from any phone, tablet or desktop on your network. Add it to your home screen for an app-like experience.
  3. Add your API keys. ☰ → Settings → Setup → API Keys → paste in the keys from above. For labels, switch on Settings → Setup → Record labels and let the label scan run.
  4. Optional: wall display and Shelf. Switch on Settings → Wall Display, then point a TV or spare tablet at http://<your-server-ip>:3399/display. Shelf needs no switch: http://<your-server-ip>:3399/shelf flicks through your covers.

Uninstall

Find how you installed Rouen below. Each way removes three things: the container (or service), the image, and the data — your Roon pairing, play history, settings, playlists, Listen later, API keys, the Qobuz and TIDAL sign-ins, backups and logs, all kept in one place. Your music is never touched: the /music mount is read-only.

Want to keep anything? Skip the step that deletes the data, and a later install pointed at the same volume or folder carries on where this one stopped. Or take a backup first: ☰ → Settings → Backup & restore → Back up now, then Download. It carries settings, playlists, Listen later and keys (not play history or the Roon pairing), and Restore from a file… brings it back. If your user isn't in the docker group, put sudo in front of each docker command.

Docker (docker run) — Linux, NAS, macOS, Windows

# 1. Stop and remove the container
docker rm -f musicd-remote

# 2. Delete the data volume (skip to keep it)
docker volume rm musicd-remote-data

# 3. Remove the image — list first: there may be more than one tag
docker images ghcr.io/meltface-80/musicd-remote
docker image rm ghcr.io/meltface-80/musicd-remote:latest
More than one image? docker images can list more than latest: a version or -test tag you pulled to try a build, or older copies marked <none> that updates left behind. Remove each the same way, by its tag or by its IMAGE ID. If the configurator wrote a .env file, delete it too — it holds your API keys in plain text.
Synology Container Manager, Portainer and the like: delete the musicd-remote container, then the image and the musicd-remote-data volume, from their own pages — or run the commands above over SSH. macOS: the same commands, in Terminal. If you installed Docker Desktop only for Rouen, it can go too: Docker Desktop's Troubleshoot menu has Uninstall, then drag Docker from Applications to the Bin.

Docker Compose

# in the folder that holds your docker-compose.yml:
# stop and remove the container, and delete its data volume
# (to keep the data, leave out -v)
docker compose down -v

# remove the image
docker image rm ghcr.io/meltface-80/musicd-remote:latest
Then delete docker-compose.yml and .env from that folder (the .env holds your API keys). Compose names the volume after the folder — musicd-remote_musicd-remote-data, say — which is why down -v is the way to remove it; docker volume ls shows the exact name if you'd rather remove it by hand.

Unraid

docker rm -f musicd-remote
rm -rf /mnt/user/appdata/musicd-remote    # the data folder (skip to keep it)
docker image rm ghcr.io/meltface-80/musicd-remote:latest
If you ran it with the Docker Compose Manager plugin, also delete the stack there, or its next Compose Up brings Rouen back. If you set Host access to custom networks to Enabled only for Rouen, you can set it back under Settings → Docker (stop the Docker service first). If you used the musicd-remote-data volume rather than the appdata folder, remove that with docker volume rm musicd-remote-data instead.

Native install (before Docker)

sudo systemctl disable --now roon-random-albums
sudo rm /etc/systemd/system/roon-random-albums.service
sudo systemctl daemon-reload

# The install folder: the code, and data/ with your pairing and history.
# /opt/roon-random-albums unless you put it elsewhere — to find it:
#   find / -name "roon-random-albums" -type d 2>/dev/null
sudo rm -rf /opt/roon-random-albums
The original install ran on Node.js as a systemd service. Node.js stays installed; remove it with your package manager only if nothing else needs it.

Leftovers, hqpweb, and afterwards

  1. Built-from-download images (before v1.8.70): docker images musicd-remote lists them, docker image rm musicd-remote:<version> removes each, and the /opt/musicd-remote folder can go.
  2. Roon Random Albums (v1.6.31 and earlier): docker rm -f roon-random-albums, docker volume rm roon-random-albums-data, and the /opt/roon-random-albums folder.
  3. alpine, if you ran one of the README's copy steps: docker image rm alpine, if nothing else of yours uses it.
  4. hqpweb on its own (above): with Compose, docker compose down -v in its folder; with docker run, docker rm -f hqpweb then docker volume rm hqpweb_config. Then docker image rm ghcr.io/statelycurmudgeon/hqpweb:latest, and delete its folder. hqpweb's README is the authority on it.
  5. Roon — nothing to remove. Once Rouen is no longer running it drops out of Settings → Extensions. Albums added to your library through Rouen (Qobuz and TIDAL favourites, Smart Picks) stay, because they are in your library now; HQPlayer keeps the settings it was last given.
  6. Phones and tablets — delete the Home Screen icon (press and hold it → Remove App or Delete). The preferences each browser kept for the app (theme, zone, layout) do nothing without the server; clear that site's data in the browser to remove them.
  7. API keys — the Discogs, FanArt.tv and Last.fm keys belong to your accounts on those sites; delete them there if you no longer want them.