diff --git a/ansible/roles/caddy/defaults/main.yml b/ansible/roles/caddy/defaults/main.yml index 9f9a142..2aefc3d 100644 --- a/ansible/roles/caddy/defaults/main.yml +++ b/ansible/roles/caddy/defaults/main.yml @@ -64,6 +64,9 @@ caddy_services: - name: immich host: "photos.{{ caddy_domain }}" backend: "https://photos.tail8d86e.ts.net" + - name: navidrome + host: "dj.{{ caddy_domain }}" + backend: "https://dj.tail8d86e.ts.net" - name: hajimari host: "go.{{ caddy_domain }}" backend: "https://go.tail8d86e.ts.net" diff --git a/argocd/apps/navidrome.yaml b/argocd/apps/navidrome.yaml new file mode 100644 index 0000000..95bcf1b --- /dev/null +++ b/argocd/apps/navidrome.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: navidrome + namespace: argocd +spec: + project: default + source: + repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git + targetRevision: main + path: argocd/manifests/navidrome + destination: + server: https://kubernetes.default.svc + namespace: navidrome + syncPolicy: + syncOptions: + - CreateNamespace=true diff --git a/argocd/manifests/navidrome/deployment.yaml b/argocd/manifests/navidrome/deployment.yaml new file mode 100644 index 0000000..5a91029 --- /dev/null +++ b/argocd/manifests/navidrome/deployment.yaml @@ -0,0 +1,63 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: navidrome + namespace: navidrome +spec: + replicas: 1 + selector: + matchLabels: + app: navidrome + template: + metadata: + labels: + app: navidrome + spec: + containers: + - name: navidrome + image: deluan/navidrome:latest + ports: + - containerPort: 4533 + name: http + env: + - name: ND_SCANSCHEDULE + value: "1h" + - name: ND_LOGLEVEL + value: "info" + - name: ND_MUSICFOLDER + value: "/music" + - name: ND_DATAFOLDER + value: "/data" + volumeMounts: + - name: music + mountPath: /music + readOnly: true + - name: data + mountPath: /data + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /ping + port: 4533 + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /ping + port: 4533 + initialDelaySeconds: 5 + periodSeconds: 10 + volumes: + - name: music + persistentVolumeClaim: + claimName: navidrome-music + - name: data + persistentVolumeClaim: + claimName: navidrome-data diff --git a/argocd/manifests/navidrome/ingress-tailscale.yaml b/argocd/manifests/navidrome/ingress-tailscale.yaml new file mode 100644 index 0000000..037838f --- /dev/null +++ b/argocd/manifests/navidrome/ingress-tailscale.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: navidrome-tailscale + namespace: navidrome + annotations: + tailscale.com/proxy-class: "default" + gethomepage.dev/enabled: "true" + gethomepage.dev/name: "DJ" + gethomepage.dev/group: "Media" + gethomepage.dev/icon: "navidrome.png" + gethomepage.dev/description: "Music streaming server" + gethomepage.dev/href: "https://dj.ops.eblu.me" + gethomepage.dev/pod-selector: "app=navidrome" +spec: + ingressClassName: tailscale + defaultBackend: + service: + name: navidrome + port: + number: 4533 + tls: + - hosts: + - dj diff --git a/argocd/manifests/navidrome/kustomization.yaml b/argocd/manifests/navidrome/kustomization.yaml new file mode 100644 index 0000000..bf62c5b --- /dev/null +++ b/argocd/manifests/navidrome/kustomization.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: navidrome +resources: + - pv-nfs.yaml + - pvc-music.yaml + - pvc-data.yaml + - deployment.yaml + - service.yaml + - ingress-tailscale.yaml diff --git a/argocd/manifests/navidrome/pv-nfs.yaml b/argocd/manifests/navidrome/pv-nfs.yaml new file mode 100644 index 0000000..a6e09a4 --- /dev/null +++ b/argocd/manifests/navidrome/pv-nfs.yaml @@ -0,0 +1,22 @@ +# NFS PersistentVolume for Navidrome music library +# Requires: NFS share on sifaka at /volume1/music with NFS permissions for indri +# +# To create on Synology: +# 1. Control Panel > Shared Folder > Create +# 2. Name: music, Location: Volume 1 +# 3. Control Panel > File Services > NFS > NFS Rules +# 4. Add rule for "music" share: Hostname=indri, Privilege=Read-Only, Squash=No mapping +apiVersion: v1 +kind: PersistentVolume +metadata: + name: navidrome-music-nfs-pv +spec: + capacity: + storage: 1Ti + accessModes: + - ReadOnlyMany + persistentVolumeReclaimPolicy: Retain + storageClassName: "" + nfs: + server: sifaka + path: /volume1/music diff --git a/argocd/manifests/navidrome/pvc-data.yaml b/argocd/manifests/navidrome/pvc-data.yaml new file mode 100644 index 0000000..67fc8fb --- /dev/null +++ b/argocd/manifests/navidrome/pvc-data.yaml @@ -0,0 +1,13 @@ +# PersistentVolumeClaim for Navidrome data (SQLite database, config, cache) +# Uses minikube's default storage class for local provisioning +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: navidrome-data + namespace: navidrome +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi diff --git a/argocd/manifests/navidrome/pvc-music.yaml b/argocd/manifests/navidrome/pvc-music.yaml new file mode 100644 index 0000000..9fd047f --- /dev/null +++ b/argocd/manifests/navidrome/pvc-music.yaml @@ -0,0 +1,15 @@ +# PersistentVolumeClaim for Navidrome music library +# Binds to the NFS PV for sifaka:/volume1/music +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: navidrome-music + namespace: navidrome +spec: + accessModes: + - ReadOnlyMany + storageClassName: "" + volumeName: navidrome-music-nfs-pv + resources: + requests: + storage: 1Ti diff --git a/argocd/manifests/navidrome/service.yaml b/argocd/manifests/navidrome/service.yaml new file mode 100644 index 0000000..a1d25e2 --- /dev/null +++ b/argocd/manifests/navidrome/service.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: navidrome + namespace: navidrome +spec: + selector: + app: navidrome + ports: + - name: http + port: 4533 + targetPort: 4533