Fully verified23,239

Editorial pickMusic

Navidrome

Navidrome turns a folder of music into a personal streaming service: it reads tags and artwork, remembers your listening history, and serves the collection to the browser and to dozens of mobile apps through the Subsonic API. One container, an SQLite database, no subscription.

Overview

Navidrome is a music server for a collection that lives as files. It reads tags and artwork, builds a library by artist and album, remembers ratings, playlists, and listening history, and streams to a browser or a phone. It fits anyone who spent years collecting music and would rather not watch tracks vanish from a subscription catalogue.

The key feature is the Subsonic API: the project ships no mobile apps of its own, but there are dozens of compatible clients, from Symfonium and substreamer on Android to play:Sub on iOS and Feishin on the desktop. The server is written in Go, fits in a single container, and runs on hardware as small as a Raspberry Pi.

The recipe mounts the music directory read-only and keeps the database, artwork, and history in a separate Docker volume. The reliable level is not claimed: Navidrome uses embedded SQLite, and the recipe adds no monitoring and no resource limits.

Anonymous usage statistics are disabled in this recipe (NAVIDROME_INSIGHTS=false). One variable turns them back on if you want to support the project with data.

Security assessment

The container runs without privileged, host networking, or Docker socket access, and uses no-new-privileges; only the web port is published, and only on 127.0.0.1. The music library is mounted read-only, so the server cannot modify or delete your files.

The main risk is the first start: until the administrator account exists, the setup form is open to whoever reaches it, so the port must stay unexposed until you have created it. The second is the protocol itself: the Subsonic API sends credentials with every request, and some clients still send the password in clear text, so the server may only be published over HTTPS. The container runs as root, as in the upstream image; if that matters, set user: and adjust volume ownership yourself.

The recipe image is scanned with Trivy and has no critical findings. That is what you would expect from an image made of Alpine plus a single statically linked Go binary.

Update tracking

These are stored results of separate checks, not real-time data. An unknown status means the check has not been performed yet.

New releases

Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.

Current version v0.63.2Aug 31, 2026, 4:17 AM UTC

Critical vulnerabilities

Result of a dedicated Docker image scan, not a Compose configuration check.

No critical vulnerabilities foundAug 31, 2026, 8:36 AM UTC

Breaking updates

A new major version is found by comparing version numbers. A compatibility verdict is entered by hand after reading the release notes and the migration steps.

Not checkedNot checked

compose.yaml

Upstream Compose changes relative to the verified recipe.

Upstream Compose is not trackedNot checked

Outdated Docker images

Pinned image tags checked for newer versions.

All images are currentAug 31, 2026, 8:36 AM UTC

From observation to action

Update plan

The recipe already pins the latest known release. The steps below show the evidence retained for that version.

v0.63.2v0.63.2
  1. Open the release evidence

    Open this release on GitHub ↗ The link is evidence to review, not proof of compatibility.

  2. Review the version boundary

    The version numbers do not cross a major compatibility boundary. No compatibility verdict has been recorded.

  3. Prepare image-tag changes

    No image-tag change is currently planned.

  4. Follow the documented migration shape

    Change the tag and restart. Release-specific migration steps still come from the release notes and installation guide.

  5. Protect the rollback point

    No version change is currently planned. The recipe includes a backup procedure. Restore has been tested.

  6. Verify the updated recipe

    An exact Fully verified check for this target was recorded on 2026-08-31.

Read the update procedure in the installation guide ↓

Specifications

Security and exposure

Installation levels

The status shows how fully the published recipe meets each level's requirements.

Ready

For home

A minimal setup for a local network or access through a VPN.

  • Single server
  • Local access
  • Minimum components

The recipe covers every requirement at this level.

Ready

For a VPS

A public deployment with protected access and backups.

  • Domain
  • HTTPS via reverse proxy
  • Off-server backup

The recipe covers every requirement at this level.

Not supported

Reliable

A setup designed for predictable operations and observability.

  • Separate database
  • Healthcheck
  • External monitoring
  • CPU and memory limits

You still need to add: separate database, external monitoring, cpu and memory limits.

Tailored to your server

Configuration generator

Answer five questions and download a ready-to-run Navidrome bundle.

Runs locally
01 Do you have a domain?
02 Which reverse proxy?
03 Server architecture
04 Where should data be stored?

Use an absolute path for a separate disk, such as /srv/navidrome.

Mounted read-only: the server cannot modify or delete your files.

05 Is VPN access required?

Your bundle is ready

The archive is created in your browser. Your answers are never sent anywhere.

Screenshots

Screenshots have not been added yet.

Quick start

Read the full guide first: it explains external access, backups, and data locations.

Prepare settingscp .env.example .env
Launchdocker compose up -d
Check statusdocker compose ps

Step-by-step guide

1. Check your Ubuntu or Debian server

This recipe needs 1 CPU core, 256 MB of RAM, and 2 GB of disk for the server itself; 512 MB of RAM is recommended. This is a conservative estimate for the recipe: upstream publishes no formal minimum. Count storage for the music separately, plus a few percent for the artwork cache. You need Ubuntu 22.04+ or Debian 12+ with Docker Engine and Docker Compose v2.24+.

docker --version
docker compose version

2. Prepare the music library

Navidrome reads tags, not file names, so filled-in Artist, Album, Title, and track number matter most. The directory layout is up to you, but artist/album is the most convenient:

/srv/music/Artist Name/Album Name (2019)/01 Track.mp3
/srv/music/Artist Name/Album Name (2019)/cover.jpg

Navidrome takes artwork from the tag or from a cover.jpg, folder.jpg, or front.jpg file next to the tracks. MP3, FLAC, OGG, Opus, M4A, WavPack, and other formats understood by the bundled ffmpeg are supported.

3. Prepare the files and variables

mkdir -p ~/services/navidrome
cd ~/services/navidrome
cp .env.example .env
chmod 600 .env
sed -i "s|^NAVIDROME_MUSIC_LOCATION=.*|NAVIDROME_MUSIC_LOCATION=/srv/music|" .env

NAVIDROME_VERSION pins the image; NAVIDROME_PORT sets the local port; NAVIDROME_MUSIC_LOCATION is the music directory, mounted read-only; NAVIDROME_DATA_VOLUME is the volume with the database, artwork, and listening history; NAVIDROME_SCAN_INTERVAL controls automatic scans; NAVIDROME_LOG_LEVEL and NAVIDROME_SESSION_TIMEOUT cover logging and session lifetime; NAVIDROME_BASE_URL is only needed when the service is published under a subpath; NAVIDROME_INSIGHTS controls anonymous usage statistics and is off by default; TZ sets the time zone.

4. Create the administrator

The administrator form has no password: whoever opens it first owns the server. Run the first start over localhost or an SSH tunnel.

docker compose pull
docker compose up -d
docker compose ps
ssh -L 4533:127.0.0.1:4533 user@server.example

Open http://localhost:4533 and set a username and password. The first scan starts right after; the container log shows how many tracks were imported:

docker compose logs --tail=50 navidrome | grep -i scanner

The administrator creates the other users under Users. Mobile and desktop clients are third-party: they connect to the same address through the Subsonic API.

Running on a VPS

On a VPS keep the 127.0.0.1 bind, block port 4533 from outside, and publish the service only through an HTTPS reverse proxy. Check the state and the API:

docker compose up -d
docker compose ps
curl --fail http://127.0.0.1:4533/ping
curl --fail "http://127.0.0.1:4533/rest/ping?v=1.16.1&c=check&f=json"

The second request answers with an authentication error — that is expected: it confirms the Subsonic API is serving and reports the server version.

Access from a local network

Without TLS use an SSH tunnel or a VPN. If the reverse proxy runs on another host in a trusted LAN, replace 127.0.0.1 in compose.yaml with the server’s LAN address and restrict the port to the proxy address in the firewall. Do not publish Navidrome on 0.0.0.0 without restrictions: the Subsonic API sends credentials with every request.

Domain and HTTPS

Replace music.example.com with your single domain in the file you pick from proxy/. proxy/Caddyfile obtains a certificate automatically; proxy/nginx.conf expects a Certbot certificate; proxy/traefik.yaml uses the letsencrypt resolver. For Traefik in a container, replace 127.0.0.1 with a host gateway it can reach.

The Nginx sample disables response buffering: without it, seeking inside a track stutters. If the service is published below the domain root, set the same subpath in NAVIDROME_BASE_URL, otherwise the web interface cannot find its own files.

curl --fail https://music.example.com/ping

Backup

chmod +x backup.sh restore.sh
./backup.sh

The script stops the container, archives the /data volume, and starts it again. Stopping is required: the SQLite database copies consistently only from a stopped server. The archive holds users, playlists, ratings, listening history, and the artwork cache.

The music is not in the archive: those are your own files and need their own copy.

Navidrome also has its own mechanism — docker compose exec navidrome /app/navidrome backup create --datafolder /data snapshots the database without stopping the server. It is handy before an update, and it ends up inside the copy that backup.sh makes.

Restore

Restoring replaces the contents of /data with the selected archive:

./restore.sh ./backups/navidrome-YYYYMMDDTHHMMSSZ.tar.gz
docker compose ps
curl --fail http://127.0.0.1:4533/ping

Before replacing anything the script takes a safety copy of the current data. The music is untouched, but the paths in the restored database must match the current /music mount, otherwise tracks are marked as missing until the next scan.

Update

Take a backup and read the release notes. Change only the pinned NAVIDROME_VERSION, then run:

./backup.sh
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 navidrome

Database migrations run the first time a new version starts. Larger updates sometimes require a full library rescan; the release notes say so when they do.

Rollback

Downgrades are not supported: after a migration the older image cannot open the database. Restore the pinned NAVIDROME_VERSION in .env and restore the archive taken before the update:

docker compose pull
./restore.sh ./backups/navidrome-before-update.tar.gz
docker compose up -d

Ratings and listening history created after the update are not in that archive.

Stopping and complete removal

docker compose down removes the container but keeps the database. Complete, irreversible removal after verifying a backup:

docker compose down
docker volume rm navidrome-data
rm -rf ~/services/navidrome

The NAVIDROME_MUSIC_LOCATION directory stays untouched: the recipe mounts it read-only and never deletes from it.

Sources: Docker installation, configuration options, artwork and tags, backup and restore, anonymous statistics, and security recommendations.

Troubleshooting

The library is empty after startup

Check that the directory is visible inside the container and that the scan finished:

docker compose exec navidrome ls -la /music
docker compose logs --tail=100 navidrome | grep -i scanner

An empty result with a visible directory almost always means missing tags: Navidrome builds the library from Artist, Album, and Title, not from file names. Inspect the tags of a single file with the built-in command:

docker compose exec navidrome /app/navidrome inspect "/music/path/to/file.mp3"

New files do not show up

By default the recipe scans once a day (NAVIDROME_SCAN_INTERVAL). Trigger a scan immediately from the web interface with the refresh button, or run:

docker compose exec navidrome /app/navidrome scan --datafolder /data

No artwork

Artwork comes from the tag or from a cover.jpg, folder.jpg, or front.jpg file next to the tracks. Make sure the file sits in the album directory and is readable. The artwork cache lives in the /data volume and rebuilds itself.

One album is split into several

This happens with compilations that have no Album Artist tag. Set the same Album Artist on every track of the album (for example Various Artists) and run a rescan.

A Subsonic client cannot connect

The client needs the server address without /app, a username, and a password. Check that the API answers:

curl --fail "https://music.example.com/rest/ping?v=1.16.1&c=check&f=json"

An authentication error means the API works. No answer at all points at the reverse proxy or at NAVIDROME_BASE_URL.

The web interface loads without styles

That happens when Navidrome is published under a subpath and NAVIDROME_BASE_URL is not set. Use the same path as in the reverse proxy and restart the container.

Seeking inside a track stutters

The reverse proxy is buffering the response. Nginx needs proxy_buffering off, which the sample in proxy/ already has. Caddy and Traefik stream without buffering.

The administrator password was lost

Change it with a command inside the container:

docker compose exec navidrome /app/navidrome user edit --datafolder /data

The command is interactive, so run it from a terminal with a TTY.

The server does not start after an update

docker compose logs --tail=200 navidrome | grep -i "migration\|error"

Downgrades are not supported: the only way back is restoring the archive taken before the update.

Official sources

Latest release: 2026-07-11 · GitHub Stars: 23,239 · metadata checked Aug 31, 2026, 4:17 AM UTC

Disclaimer

Fossary is an independent informational catalog and is not affiliated with the developers of the listed applications. We collect information from public sources and verify published recipes, but we do not develop, distribute, or control these applications.

A listing or validation status is not a requirement, endorsement, or personal recommendation to use an application. You decide whether it is suitable and use it at your own risk. We do not warrant an application's security, availability, or fitness for purpose and, to the extent permitted by law, are not liable for resulting loss or damage. Review its license, security settings, data processing, and backup procedures before installation.