From e75dde6ed213649dc2431c2f2909277fe5e5671d Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sun, 15 Mar 2026 01:17:39 -0400 Subject: [PATCH] feat: add Navidrome music server as installable service - Add NAVIDROME to SERVICE_NAMES constant - Add service seeder entry with Docker config: - Image: deluan/navidrome:0.55.2 - Port: 4533 - Volumes: data + music (read-only) - Telemetry disabled (ND_ENABLEINSIGHTSCOLLECTOR=false) - Auto-scan every hour - Add Navidrome to Easy Setup wizard (Additional Tools) - No dependencies, no new migrations needed - Subsonic API compatible for mobile app streaming --- admin/constants/service_names.ts | 1 + admin/database/seeders/service_seeder.ts | 32 ++++++++++++++++++++++++ admin/inertia/pages/easy-setup/index.tsx | 13 ++++++++++ 3 files changed, 46 insertions(+) diff --git a/admin/constants/service_names.ts b/admin/constants/service_names.ts index 8009222..5aa13db 100644 --- a/admin/constants/service_names.ts +++ b/admin/constants/service_names.ts @@ -5,4 +5,5 @@ export const SERVICE_NAMES = { CYBERCHEF: 'nomad_cyberchef', FLATNOTES: 'nomad_flatnotes', KOLIBRI: 'nomad_kolibri', + NAVIDROME: 'nomad_navidrome', } diff --git a/admin/database/seeders/service_seeder.ts b/admin/database/seeders/service_seeder.ts index 2afa6f3..ecdbd80 100644 --- a/admin/database/seeders/service_seeder.ts +++ b/admin/database/seeders/service_seeder.ts @@ -159,6 +159,38 @@ export default class ServiceSeeder extends BaseSeeder { is_dependency_service: false, depends_on: null, }, + { + service_name: SERVICE_NAMES.NAVIDROME, + friendly_name: 'Music Server', + powered_by: 'Navidrome', + display_order: 4, + description: + 'Stream your personal music library offline — supports Subsonic-compatible apps', + icon: 'IconMusic', + container_image: 'deluan/navidrome:0.60.3', + source_repo: 'https://github.com/navidrome/navidrome', + container_command: null, + container_config: JSON.stringify({ + HostConfig: { + RestartPolicy: { Name: 'unless-stopped' }, + PortBindings: { '4533/tcp': [{ HostPort: '4533' }] }, + Binds: [ + `${ServiceSeeder.NOMAD_STORAGE_ABS_PATH}/navidrome/data:/data`, + `${ServiceSeeder.NOMAD_STORAGE_ABS_PATH}/navidrome/music:/music:ro`, + ], + }, + ExposedPorts: { '4533/tcp': {} }, + Env: [ + 'ND_ENABLEINSIGHTSCOLLECTOR=false', + 'ND_SCANNER_SCHEDULE=@every 1h', + ], + }), + ui_location: '4533', + installed: false, + installation_status: 'idle', + is_dependency_service: false, + depends_on: null, + }, ] async run() { diff --git a/admin/inertia/pages/easy-setup/index.tsx b/admin/inertia/pages/easy-setup/index.tsx index c1fab9b..f770193 100644 --- a/admin/inertia/pages/easy-setup/index.tsx +++ b/admin/inertia/pages/easy-setup/index.tsx @@ -103,6 +103,19 @@ const ADDITIONAL_TOOLS: Capability[] = [ services: [SERVICE_NAMES.CYBERCHEF], icon: 'IconChefHat', }, + { + id: 'music', + name: 'Music Server', + technicalName: 'Navidrome', + description: 'Stream your personal music library offline — supports Subsonic-compatible apps', + features: [ + 'Web-based music player', + 'Subsonic API for mobile apps', + 'No internet required after setup', + ], + services: [SERVICE_NAMES.NAVIDROME], + icon: 'IconMusic', + }, ] type WizardStep = 1 | 2 | 3 | 4