feat: Add Navidrome application and VolSync components, migrating media apps from beta.
This commit is contained in:
13
kubernetes/apps/media/kustomization.yaml
Normal file
13
kubernetes/apps/media/kustomization.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: media
|
||||
|
||||
resources:
|
||||
- ./namespace.yaml
|
||||
#- ./booklore
|
||||
#- ./feishin
|
||||
#- ./immich
|
||||
#- ./plex
|
||||
#- ./karakeep
|
||||
- ./navidrome
|
||||
0
kubernetes/apps/media/namespace.yaml
Normal file
0
kubernetes/apps/media/namespace.yaml
Normal file
31
kubernetes/apps/media/navidrome/app.ks.yaml
Normal file
31
kubernetes/apps/media/navidrome/app.ks.yaml
Normal 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
|
||||
94
kubernetes/apps/media/navidrome/app/helm-release.yaml
Normal file
94
kubernetes/apps/media/navidrome/app/helm-release.yaml
Normal 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
|
||||
7
kubernetes/apps/media/navidrome/app/kustomization.yaml
Normal file
7
kubernetes/apps/media/navidrome/app/kustomization.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ./helm-release.yaml
|
||||
- ./oci-repository.yaml
|
||||
15
kubernetes/apps/media/navidrome/app/oci-repository.yaml
Normal file
15
kubernetes/apps/media/navidrome/app/oci-repository.yaml
Normal 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
|
||||
0
kubernetes/apps/media/navidrome/kustomization.yaml
Normal file
0
kubernetes/apps/media/navidrome/kustomization.yaml
Normal file
22
kubernetes/components/volsync/external-secret.yaml
Normal file
22
kubernetes/components/volsync/external-secret.yaml
Normal 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
|
||||
10
kubernetes/components/volsync/kustomization.yaml
Normal file
10
kubernetes/components/volsync/kustomization.yaml
Normal 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
|
||||
20
kubernetes/components/volsync/pvc.yaml
Normal file
20
kubernetes/components/volsync/pvc.yaml
Normal 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}"
|
||||
28
kubernetes/components/volsync/replica-destination.yaml
Normal file
28
kubernetes/components/volsync/replica-destination.yaml
Normal 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
|
||||
31
kubernetes/components/volsync/replica-source.yaml
Normal file
31
kubernetes/components/volsync/replica-source.yaml
Normal 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
|
||||
25
kubernetes/components/volsync/secrets.sops.yaml
Normal file
25
kubernetes/components/volsync/secrets.sops.yaml
Normal 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
|
||||
Reference in New Issue
Block a user