Navidrome Playlists Backup
This role backs up Navidrome music playlists using the Navidrome API.
Navidrome Playlists Backup Role
Overview
This role backs up Navidrome music playlists using the Navidrome API. It authenticates to Navidrome, downloads each playlist as M3U files, and stores them on dual NAS storage with dated directories for organization. The role automatically manages retention by keeping only the last 5 backup directories per NAS.
Purpose
- Playlist Protection: Backs up curated music playlists
- Migration Support: Export playlists for transferring to new Navidrome instance
- Disaster Recovery: Restore playlists after data loss
- Dual Redundancy: Backs up to two separate NAS devices (Synology DS418 and Proxmox OMV)
- Dated Organization: Groups backups by date for easy identification
- API-Based: Uses Navidrome’s native API with JWT authentication
Requirements
- Ansible 2.9 or higher
- Navidrome server accessible via HTTPS
- Navidrome user credentials stored in Ansible Vault
- NAS mount points must be accessible and writable
- Network connectivity to Navidrome server
What is Navidrome?
Navidrome is a self-hosted music streaming server that provides:
- Music library management and streaming
- Playlist creation and management
- Subsonic API compatibility
- Web and mobile client support
Role Variables
Required Variables
| Variable | Required | Description |
|---|---|---|
vault_navidrome_joffrey_user | Yes | Navidrome username (stored in Ansible Vault) |
vault_navidrome_joffrey_password | Yes | Navidrome password (stored in Ansible Vault) |
navidrome_playlists_backup_playlists | Yes | Dictionary of playlist IDs and names |
Optional Variables
| Variable | Default | Description |
|---|---|---|
navidrome_playlists_backup_url | https://server.homelab | Navidrome instance URL |
navidrome_playlists_backup_syno_mount_point | /mnt/synology-ds418/navidrome/playlists | Synology NAS backup destination |
navidrome_playlists_backup_prxmxomv_mount_point | /mnt/prxmx-omv/navidrome/playlists | Proxmox OMV NAS backup destination |
Variable Details
vault_navidrome_joffrey_user and vault_navidrome_joffrey_password
Navidrome login credentials. Must be stored in Ansible Vault.
Example vault variables:
vault_navidrome_joffrey_user: "joffrey"
vault_navidrome_joffrey_password: "YourSecurePassword123"
navidrome_playlists_backup_playlists
Dictionary mapping playlist IDs (UUIDs) to human-readable names.
How to find playlist IDs:
- Log into Navidrome web UI
- Click on a playlist
- Check URL:
https://server.homelab/app/playlist/{playlist_id}
Example:
navidrome_playlists_backup_playlists:
abc123-def456-ghi789: "Rock Classics"
xyz789-uvw456-rst123: "Chill Vibes"
mno345-pqr678-stu901: "Workout Mix"
navidrome_playlists_backup_url
The full URL to your Navidrome instance. Must include protocol (https://).
Example:
navidrome_playlists_backup_url: "https://music.example.com"
Dependencies
This role has no dependencies on other Ansible roles, but requires:
- Navidrome server running and accessible
- Valid user credentials in Navidrome
- NAS mounts configured (see
nas_mountornas_mount_systemdroles)
Example Playbook
Basic Usage
---
- name: Backup Navidrome Playlists
hosts: localhost
become: true
roles:
- navidrome_playlists_backup
With Custom Configuration
---
- name: Backup Navidrome Playlists from Custom URL
hosts: localhost
become: true
vars:
navidrome_playlists_backup_url: "https://music.example.com"
navidrome_playlists_backup_playlists:
playlist-uuid-1: "My Favorites"
playlist-uuid-2: "Workout Music"
roles:
- navidrome_playlists_backup
Scheduled Backup with Cron
---
- name: Schedule Weekly Navidrome Playlist Backup
hosts: localhost
become: true
tasks:
- name: Create cron job for weekly playlist backup
ansible.builtin.cron:
name: "Weekly Navidrome Playlist Backup"
minute: "0"
hour: "4"
weekday: "0" # Sunday
job: "ansible-playbook /path/to/navidrome_backup.yml"
What This Role Does
- Creates dated backup directories on both NAS mounts (format: YYYY-MM-DD)
- Authenticates to Navidrome API (
/auth/login) - Extracts JWT token and client ID from response
- Fails gracefully if authentication fails
- Downloads each playlist as M3U file from
/api/playlist/{id}/tracks - Saves to Synology NAS with timestamped filename
- Saves to Proxmox OMV NAS with timestamped filename
- Finds all backup directories on each NAS
- Removes old directories, keeping only the 5 most recent per NAS
Authentication Flow
Step 1: Authenticate
POST /auth/login
Body: {
"username": "user",
"password": "password"
}
Response:
{
"id": "user-uuid",
"token": "jwt-token-here",
"username": "user",
...
}
Step 2: Extract Token
The role extracts:
token: JWT for authenticationid: Client ID for requests
Step 3: Download Playlists
GET /api/playlist/{playlist_id}/tracks
Headers:
Accept: audio/x-mpegurl
x-nd-authorization: Bearer {jwt_token}
x-nd-client-unique-id: {client_id}
Response: M3U playlist file
Backup Organization
Directory Structure
synology-ds418/navidrome/playlists/
├── 2026-01-07/
│ ├── Alt_Rock_And_Metal_20260107_143022.m3u
│ ├── Guitar_20260107_143022.m3u
│ └── The_Very_Best_Of_20260107_143022.m3u
├── 2026-01-06/
│ └── ...
└── 2026-01-05/
└── ...
File Naming
{sanitized_playlist_name}_{timestamp}.m3u
Examples:
Alt_Rock_And_Metal_20260107_143022.m3uMelodic_Death_Metal_20260107_143022.m3uThe_Very_Best_Of_20260107_143022.m3u
Special characters are replaced with underscores for filesystem safety.
M3U File Format
#EXTM3U
#EXTINF:240,Artist Name - Song Title
/path/to/music/file1.mp3
#EXTINF:180,Another Artist - Another Song
/path/to/music/file2.mp3
M3U files contain:
- Track duration
- Artist and title metadata
- File paths (absolute)
Backup Content
The backup includes:
- Playlist track listings (order preserved)
- Track metadata (artist, title, duration)
- File paths to music files
The backup does NOT include:
- Actual music files (only playlists)
- Playlist descriptions or artwork
- Play counts or statistics
- User-specific data
Backup Retention
The role implements directory-based retention:
- Keeps: Last 5 dated directories per NAS
- Deletes: Directories older than the 5th most recent
- Per-NAS logic: Each NAS independently maintains 5 directories
Example retention (keeps these):
2026-01-07/ ← Keep (newest)
2026-01-06/ ← Keep
2026-01-05/ ← Keep
2026-01-04/ ← Keep
2026-01-03/ ← Keep
2026-01-02/ ← Delete (too old)
2026-01-01/ ← Delete (too old)
Restoration
To restore playlists:
Manual Method
- Copy M3U files to Navidrome’s music directory
- Navidrome will automatically scan and import them
Import via Navidrome UI
- Upload M3U file in Navidrome settings
- Navidrome parses and creates playlist
Note: File paths in M3U must match your current music library structure.
Security Considerations
- Credential Protection: Username/password marked with
no_log: true - Vault Storage: Credentials must be in Ansible Vault
- Token Protection: JWT token marked with
no_log: true - HTTPS Required: Always use HTTPS for Navidrome connections
- File Permissions: M3U files created with default permissions
Tags
This role does not define any tags. Use playbook-level tags if needed:
- hosts: localhost
roles:
- navidrome_playlists_backup
tags:
- backup
- navidrome
- music
- playlists
Notes
- Downloads playlists sequentially (one at a time)
- Dated directories allow multiple backups per day
- Special characters in playlist names are sanitized
- Empty playlists create empty M3U files
- Role is idempotent - safe to run daily
Troubleshooting
”Authentication failed - no token received”
Verify credentials:
- Check username/password are correct in Navidrome
- Ensure user account is active
- Test login via Navidrome web UI
Test manually:
curl -X POST -H "Content-Type: application/json" \
-d '{"username":"user","password":"pass"}' \
https://server.homelab/auth/login
“Permission denied” when writing to NAS
Ensure:
- NAS is mounted:
mount | grep synology - Backup directories are writable
- User has write permissions
Playlist download returns empty file
Check:
- Playlist actually has tracks in Navidrome UI
- Playlist ID is correct (check URL in browser)
- Music files still exist in library
”Connection refused” errors
Verify:
- Navidrome is running
- URL is correct:
curl -I https://server.homelab - Network connectivity
Wrong playlists backed up
Verify playlist IDs:
- Open Navidrome in browser
- Click each playlist
- Check URL for correct UUID
- Update
navidrome_playlists_backup_playlistsdictionary
Performance Considerations
- Download speed depends on playlist size
- Small playlists (< 100 tracks): ~1-2 seconds each
- Large playlists (1000+ tracks): ~5-10 seconds each
- Sequential downloads (not parallel)
Typical performance:
- 5 playlists (avg 50 tracks): ~10-15 seconds
- 10 playlists (avg 100 tracks): ~30-40 seconds
Navidrome Version Compatibility
- Navidrome 0.47+: Full support
- Navidrome 0.48+: Full support
- Navidrome 0.49+: Full support (latest)
The role uses stable API endpoints that haven’t changed.
API Endpoints Used
1. Authenticate
POST /auth/login
Content-Type: application/json
Body:
{
"username": "user",
"password": "password"
}
2. Download Playlist
GET /api/playlist/{playlist_id}/tracks
Accept: audio/x-mpegurl
x-nd-authorization: Bearer {jwt_token}
x-nd-client-unique-id: {client_id}
Finding Playlist IDs
Method 1: Browser URL
- Log into Navidrome
- Click on playlist
- URL shows ID:
https://server.homelab/app/playlist/{ID}
Method 2: Browser DevTools
- Open DevTools (F12)
- Go to Network tab
- Click on playlist
- Find API request:
/api/playlist/{ID}
Method 3: API
# Get all playlists
curl -H "x-nd-authorization: Bearer YOUR_TOKEN" \
https://server.homelab/api/playlist
Alternative: Manual Backup
If you prefer manual backup:
# Authenticate
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"username":"user","password":"pass"}' \
https://server.homelab/auth/login | jq -r '.token')
CLIENT_ID=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"username":"user","password":"pass"}' \
https://server.homelab/auth/login | jq -r '.id')
# Download playlist
curl -H "Accept: audio/x-mpegurl" \
-H "x-nd-authorization: Bearer $TOKEN" \
-H "x-nd-client-unique-id: $CLIENT_ID" \
-o "my_playlist.m3u" \
"https://server.homelab/api/playlist/PLAYLIST_ID/tracks"
Best Practices
- Document playlist IDs in comments or documentation
- Schedule regular backups (weekly for active playlists)
- Verify M3U files occasionally
- Test restoration to ensure file paths are valid
- Update playlist dictionary when creating new playlists
License
MIT
Author
Created for homelab infrastructure management.