feat: Add Navidrome application and VolSync components, migrating media apps from beta.

This commit is contained in:
2026-02-26 13:00:52 +01:00
parent 2be2941343
commit fdbcde49f6
14 changed files with 296 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: media
resources:
- ./namespace.yaml
#- ./booklore
#- ./feishin
#- ./immich
#- ./plex
#- ./karakeep
- ./navidrome

View File

View File

@@ -0,0 +1,31 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app navidrome
spec:
interval: 10m
prune: true
wait: true
timeout: 15m
targetNamespace: media
path: ./apps/media/navidrome/app
components:
- ../../../../components/volsync/
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
postBuild:
substitute:
APP: *app
VOLSYNC_CAPACITY: 1Gi
VOLSYNC_PUID: "568"
VOLSYNC_PGID: "568"
decryption: { provider: sops }
dependsOn:
- name: volsync
namespace: storage-system

View File

@@ -0,0 +1,94 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: navidrome
spec:
interval: 10m
chartRef:
kind: OCIRepository
name: navidrome
values:
controllers:
navidrome:
containers:
navidrome:
image:
repository: ghcr.io/navidrome/navidrome
tag: 0.60.3
env:
ND_DATAFOLDER: /data
ND_ENABLEDOWNLOADS: "true"
ND_ENABLEEXTERNALSERVICES: "false"
ND_ENABLESHARING: "false"
ND_ENABLESTARRATING: "false"
ND_LOGLEVEL: info
ND_MUSICFOLDER: /music
ND_PORT: &port 4533
ND_SCANSCHEDULE: 30m
# ND_BASEURL: https://navidrome.home.mirceanton.com
resources:
requests:
cpu: 20m
memory: 512Mi
limits:
memory: 2Gi
probes:
liveness:
enabled: true
readiness:
enabled: true
startup:
enabled: true
spec:
failureThreshold: 30
periodSeconds: 5
securityContext:
allowPrivilegeEscalation: false
# readOnlyRootFilesystem: true
capabilities: { drop: ["ALL"] }
defaultPodOptions:
enableServiceLinks: false
securityContext:
runAsNonRoot: true
runAsUser: 568
runAsGroup: 568
fsGroup: 568
fsGroupChangePolicy: "OnRootMismatch"
service:
app:
ports:
http:
port: *port
route:
home:
hostnames: ["music.laurivan.com"]
parentRefs:
- name: envoy-internal
namespace: network-system
# tailscale: {}
persistence:
config:
existingClaim: navidrome
globalMounts:
- path: /data
music:
type: nfs
server: 10.0.0.14
path: /mnt/Main/shares/audio
globalMounts:
- path: /music
readOnly: true
cache:
type: emptyDir
globalMounts:
- path: /config/cache

View File

@@ -0,0 +1,7 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./helm-release.yaml
- ./oci-repository.yaml

View File

@@ -0,0 +1,15 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: navidrome
spec:
interval: 15m
url: oci://ghcr.io/bjw-s-labs/helm/app-template
ref:
tag: 4.6.2
layerSelector:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy

View File

@@ -0,0 +1,22 @@
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: "${APP}-volsync"
spec:
secretStoreRef:
kind: SecretStore
name: volsync-local
target:
name: "${APP}-volsync-secret"
template:
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ .RESTIC_REPOSITORY }}"
RESTIC_PASSWORD: "{{ .RESTIC_PASSWORD }}"
AWS_ACCESS_KEY_ID: "{{ .AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "{{ .AWS_SECRET_ACCESS_KEY }}"
dataFrom:
- extract:
key: volsync-sops-secret

View File

@@ -0,0 +1,10 @@
---
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- external-secret.yaml
- replication-source.yaml
- replication-destination.yaml
- pvc.yaml
- secret.sops.yaml

View File

@@ -0,0 +1,20 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.30.0/persistentvolumeclaim-v1.json
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: "${VOLSYNC_PVC:=${APP}}"
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled
spec:
storageClassName: "${VOLSYNC_STORAGECLASS:=openebs-zfs}"
accessModes: ["${VOLSYNC_ACCESSMODES:=ReadWriteOnce}"]
dataSourceRef:
kind: ReplicationDestination
apiGroup: volsync.backube
name: "${APP}-dst"
resources:
requests:
storage: "${VOLSYNC_CAPACITY:=5Gi}"

View File

@@ -0,0 +1,28 @@
---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationDestination
metadata:
name: "${APP}-dst"
labels:
kustomize.toolkit.fluxcd.io/ssa: IfNotPresent
spec:
trigger:
manual: restore-once
restic:
repository: "${APP}-volsync-secret"
copyMethod: Snapshot
volumeSnapshotClassName: "${VOLSYNC_SNAPSHOTCLASS:=openebs-snapshots}"
cacheStorageClassName: "${VOLSYNC_CACHE_SNAPSHOTCLASS:=openebs-zfs}"
cacheAccessModes: ["${VOLSYNC_CACHE_ACCESSMODES:=ReadWriteOnce}"]
cacheCapacity: "${VOLSYNC_CACHE_CAPACITY:=5Gi}"
storageClassName: "${VOLSYNC_STORAGECLASS:=openebs-zfs}"
accessModes: ["${VOLSYNC_ACCESSMODES:=ReadWriteOnce}"]
capacity: "${VOLSYNC_CAPACITY:=5Gi}"
moverSecurityContext:
runAsUser: ${VOLSYNC_PUID:=1000}
runAsGroup: ${VOLSYNC_PGID:=1000}
fsGroup: ${VOLSYNC_PGID:=1000}
fsGroupChangePolicy: "OnRootMismatch"
enableFileDeletion: true
cleanupCachePVC: true
cleanupTempPVC: true

View File

@@ -0,0 +1,31 @@
---
# yaml-language-server: $schema=https://k8s-schemas.m00nlit.dev/volsync.backube/replicationsource_v1alpha1.json
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: "${APP}"
spec:
sourcePVC: "${VOLSYNC_PVC:=${APP}}"
trigger:
schedule: "0 */2 * * *"
restic:
copyMethod: "${VOLSYNC_COPYMETHOD:=Snapshot}"
pruneIntervalDays: 14
repository: "${APP}-volsync-secret"
volumeSnapshotClassName: "${VOLSYNC_SNAPSHOTCLASS:=openebs-snapshots}"
cacheCapacity: "${VOLSYNC_CACHE_CAPACITY:=5Gi}"
cacheStorageClassName: "${VOLSYNC_CACHE_SNAPSHOTCLASS:=openebs-zfs}"
cacheAccessModes: ["${VOLSYNC_CACHE_ACCESSMODES:=ReadWriteOnce}"]
storageClassName: "${VOLSYNC_STORAGECLASS:=openebs-zfs}"
accessModes: ["${VOLSYNC_SNAP_ACCESSMODES:=ReadWriteOnce}"]
moverSecurityContext:
runAsUser: ${VOLSYNC_PUID:=1000}
runAsGroup: ${VOLSYNC_PGID:=1000}
fsGroup: ${VOLSYNC_PGID:=1000}
fsGroupChangePolicy: "OnRootMismatch"
retain:
hourly: 24
daily: 7

View File

@@ -0,0 +1,25 @@
apiVersion: v1
kind: Secret
metadata:
name: volsync-sops-secret
stringData:
RESTIC_REPOSITORY: ENC[AES256_GCM,data:IKeoMJMhqvBW9M0Et8st1DrcrkQuw9VH/Mdmz9OGorm7ECPIxKQseQ6J6IkW9LqOt9kXjNFbiA==,iv:DnSDCC82nlmoH5SliGbdbAZRcUyYpgWKfS2BhTXIy/0=,tag:jAd08ZsqUDFt/cd2H79QsA==,type:str]
RESTIC_PASSWORD: ENC[AES256_GCM,data:DYOgxKL/isykzUPQeroucni999HArY8kp/2l6Fq2RLuI8LJRqTd0q/6qCeEe1G0=,iv:VPc1BW8q8yMnjOpL9ys0TloxeE12YL4IK0QdUhXyP8w=,tag:MlYI3TIDlSIOtgaP6k0myg==,type:str]
AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:DQ4XP510iouZxHk1quzldRyxQnxerhSBj2M=,iv:HQIIDDLhgMUd/FVk9GLE+Mr7NzPVlLbng1uV8zc/ZHE=,tag:1bNVkRplUbQ0cu+tA7GakA==,type:str]
AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:RB2Du0GVSyoBXIrLbc5Lqa5XJPRdgyLDp0LaOR1KiX8Fsu6Y18mZVrHuGJSMyUkvtkiw1r6WM7i6krnwJHmZmA==,iv:5SoDONSzqq3er07sJUNH0xvZ07jdvl9zxj+BIoZD2D4=,tag:OqOe20odWaS7CFcFWmjxyw==,type:str]
sops:
age:
- recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqRDRDT2JzZmF2RlcyREg5
aEgyZ0QwNTJQK2JYbDBrNjRhT3BNSzdFZGlzCndQVloyK1RUU281S1Q2YnI4eXQv
RVoxa0UxOFNEVkZwQzB3ZUhTNHBMTWcKLS0tIGZLMTZ3YUs3d2FHWVBtczJzdzhp
dUtWdGJ0cjhjREI5YnVzVDk5VGJJS0kKpa+N5XC8a5/V/eUgqZoosxrio9CJMTYS
TzhILOHxY59zNtl4Jw7QtIy27jWki4+318WnQ2XGHO5yPUitc1yPuA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-26T11:50:59Z"
mac: ENC[AES256_GCM,data:Mc8yc/04WdQZIDUXIosrA0s6fFw42OF+q+FUxkrWQhT37w2NfdMq8PIWUT4TwlbWthoHZRfTP/vLW6/p6fvKYrc+bjFGdwa4CHSXq5CdhqTZEt0VBA1XyjYh06k01Sf7JFK0X4YlolR6qrmyloibh6reW25Sq7xjU+HI/x1mmWA=,iv:FbUCwU8lfpPebBXFngVhqOO+cc/u8/CT+cC2qBN+h6I=,tag:O1uAYkFi+TmrWO/EwJtUbg==,type:str]
encrypted_regex: ^(data|stringData)$
mac_only_encrypted: true
version: 3.11.0