User Tools

Site Tools


computing:navidrome

This is an old revision of the document!



  • Navidrome Setup
  • oemb1905
  • gnulinux.studio
  • webmaster@gnulinux.studio

navidromesetup


This tutorial is for Debian Trixie users seeking to set up a production-ready Navidrome server. I used virsh+qemu to make a VM with 8TB of storage, and the VM is set up with a LAMP stack, a reverse proxy with Let's Encrypt, automated syncing, scanning, and some hardening measures. Im using fpm with the mpm_event handler for concurrency. My standard fail2ban setup is in place for protection. This instance is designed for public listening. The library is imaged off my master library via a remote source and includes aggressive cover art fetching.

Initial VM Prep and Navidrome Installation

sudo apt update && sudo apt upgrade -y
sudo apt install ffmpeg wget nano curl snapd ufw fail2ban postfix apache2 php8.4-fpm php8.4-mysql php8.4-curl php8.4-gd php8.4-mbstring php8.4-xml php8.4-zip

Download and install Navidrome:

wget https://github.com/navidrome/navidrome/releases/download/v0.54.1/navidrome_0.54.1_linux_amd64.deb
sudo apt install ./navidrome_0.54.1_linux_amd64.deb

Set up music dir:

sudo mkdir -p /opt/navidrome/music
sudo chown -R navidrome:navidrome /opt/navidrome/music
sudo find /opt/navidrome/music -type d -exec chmod 755 {} +
sudo find /opt/navidrome/music -type f -exec chmod 644 {} +

Apache Reverse Proxy and Let's Encrypt and associated modules:

sudo a2enmod proxy proxy_http ssl headers rewrite proxy_fcgi setenvif
sudo a2enconf php8.4-fpm
sudo a2dismod mpm_prefork php8.4
sudo a2enmod mpm_event

Create vhost nano /etc/apache2/sites-available/gnulinux.studio.conf:

<VirtualHost *:80>
    ServerName gnulinux.studio
    Redirect permanent / https://gnulinux.studio/
</VirtualHost>
<VirtualHost *:443>
    ServerName gnulinux.studio
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/gnulinux.studio/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/gnulinux.studio/privkey.pem
    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass / http://127.0.0.1:4533/
    ProxyPassReverse / http://127.0.0.1:4533/
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost/"
    </FilesMatch>
    <Location />
        Require all granted
    </Location>
    RequestHeader set X-Real-IP %{REMOTE_ADDR}s
    RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Frame-Options "SAMEORIGIN"
</VirtualHost>

Enable site and Certbot:

sudo a2ensite gnulinux.studio.conf

sudo apache2ctl configtest
sudo apt install certbot letsencrypt python3-certbot-apache
sudo certbot --authenticator standalone --installer apache -d gnulinux.studio --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2"

Tune mpm_event in nano /etc/apache2/mods-available/mpm_event.conf, assuming 8 cores and an upper limit of 400 workers:

StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
ServerLimit 16

Once you've adjusted this, restart apache with sudo systemctl restart apache2. Make sure fpm is tweaked by heading to nano /etc/php/8.4/fpm/pool.d/www.conf and adjust servers as follows:

pm = dynamic
pm.max_children = 200
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 20
pm.max_requests = 1000
request_terminate_timeout = 300s

Once you enter the adjustments test fpm and restart the service as follows: sudo php-fpm8.4 -t && sudo systemctl restart php8.4-fpm. It's now time to edit the main Navidrome configuration file. Let's open nano /etc/navidrome/navidrome.toml as follows:

DataFolder = "/var/lib/navidrome"
MusicFolder = "/opt/navidrome/music"
Address = "127.0.0.1"
Port = 4533
BaseUrl = "https://gnulinux.studio"
ShareURL = "https://gnulinux.studio"
EnableUserEditing = false
EnableDownloads = false
ImportPlaylists = false
LogLevel = "info"
LogFile = "/var/log/navidrome/navidrome.log"
[Scanner]
Enabled = true
Schedule = "@every 24h"
WatcherWait = "5s"
ScanOnStartup = true
[CoverArt]
Enabled = true
Embed = true
CacheSize = "2GB"
Sources = ["embedded", "folder", "metadata"]
Priority = ["embedded", "folder", "metadata"]

Let's restart the navidrome service and check its status sudo systemctl enable –now navidrome and then systemctl status navidrome. To manually scan your library, do the following:

cd /var/lib/navidrome
sudo -u navidrome navidrome scan -f

In my case, the navidrome instance is for public listening, and my master library is managed through Airsonic Advanced on a different server. I also use Picard from musicbrainz.org to edit my tags, and even RhythmBox comes in handy from time to time. All of these tools, however, edit a common master file source that's synced with Nextcloud and editable by Airsonic Advanced. It's that library, which I use a cronjob for to pull over to Navidrome, ensuring that Navidrome continues to be a live mirror of my Master Library, or Masters. Let's create a script nano /usr/local/bin/sync-music.sh and make it executable sudo chmod 750 /usr/local/bin/sync-music.sh that does all this:

#!/bin/bash
SOURCE="root@mail.outsidebox.club:/mnt/Storage/obdata/oemb1905/files/Masters/*"
DEST="/opt/navidrome/music/"
LOG="/root/logs/rsync-music.log"
touch /tmp/sync-music.lock
echo "$(date): Starting music sync..." >> "$LOG"
sudo rsync -ai --log-file=/root/logs/rsync-music.log --delete --chown=navidrome:navidrome root@mail.outsidebox.club:/mnt/Storage/obdata/oemb1905/files/Masters/* /opt/navidrome/music/
echo "$(date): Music sync completed." >> "$LOG"
rm /tmp/sync-music.lock

Let's run this via cron every 2 hours:

0 */2 * * * /usr/bin/flock --nonblock /tmp/sync-music.lock /bin/bash /usr/local/bin/sync-music.sh >> /root/logs/rsync-music.log

Fail2Ban needs to be setup. Users should be familiar with how to do that and can refer to my wiki entry if they need help with basic setup. Here, I am covering how to setup a custom Navidrome jail for extra protection. One should additionally enable the apache protections, sshd, dropbear and/or whatever their instance might benefit from. Let's open nano /etc/fail2ban/jail.local and add a jail:

[navidrome]
enabled = true
backend = systemd
filter = navidrome
maxretry = 5
findtime = 600
bantime = 3600

Next, let's create rules for this jail in its configuration file nano /etc/fail2ban/filter.d/navidrome.conf:

[Definition]
failregex = ^.*msg="Unsuccessful login".*(X-Real-Ip|X-Forwarded-For):\s*\[<HOST>\].*$
ignoreregex =
journalmatch = _SYSTEMD_UNIT=navidrome.service + _TRANSPORT=stderr

After everything is built, let's restart fail2ban sudo systemctl restart fail2ban. For upgradind, simply wget the new image and then sudo apt install ./new.deb.

oemb1905 2025/10/29 02:18

computing/navidrome.1761705616.txt.gz · Last modified: by oemb1905