A lightweight self-hosted web application for browsing and downloading music to your Navidrome library. Optimized for low-end hardware.
Multi-Provider Architecture: Browse metadata via HiFi (Tidal API proxy) or Qobuz. Download and stream via Qobuz — the HiFi/Tidal API is unreliable for streaming/downloads.
- Browse & Search: Discover artists, albums, playlists, and tracks from HiFi (Tidal) or Qobuz catalog APIs
- Stream Preview: Play tracks directly from search results with play/pause controls on track cards
- Download Queue: Asynchronous job queuing with configurable concurrency control
- Multi-Provider: Separate provider selection for metadata browsing, downloads, and streaming — mix HiFi (browse) + Qobuz (download/stream) or any combination
- Quality Selection: Choose from LOSSLESS, HI_RES_LOSSLESS, HIGH, or LOW audio quality
- Queue Page: Monitor active downloads with real-time progress updates
- Downloads Browser: Browse, search (by track, album, artist, genre), filter (by genre including "no_genre"), and manage downloaded tracks with bulk actions (delete, sync, set metadata)
- Bulk Metadata: Set genre, year, mood, and style for multiple tracks at once
- Sync to File: Re-tag audio files with updated metadata from Database
- Sync All: Fetch missing metadata from provider (HiFi/Qobuz) and MusicBrainz, update Database and sync to files
- History Tracking: View last 20 completed/failed/cancelled downloads
- Job Management: Cancel active jobs, retry failed downloads, clear history
- Stuck Job Recovery: Automatic reset of interrupted downloads on startup
- Comprehensive Tagging: Automatically embeds metadata in audio files:
- Basic: Title, Artist(s), Album Artist(s), Album, Track/Disc Numbers
- Release Details: Year, Release Date, Genre, Label, ISRC, Copyright, Composer
- Extended: BPM, Key, KeyScale, ReplayGain, Peak levels, MusicBrainz IDs
- Mood/Style: Custom mood and style tags for personal organization (manual addition by track or bulk action)
- Commercial: Barcode, Catalog Number, Release Type
- Lyrics: Unsynchronized lyrics (LYRICS) and subtitles (LRC format)
- Album Art Handling: Embedded cover art + saved as
cover.jpgin album folders - Playlist Images: Cover images saved to playlists folder
- MusicBrainz Integration: Metadata enrichment using ISRC codes and genre fetching
- Format Support: FLAC and MP3 audio formats (MP4/M4A support stubbed)
- File Verification: SHA256 hash checking with
LastVerifiedAttracking - Path Organization: Configurable directory structure via Go templates
- Path Sanitization: Automatic cleaning of invalid filesystem characters
- Empty Directory Cleanup: Automatic removal of empty folders after deletions
- Playlist Generation: Automatic M3U file creation for playlists and artist top tracks
- Separate Per-Operation Selection: Choose different providers for metadata browsing, downloads, and streaming
- Provider Types: HiFi (Tidal API proxy) and Qobuz — each can have multiple endpoint URLs as fallbacks
- Provider Fallback: Multiple URLs of the same type tried in order until one succeeds
- Per-Type Caching: Each provider chain has its own response cache with configurable TTL
- API Throttling: Built-in request throttling for external APIs (HiFi, Qobuz, MusicBrainz) to prevent rate limiting
- Automatic Retries: Exponential backoff with 3 attempts for failed downloads
- Concurrent Downloads: Configurable worker concurrency (default: 2)
- File Hash Verification: Prevents duplicate downloads via hash matching
- Statistics Tracking: Job success/failure rates and performance metrics
- HTMX-Powered: Responsive UI with no JSON APIs for frontend
- Real-time Updates: Live progress updates without page reloads
- Component-based: Modular templates for maintainable UI code
- Basic Authentication: Optional HTTP basic auth protection
- Track Details View: Comprehensive file, audio, and MusicBrainz metadata display
- Provider Management: Add, reorder, edit, and remove HiFi and Qobuz provider URLs; select which provider type to use per operation (metadata, download, streaming)
- Genre Mapping: Customize how MusicBrainz genres are normalized (maps sub-genres to main genres)
- Genre Separator: Configure the separator used when writing multiple genres to audio tags
- Theme Selector: Override the default application theme configured via environment variable
Recommended: Use Cloudflare Tunnel and Zero Trust instead of basic auth
For production deployments exposed to the internet, we strongly recommend using a reverse proxy with built-in authentication instead of HTTP basic auth:
- Cloudflare Tunnel (Zero Trust): Tunnel your service through Cloudflare withAccess policies, SSO integration, and built-in DDoS protection
- Traefik: Configure OAuth2 or ForwardAuth middleware
- Nginx: Use Auth_request module with external auth service
- Caddy: Built-in OAuth2 or Cloudflare API key support
Basic auth has limitations:
- Credentials sent with every request (even if over HTTPS)
- No MFA/SSO support
- Hard to revoke without changing passwords
When using a proxy with authentication, set SKIP_AUTH=true to disable built-in auth:
SKIP_AUTH=true ./navidrums
Rate limiting is still applied as a second layer of protection.
- Two-Table Design: Jobs (work queue) + Tracks (full metadata) separation
- SQLite Database: Efficient embedded database with WAL mode for concurrency
- Data Invariants: Prevents duplicate downloads, ensures file-tagging order
- Docker & Docker Compose (for Docker installation only)
- Go 1.22+ (for building from source)
- A HiFi (Tidal) API proxy (for metadata browsing, e.g.,
http://127.0.0.1:8000) - A Qobuz API proxy (for downloads/streaming, e.g.,
https://qobuz.kennyy.com.br/api) - ffmpeg (optional, only needed for MP4/M4A tagging - commonly required for hi-res downloads)
Environment variables:
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP server port |
DB_PATH |
navidrums.db |
SQLite database file path |
DOWNLOADS_DIR |
~/Downloads/navidrums |
Output directory for downloaded music |
SUBDIR_TEMPLATE |
{{.AlbumArtist}}/{{.OriginalYear}} - {{.Album}}/{{.Disc}}-{{.Track}} {{.Title}} |
Go template for file organization |
PROVIDER_URL |
http://127.0.0.1:8000 |
Default HiFi (Tidal) API URL for metadata browsing (additional providers managed via Settings UI) |
QUALITY |
LOSSLESS |
Download audio quality (LOSSLESS, HI_RES_LOSSLESS, HIGH, LOW) |
PLAY_QUALITY |
HIGH |
Streaming playback quality (LOSSLESS, HI_RES_LOSSLESS, HIGH, LOW) |
LOG_LEVEL |
info |
Logging level (debug, info, warn, error) |
LOG_FORMAT |
text |
Log output format (text, json) |
NAVIDRUMS_USERNAME |
navidrums |
Username for HTTP basic authentication |
NAVIDRUMS_PASSWORD |
(empty) | Password for HTTP basic authentication (empty disables auth) |
SKIP_AUTH |
false |
Set to true to disable authentication entirely |
CACHE_TTL |
12h |
Provider response cache TTL (e.g., 1h, 24h, 7d) |
MUSICBRAINZ_CACHE_TTL |
7d |
MusicBrainz API response cache TTL (e.g., 1d, 168h) |
MUSICBRAINZ_URL |
https://musicbrainz.org/ws/2 |
MusicBrainz API endpoint for metadata enrichment |
RATE_LIMIT_REQUESTS |
200 |
Maximum requests per rate limit window |
RATE_LIMIT_WINDOW |
1m |
Rate limit time window (e.g., 30s, 1m) |
RATE_LIMIT_BURST |
10 |
Burst requests allowed beyond rate limit |
DISABLE_RATE_LIMIT |
false |
Disable rate limiting (use when behind Cloudflare) |
THEME |
golden |
Default application theme (can be overridden in Settings) |
FFMPEG_PATH |
(system) | Path to ffmpeg binary (required for MP4/M4A tagging) |
FFPROBE_PATH |
(system) | Path to ffprobe binary |
ffmpeg and ffprobe are automatically detected most of the times, but you can override them with the above variables if needed.
HiFi/Tidal streaming limitation: The HiFi/Tidal API is unreliable for downloads and streaming — it often returns 30-second previews instead of full tracks, especially at HI_RES_LOSSLESS quality. This is why Qobuz is the recommended provider for downloads and streaming. You can configure separate providers per operation in Settings:
- Metadata (search/browse): HiFi works well for browsing
- Download: Switch to Qobuz for reliable full-track downloads
- Streaming: Switch to Qobuz for full-length playback previews
Template Variables:
The SUBDIR_TEMPLATE uses Go's text/template syntax. Available variables:
{{.AlbumArtist}}- Album artist (falls back to track artist if empty){{.OriginalYear}}- Release year (integer){{.Album}}- Album name{{.Disc}}- Disc number, zero-padded (01, 02, etc.){{.Track}}- Track number, zero-padded (01, 02, etc.){{.Title}}- Track title
The file extension (.flac, .mp3, or .mp4) is appended automatically.
Example: The default template produces paths like:
~/Downloads/navidrums/Pink Floyd/1973 - The Dark Side of the Moon/01-01 Speak to Me.flac
Note: Invalid filesystem characters (<>:"/\|?*) are automatically sanitized from paths.
HiFi API: https://github.com/binimum/hifi-api
-
Download the latest release for your platform from the Releases page:
- Linux (x86_64):
navidrums-linux-amd64 - Linux (ARM64/Raspberry Pi):
navidrums-linux-arm64 - macOS (Intel):
navidrums-darwin-amd64 - macOS (Apple Silicon):
navidrums-darwin-arm64 - Windows (x86_64):
navidrums-windows-amd64.exe
- Linux (x86_64):
-
Make the binary executable (Linux/macOS):
chmod +x navidrums-* -
Optionally, move it to a directory in your PATH:
sudo mv navidrums-* /usr/local/bin/navidrums
-
Create a systemd service file at
/etc/systemd/system/navidrums.service:[Unit] Description=Navidrums Music Downloader After=network.target [Service] Type=simple User=YOUR_USERNAME WorkingDirectory=/home/YOUR_USERNAME/navidrums Environment="PORT=8080" Environment="DB_PATH=/home/YOUR_USERNAME/navidrums/navidrums.db" Environment="DOWNLOADS_DIR=/home/YOUR_USERNAME/Music" Environment="PROVIDER_URL=http://127.0.0.1:8000" Environment="QUALITY=LOSSLESS" Environment="NAVIDRUMS_USERNAME=navidrums" Environment="NAVIDRUMS_PASSWORD=password" ExecStart=/usr/local/bin/navidrums Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
-
Replace
YOUR_USERNAMEwith your actual username and adjust paths as needed. -
Enable and start the service:
sudo systemctl daemon-reload sudo systemctl enable navidrums sudo systemctl start navidrums -
Check service status:
sudo systemctl status navidrums
Note: The binary is self-contained with all templates and assets embedded. You only need the single executable file to run the application.
- Clone the repository.
- Build the server:
go build -o navidrums ./cmd/server
- Start the server:
NAVIDRUMS_PASSWORD=admin PROVIDER_URL=https://your-hifi-url.com ./navidrums
- Open browser at
http://localhost:8080. - Search for music and click download.
- Check the "Queue" tab for progress.
No clone needed. Just run the container directly:
-
Create a directory for persistent data:
mkdir -p ~/navidrums/data -
Run the container:
docker run -d \ --name navidrums \ -p 8080:8080 \ -u 1000:1000 \ -v ~/navidrums/data:/data \ -v ~/Music:/music \ -e PROVIDER_URL=https://your-hifi-api.com \ -e NAVIDRUMS_PASSWORD=your-secure-password \ --restart unless-stopped \ ghcr.io/cesargomez89/navidrums:latest
-
Open browser at
http://localhost:8080.
Available tags:
latest- Most recent releasev1.0.0- Specific version (replace with your desired tag)
-
Clone the repository:
git clone https://github.com/cesargomez89/navidrums.git cd navidrums -
Create
.envfile:cp .env.sample .env
Edit
.envand set at least:PROVIDER_URL=https://your-hifi-api.com NAVIDRUMS_PASSWORD=your-secure-password -
Start the container:
docker-compose up -d
-
Open browser at
http://localhost:8080.
Note: Persistent data is saved to ./data and downloads to ./downloads (mounted to /music) in the project directory by default.
See the Configuration section for all available options. The most important ones:
| Variable | Description |
|---|---|
PROVIDER_URL |
Your Hifi API URL (required) |
NAVIDRUMS_PASSWORD |
Web interface password (empty disables auth) |
DOWNLOADS_DIR |
Container path /music (mounted volume) |
DB_PATH |
Container path /data/navidrums.db (mounted volume) |
SUBDIR_TEMPLATE |
File organization template (optional) |
QUALITY |
Audio quality preference (optional) |
To use different host directories, modify the volume mounts:
Docker Compose: Edit docker-compose.yml:
volumes: - /custom/path/to/music:/music - /custom/path/to/data:/data
Docker Run: Change the -v arguments:
-v /custom/path/to/music:/music \ -v /custom/path/to/data:/data
Run tests:
go test ./...To create a new release:
-
Tag the commit:
git tag v1.0.0 git push origin v1.0.0
-
GitHub Actions will automatically:
- Build binaries for all platforms (Linux, macOS, Windows)
- Build and push Docker image to GHCR (
ghcr.io/cesargomez89/navidrums:v1.0.0) - Create a GitHub release
Navidrums follows a clean layered architecture with clear separation of concerns:
- Two-Table Design: Jobs (minimal work queue) + Tracks (full metadata and download state)
- Job Lifecycle:
queued → running → completed | failed | cancelled - Track Lifecycle:
missing → queued → downloading → downloaded → processing → completed | failed - Duplicate Prevention: Unique
provider_idconstraint prevents duplicate downloads
- HTTP Handlers: Request parsing and HTML rendering only
- Application Services: Business logic and workflow orchestration
- Repository: Database persistence and queries
- Providers: External API adapters (HiFi/Tidal, Qobuz) with multi-provider manager, per-type fallback, and caching decorator
- Storage: Filesystem operations and path management
- Workers: Background job processing with concurrency control
- ProviderManager: Central orchestrator with three independent provider chains — metadata, download, streaming
- FallbackProvider: Tries multiple URLs of the same type in order until one succeeds
- CachedProvider: Decorator wrapping each chain with response caching
- Per-Operation Selection: Settings store which provider type (HiFi or Qobuz) to use per operation. Defaults to HiFi
- No Cross-Type Fallback: Provider choice is per-operation, not automatic fallback — configure in Settings
- No downloads in HTTP handlers
- No goroutines in HTTP handlers
- No database access outside store package
- No file writes outside storage package
- All heavy operations run asynchronously via background workers
See ARCHITECTURE.md for technical architecture details and DOMAIN.md for domain model specifications.