The way to an own clowd - Part 13
Music today has almost completely moved into streaming. Services like Spotify, Apple Music or Deezer are convenient – but they come at a price: you pay twice.
On the one hand with money, on the other hand with your own data and dependency on the provider. If the service raises prices tomorrow or a favorite album disappears, you are powerless.
The best solution is as before: own and host your music yourself. With open formats (MP3, FLAC, OGG, …) and a tool like Navidrome you can build your very own personal streaming service.
Setup
The service requires two directories: One for the application and one for the music files:
sudo mkdir -p /opt/music
sudo mkdir -p /opt/navidrome
The music files will later be copied into the directory /opt/music
.
As with the other services, Navidrome should again get its own random port:
echo $(shuf -i 1024-65535 -n 1)
In the application directory create the file docker-compose.yaml
:
services:
navidrome:
image: localhost:5000/deluan/navidrome:latest
container_name: navidrome
restart: unless-stopped
ports:
- "4533:4533"
environment:
- ND_SCANINTERVAL=1m
- ND_LOGLEVEL=info
- ND_BASEURL=https://<CLOUD-DOMAIN>:<RANDOM-PORT>
volumes:
- /opt/music:/music:ro
- ./data:/data
Before the container can be started, the image must be mirrored from the official container hub:
docker pull deluan/navidrome:latest
docker tag deluan/navidrome:latest localhost:5000/deluan/navidrome:latest
docker push localhost:5000/deluan/navidrome:latest
Now the service can be started:
docker compose up -d
For external communication NGINX needs an additional configuration called navidrome
under /etc/nginx/sites-available
:
server {
listen <RANDOM-PORT> ssl;
server_name <CLOUD-DOMAIN>;
ssl_certificate /etc/letsencrypt/live/<CLOUD-DOMAIN>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<CLOUD-DOMAIN>/privkey.pem;
client_max_body_size 256M;
location / {
proxy_pass http://localhost:4533;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable and restart:
sudo ln -s /etc/nginx/sites-available/navidrome /etc/nginx/sites-enabled/
sudo systemctl restart nginx
After opening the firewall on the port:
sudo ufw allow <RANDOM-PORT>
sudo ufw reload
the web interface should be reachable at https://<CLOUD-DOMAIN>:<RANDOM-PORT>
Apps
A list of compatible apps for all common operating systems 👉 https://www.navidrome.org/docs/overview/#apps
Backups
Navidrome stores important data (users, playlists, settings) in the data
directory. This should definitely be backed up regularly.
Simply create a plugin under /opt/backup/plugins/navidrome.sh
:
#!/bin/bash
PLUGIN_OUTPUT_DIR="$1"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S.%3N')] $*"
}
NAVIDROME_DIR="/opt/navidrome/data"
BACKUP_FILE="$PLUGIN_OUTPUT_DIR/navidrome_data_$(date '+%Y-%m-%d').tar.gz"
log "[INFO] Starting backup of Navidrome data ..."
tar -czf "$BACKUP_FILE" -C "$NAVIDROME_DIR" .
if [ $? -eq 0 ]; then
log "[INFO] Backup successful: $BACKUP_FILE"
else
log "[ERROR] Backup failed!"
fi
And make it executable:
chmod +x /opt/backup/plugins/navidrome.sh
Quick & Dirty
DOMAIN=cloud.example.com
PORT=$(shuf -i 1024-65535 -n 1)
sudo mkdir -p /opt/music /opt/navidrome
cat <<EOF > /opt/navidrome/docker-compose.yaml
services:
navidrome:
image: localhost:5000/deluan/navidrome:latest
container_name: navidrome
restart: unless-stopped
ports:
- "4533:4533"
environment:
- ND_BASEURL=https://$DOMAIN:$PORT
volumes:
- /opt/music:/music:ro
- ./data:/data
EOF
docker pull deluan/navidrome:latest
docker tag deluan/navidrome:latest localhost:5000/deluan/navidrome:latest
docker push localhost:5000/deluan/navidrome:latest
docker compose -f /opt/navidrome/docker-compose.yaml up -d
sudo tee /etc/nginx/sites-available/navidrome >/dev/null <<EONGX
server {
listen $PORT ssl;
server_name $DOMAIN;
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
client_max_body_size 256M;
location / {
proxy_pass http://localhost:4533;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EONGX
sudo ln -s /etc/nginx/sites-available/navidrome /etc/nginx/sites-enabled/
sudo systemctl restart nginx
sudo ufw allow $PORT && sudo ufw reload