From 7b23d27554fcf4ed561ffbc00fbfa4082a3c37f0 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 4 Feb 2026 19:23:55 +0200 Subject: Add Navidrome music server deployment Adds Navidrome music streaming server with: - Helm chart with deployment, service, ingress, and persistent volumes - Two PVs: data (10Gi) and music library (200Gi) - ArgoCD application for automated deployment - Ingress at navidrome.f3s.buetow.org - Justfile for operational commands --- f3s/argocd-apps/services/navidrome.yaml | 28 ++++ f3s/navidrome/Justfile | 44 +++++++ f3s/navidrome/helm-chart/Chart.yaml | 5 + f3s/navidrome/helm-chart/README.md | 141 +++++++++++++++++++++ f3s/navidrome/helm-chart/templates/deployment.yaml | 55 ++++++++ f3s/navidrome/helm-chart/templates/ingress.yaml | 20 +++ .../helm-chart/templates/persistent-volume.yaml | 55 ++++++++ 7 files changed, 348 insertions(+) create mode 100644 f3s/argocd-apps/services/navidrome.yaml create mode 100644 f3s/navidrome/Justfile create mode 100644 f3s/navidrome/helm-chart/Chart.yaml create mode 100644 f3s/navidrome/helm-chart/README.md create mode 100644 f3s/navidrome/helm-chart/templates/deployment.yaml create mode 100644 f3s/navidrome/helm-chart/templates/ingress.yaml create mode 100644 f3s/navidrome/helm-chart/templates/persistent-volume.yaml diff --git a/f3s/argocd-apps/services/navidrome.yaml b/f3s/argocd-apps/services/navidrome.yaml new file mode 100644 index 0000000..aca2d4b --- /dev/null +++ b/f3s/argocd-apps/services/navidrome.yaml @@ -0,0 +1,28 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: navidrome + namespace: cicd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + source: + repoURL: http://git-server.cicd.svc.cluster.local/conf.git + targetRevision: master + path: f3s/navidrome/helm-chart + destination: + server: https://kubernetes.default.svc + namespace: services + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=false + retry: + limit: 3 + backoff: + duration: 5s + factor: 2 + maxDuration: 1m diff --git a/f3s/navidrome/Justfile b/f3s/navidrome/Justfile new file mode 100644 index 0000000..e7003c8 --- /dev/null +++ b/f3s/navidrome/Justfile @@ -0,0 +1,44 @@ +NAMESPACE := "services" +APP_NAME := "navidrome" + +# Show deployment status +status: + @echo "=== Pods ===" + @kubectl get pods -n {{NAMESPACE}} | grep navidrome + @echo "" + @echo "=== Service ===" + @kubectl get svc -n {{NAMESPACE}} navidrome-service + @echo "" + @echo "=== Ingress ===" + @kubectl get ingress -n {{NAMESPACE}} navidrome-ingress + @echo "" + @echo "=== PVCs ===" + @kubectl get pvc -n {{NAMESPACE}} | grep navidrome + @echo "" + @echo "=== ArgoCD Status ===" + @kubectl get application {{APP_NAME}} -n cicd -o jsonpath='Sync: {.status.sync.status}, Health: {.status.health.status}' 2>/dev/null && echo "" || echo "Not found" + +# View logs +logs lines="100": + kubectl logs -n {{NAMESPACE}} -l app=navidrome --tail={{lines}} -f + +# Port forward +port-forward port="4533": + @echo "Forwarding navidrome to localhost:{{port}}" + kubectl port-forward -n {{NAMESPACE}} svc/navidrome-service {{port}}:4533 + +# Trigger ArgoCD sync +sync: + @echo "Triggering ArgoCD sync..." + @kubectl annotate application {{APP_NAME}} -n cicd argocd.argoproj.io/refresh=normal --overwrite + @sleep 2 + @kubectl get application {{APP_NAME}} -n cicd -o jsonpath='Sync: {.status.sync.status}, Health: {.status.health.status}' && echo "" + +# Show ArgoCD application details +argocd-status: + argocd app get {{APP_NAME}} --core + +# Restart +restart: + @echo "Restarting navidrome..." + kubectl rollout restart -n {{NAMESPACE}} deployment/navidrome diff --git a/f3s/navidrome/helm-chart/Chart.yaml b/f3s/navidrome/helm-chart/Chart.yaml new file mode 100644 index 0000000..bf9e4b7 --- /dev/null +++ b/f3s/navidrome/helm-chart/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: navidrome +description: A Helm chart for deploying Navidrome music server. +version: 0.1.0 +appVersion: "latest" diff --git a/f3s/navidrome/helm-chart/README.md b/f3s/navidrome/helm-chart/README.md new file mode 100644 index 0000000..bee6058 --- /dev/null +++ b/f3s/navidrome/helm-chart/README.md @@ -0,0 +1,141 @@ +# Navidrome Music Server Kubernetes Deployment + +This directory contains the Kubernetes configuration for deploying Navidrome, a modern music server and streamer compatible with Subsonic/Airsonic clients. + +## Overview + +- **Application**: Navidrome +- **Image**: `deluan/navidrome:latest` +- **Namespace**: `services` +- **Ingress**: `navidrome.f3s.buetow.org` +- **Port**: 4533 + +## Storage + +Navidrome requires two persistent volumes: + +1. **Data Volume** (`/data/nfs/k3svolumes/navidrome/data`): 10Gi + - Stores configuration, database (SQLite), cache, and metadata + - Mounted at `/data` in the container + +2. **Music Volume** (`/data/nfs/k3svolumes/navidrome/music`): 200Gi + - Stores your music library + - Mounted at `/music` in the container + +## Pre-Deployment Setup + +Before deploying, ensure the storage directories exist on the host: + +```bash +mkdir -p /data/nfs/k3svolumes/navidrome/data +mkdir -p /data/nfs/k3svolumes/navidrome/music +``` + +## Deployment + +The application is managed by ArgoCD. After committing changes to git and pushing to the r0 remote, ArgoCD will automatically sync and deploy the application. + +To manually trigger a sync: + +```bash +just sync +``` + +## Initial Configuration + +1. After deployment, access Navidrome at `http://navidrome.f3s.buetow.org` +2. On first access, you'll be prompted to create an admin account +3. Configure settings as needed through the web UI + +## Adding Music + +Copy or sync your music files to the music volume on the host: + +```bash +# On the host with the NFS share +cp -r /path/to/your/music/* /data/nfs/k3svolumes/navidrome/music/ +``` + +Navidrome will automatically scan for new music based on the `ND_SCANSCHEDULE` setting (default: hourly). + +## Management Commands + +Check deployment status: + +```bash +just status +``` + +View logs: + +```bash +just logs +``` + +Port forward for local access: + +```bash +just port-forward +``` + +Restart the application: + +```bash +just restart +``` + +## Features + +- Web-based music player +- Compatible with Subsonic/Airsonic mobile apps +- Automatic metadata fetching from Last.fm +- Playlist support +- Multi-user support +- Transcoding support +- Scrobbling to Last.fm + +## Client Apps + +Navidrome is compatible with various Subsonic clients: + +- **iOS**: play:Sub, substreamer +- **Android**: DSub, Ultrasonic, substreamer +- **Desktop**: Sublime Music, Sonixd +- **Web**: Built-in web player + +## Configuration + +Environment variables can be adjusted in the deployment.yaml: + +- `ND_SCANSCHEDULE`: How often to scan for new music (default: 1h) +- `ND_LOGLEVEL`: Logging level (info, debug, trace) +- `ND_BASEURL`: Base URL if behind a reverse proxy + +See [Navidrome documentation](https://www.navidrome.org/docs/usage/configuration-options/) for all available options. + +## Troubleshooting + +Check pod status: + +```bash +kubectl get pods -n services | grep navidrome +``` + +View detailed logs: + +```bash +kubectl logs -n services -l app=navidrome --tail=200 +``` + +Check persistent volume claims: + +```bash +kubectl get pvc -n services | grep navidrome +``` + +## Security + +- Authentication is handled by Navidrome itself +- No secrets are stored in git +- User accounts are managed through the web UI +- Consider enabling HTTPS in production diff --git a/f3s/navidrome/helm-chart/templates/deployment.yaml b/f3s/navidrome/helm-chart/templates/deployment.yaml new file mode 100644 index 0000000..b140537 --- /dev/null +++ b/f3s/navidrome/helm-chart/templates/deployment.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: navidrome + namespace: services +spec: + replicas: 1 + selector: + matchLabels: + app: navidrome + template: + metadata: + labels: + app: navidrome + spec: + containers: + - name: navidrome + image: deluan/navidrome:latest + ports: + - containerPort: 4533 + env: + - name: ND_SCANSCHEDULE + value: "1h" + - name: ND_LOGLEVEL + value: "info" + - name: ND_BASEURL + value: "" + volumeMounts: + - name: navidrome-data + mountPath: /data + - name: navidrome-music + mountPath: /music + volumes: + - name: navidrome-data + persistentVolumeClaim: + claimName: navidrome-data-pvc + - name: navidrome-music + persistentVolumeClaim: + claimName: navidrome-music-pvc +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: navidrome + name: navidrome-service + namespace: services +spec: + ports: + - name: web + port: 4533 + protocol: TCP + targetPort: 4533 + selector: + app: navidrome diff --git a/f3s/navidrome/helm-chart/templates/ingress.yaml b/f3s/navidrome/helm-chart/templates/ingress.yaml new file mode 100644 index 0000000..e8d94c6 --- /dev/null +++ b/f3s/navidrome/helm-chart/templates/ingress.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: navidrome-ingress + namespace: services + annotations: + spec.ingressClassName: traefik + traefik.ingress.kubernetes.io/router.entrypoints: web +spec: + rules: + - host: navidrome.f3s.buetow.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: navidrome-service + port: + number: 4533 diff --git a/f3s/navidrome/helm-chart/templates/persistent-volume.yaml b/f3s/navidrome/helm-chart/templates/persistent-volume.yaml new file mode 100644 index 0000000..960bee3 --- /dev/null +++ b/f3s/navidrome/helm-chart/templates/persistent-volume.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: navidrome-data-pv +spec: + capacity: + storage: 10Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /data/nfs/k3svolumes/navidrome/data + type: Directory +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: navidrome-data-pvc + namespace: services +spec: + storageClassName: "" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: navidrome-music-pv +spec: + capacity: + storage: 200Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /data/nfs/k3svolumes/navidrome/music + type: Directory +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: navidrome-music-pvc + namespace: services +spec: + storageClassName: "" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Gi -- cgit v1.2.3