From 3598969583b578369ef9aeef3800f4d9fd5766f3 Mon Sep 17 00:00:00 2001 From: Oleksandr Berezovskyi Date: Wed, 11 Mar 2026 19:31:13 +0200 Subject: [PATCH] feat(k8s/grocy): add grocy stack (deployment scaled to 0 for data migration) --- kubernetes/app/grocy/cronjob-backup.yaml | 76 ++++++++++++++++ kubernetes/app/grocy/deployment.yaml | 96 ++++++++++++++++++++ kubernetes/app/grocy/ingress.yaml | 24 +++++ kubernetes/app/grocy/namespace.yaml | 4 + kubernetes/app/grocy/networkpolicy.yaml | 50 ++++++++++ kubernetes/app/grocy/pv-config.yaml | 32 +++++++ kubernetes/app/grocy/pvc.yaml | 12 +++ kubernetes/app/grocy/secret-backup.sops.yaml | 26 ++++++ kubernetes/app/grocy/service.yaml | 12 +++ kubernetes/config/cluster-vars.sops.yaml | 58 ++++++------ 10 files changed, 362 insertions(+), 28 deletions(-) create mode 100644 kubernetes/app/grocy/cronjob-backup.yaml create mode 100644 kubernetes/app/grocy/deployment.yaml create mode 100644 kubernetes/app/grocy/ingress.yaml create mode 100644 kubernetes/app/grocy/namespace.yaml create mode 100644 kubernetes/app/grocy/networkpolicy.yaml create mode 100644 kubernetes/app/grocy/pv-config.yaml create mode 100644 kubernetes/app/grocy/pvc.yaml create mode 100644 kubernetes/app/grocy/secret-backup.sops.yaml create mode 100644 kubernetes/app/grocy/service.yaml diff --git a/kubernetes/app/grocy/cronjob-backup.yaml b/kubernetes/app/grocy/cronjob-backup.yaml new file mode 100644 index 0000000..aee6539 --- /dev/null +++ b/kubernetes/app/grocy/cronjob-backup.yaml @@ -0,0 +1,76 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: grocy-config-backup + namespace: grocy + labels: + app: grocy-backup +spec: + schedule: "0 2 * * *" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + template: + metadata: + labels: + app: grocy-backup + spec: + restartPolicy: OnFailure + initContainers: + - name: sqlite-backup + image: alpine:3.21 + command: + - sh + - -c + - | + apk add --no-cache sqlite + sqlite3 /db-local/grocy.db ".backup /backup/grocy.db" + volumeMounts: + - name: db + mountPath: /db-local + readOnly: true + - name: backup-tmp + mountPath: /backup + containers: + - name: resticprofile + image: creativeprojects/resticprofile:0.32.0 + command: + - sh + - -c + - | + resticprofile -c /secrets/profiles.yaml -n grocy-config backup + resticprofile -c /secrets/profiles.yaml -n grocy-config copy + env: + - name: B2_ACCOUNT_ID + valueFrom: + secretKeyRef: + name: grocy-backup-config + key: B2_ACCOUNT_ID + - name: B2_ACCOUNT_KEY + valueFrom: + secretKeyRef: + name: grocy-backup-config + key: B2_ACCOUNT_KEY + volumeMounts: + - name: secrets + mountPath: /secrets + readOnly: true + - name: config + mountPath: /config + readOnly: true + - name: backup-tmp + mountPath: /backup + volumes: + - name: secrets + secret: + secretName: grocy-backup-config + - name: config + persistentVolumeClaim: + claimName: grocy-config + - name: db + persistentVolumeClaim: + claimName: grocy-db + - name: backup-tmp + emptyDir: {} diff --git a/kubernetes/app/grocy/deployment.yaml b/kubernetes/app/grocy/deployment.yaml new file mode 100644 index 0000000..ea7c45a --- /dev/null +++ b/kubernetes/app/grocy/deployment.yaml @@ -0,0 +1,96 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grocy + namespace: grocy + labels: + app: grocy +spec: + replicas: 0 + strategy: + type: Recreate + selector: + matchLabels: + app: grocy + template: + metadata: + labels: + app: grocy + spec: + securityContext: + # runAsNonRoot omitted — LinuxServer image requires root for s6-overlay init + seccompProfile: + type: RuntimeDefault + initContainers: + - name: migrate-db-to-local + image: busybox:1.36 + command: + - sh + - -c + - | + if [ ! -d /config/data ]; then + echo "No /config/data yet — skipping" + exit 0 + fi + cd /config/data + for db in *.db; do + [ -f "$db" ] && [ ! -L "$db" ] || continue + echo "Migrating $db to local storage..." + cp "$db" "/db-local/$db" + rm -f "$db" + ln -sf "/db-local/$db" "$db" + done + echo "Done" + volumeMounts: + - name: config + mountPath: /config + - name: db + mountPath: /db-local + containers: + - name: grocy + image: linuxserver/grocy:4.6.0 + ports: + - containerPort: 80 + name: http + protocol: TCP + env: + - name: PUID + value: "1027" + - name: PGID + value: "100" + - name: TZ + value: Etc/UTC + - name: UMASK + value: "002" + - name: GROCY_AUTH_CLASS + value: "Grocy\\Middleware\\ReverseProxyAuthMiddleware" + - name: GROCY_REVERSE_PROXY_AUTH_HEADER + value: Remote-User + volumeMounts: + - name: config + mountPath: /config + - name: db + mountPath: /db-local + livenessProbe: + tcpSocket: + port: 80 + initialDelaySeconds: 90 + periodSeconds: 30 + readinessProbe: + tcpSocket: + port: 80 + initialDelaySeconds: 30 + periodSeconds: 10 + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + memory: 512Mi + volumes: + - name: config + persistentVolumeClaim: + claimName: grocy-config + - name: db + persistentVolumeClaim: + claimName: grocy-db diff --git a/kubernetes/app/grocy/ingress.yaml b/kubernetes/app/grocy/ingress.yaml new file mode 100644 index 0000000..83ada6e --- /dev/null +++ b/kubernetes/app/grocy/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: grocy + namespace: grocy + annotations: + cert-manager.io/cluster-issuer: letsencrypt + traefik.ingress.kubernetes.io/router.middlewares: authelia-chain-authelia-authelia-auth@kubernetescrd +spec: + tls: + - hosts: + - ${GROCY_HOST} + secretName: grocy-tls + rules: + - host: ${GROCY_HOST} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: grocy + port: + number: 80 diff --git a/kubernetes/app/grocy/namespace.yaml b/kubernetes/app/grocy/namespace.yaml new file mode 100644 index 0000000..6ff555d --- /dev/null +++ b/kubernetes/app/grocy/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: grocy diff --git a/kubernetes/app/grocy/networkpolicy.yaml b/kubernetes/app/grocy/networkpolicy.yaml new file mode 100644 index 0000000..4107c37 --- /dev/null +++ b/kubernetes/app/grocy/networkpolicy.yaml @@ -0,0 +1,50 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-deny-ingress + namespace: grocy +spec: + podSelector: {} + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-ingress-controller + namespace: grocy +spec: + podSelector: + matchLabels: + app: grocy + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: traefik +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-backup-egress + namespace: grocy +spec: + podSelector: + matchLabels: + app: grocy-backup + policyTypes: + - Egress + egress: + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - ports: + - port: 8888 + protocol: TCP + - ports: + - port: 443 + protocol: TCP diff --git a/kubernetes/app/grocy/pv-config.yaml b/kubernetes/app/grocy/pv-config.yaml new file mode 100644 index 0000000..af07eeb --- /dev/null +++ b/kubernetes/app/grocy/pv-config.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: grocy-config-nfs +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + storageClassName: "" + persistentVolumeReclaimPolicy: Retain + mountOptions: + - hard + - timeo=30 + - retrans=3 + nfs: + server: synology.storage.lviv + path: ${GROCY_NFS_PATH} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: grocy-config + namespace: grocy +spec: + accessModes: + - ReadWriteOnce + storageClassName: "" + volumeName: grocy-config-nfs + resources: + requests: + storage: 5Gi diff --git a/kubernetes/app/grocy/pvc.yaml b/kubernetes/app/grocy/pvc.yaml new file mode 100644 index 0000000..9ac2786 --- /dev/null +++ b/kubernetes/app/grocy/pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: grocy-db + namespace: grocy +spec: + accessModes: + - ReadWriteOnce + storageClassName: local-path + resources: + requests: + storage: 1Gi diff --git a/kubernetes/app/grocy/secret-backup.sops.yaml b/kubernetes/app/grocy/secret-backup.sops.yaml new file mode 100644 index 0000000..9dcbaad --- /dev/null +++ b/kubernetes/app/grocy/secret-backup.sops.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Secret +metadata: + name: grocy-backup-config + namespace: grocy +stringData: + profiles.yaml: ENC[AES256_GCM,data:oCTBX2/3P6xmhgi4ObZ81gl8goRVbqn1kL0ZNbiyurzX+omqsk7RrpVpKXsBwAXbqDIvwAk6gWyFQwT3g8LQEzpLJTXLSJE4pNSlpK3V02xtWzQu+28rPptnpRKqYqLM7DGeTmm1AJwzTNaCG7X46RBCc1gWP8S6vXvjjwpdqpsJH3G2zQpZsx8fmlRC3Vc38DWq1EQatnOi+RFMd2e7WufL6Yari9r14E8tpp3s1CZ1qwQ9W9K5uHAjXI+kuPL/NVRqYzkqwuSvmD4QTtHhH1eyu3WFIkIkah1tDYAivy+wCZjMLSe+q6heHiXIMV5IaVj0tTg/L5wbjwwQZXB53nnbuadViPuC3kFBej7QHkx6hwIMmEgKsp2skG7mFFLkYm9AXDOUxUZlrVU3eN47PxR2nFNYiWoQi5YSYkltBA4eEFZ9d4EKFcxWqj1tr7Y4VDtTjz2ZEfff/eyu8oJ75XdFb74Or8PXBKfFUpLjtOnax7Dc7Ff/fv1oTCvmHSxyv4pgdCfrkwERnMd5DspkxEppCqPpxtxMVIp31cAWDkvJ21wmCR9esCVHfe1eTj4+76Ok7c3vEXy49M/K9GstwPIWcEwiDrvftiXMEgHn95YRcNBGdjh3nLJ76DTO+pTsuVoOW5Bogcn4W7hGrgYKFFFESMzXUWRlF15YPN0RHg/2TI0I9Ke1lIOhUZj1ljefH9UwnERhKmXZ7AlsXvDPqUpYPwPmW55bbkDDa/VDp58BLA==,iv:tfWTMYk99Jkje9GAHLEUu77LIIP3XQjWaR25HQYHOLg=,tag:chdgdkDNp57f3OCIEOcYTw==,type:str] + restic-password-nas: ENC[AES256_GCM,data:bG0LFnoo84t/r+cOGwjBPALc4dzrUj3Y9sMIuF7W1bjEkC9XsvSTQkczK1vmevhKuWdaaPYBr72gFzHcga7hUQ==,iv:tD1zf/mWknbMWtn/k0o8zJPcNvBK2Xa12eNSPyarybI=,tag:b03st6HrnpgXgkjDn0Gp+Q==,type:str] + restic-password-b2: ENC[AES256_GCM,data:nyDMggQFE5Z2aCz/+kTdIIYe2BXisTb/MlVRfiRMCKjPPZDQ49jyf3z986jEXp9CyxKK665ySjnZEXn3txi/PQ==,iv:xvdCBKhlFPMH4cTXSm2VtFlpJlgbiggvdvfyjB7b76I=,tag:HEoizYHWcnkVTAe3APWsMA==,type:str] + B2_ACCOUNT_ID: ENC[AES256_GCM,data:iXPdIOHzrggnh2pjimgFpQPNmA2FZgj8Mg==,iv:uS91Eg9xOHdZH113zfzlldgmCnFTopuOx/mmlsQsUC8=,tag:QDtAIhKwUkpt3v/tRZBYFA==,type:str] + B2_ACCOUNT_KEY: ENC[AES256_GCM,data:RLT5JBRs7JfcJzFv6MilqXUTf5MocOeB1Pp1kQaUcg==,iv:FqyfAgE0wM7KFdPTBM2s3eKrXvzeUCO7qLyUwZUCPqM=,tag:rM15UoD2CyZ4yRYAQJ6xoA==,type:str] +sops: + age: + - recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArR1BFRmFZU3dJblVEVnRr + bksyUzVHU0NjUkY2bGlXMzh3N0VEall4TFNVCmlBOUM4UnBPeVRPOHp3SnI5djUr + elpodVdqSWt2L0ovMFZCNUZTVkxIcVEKLS0tIDRvNzdSQ3hxN0o3R3ViSzJoQi9E + eDZTN3Fzak81RDJPR2dVOHlKOHJURzAK8DUPG6iCb6s7CQ6/+TZrIcLDKbN8bmh6 + lUwBN0Ciu8OAX+tRW6P3R/iZebc9s5jH/VkzGsR9qGjKw5BsNB811Q== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T19:28:51Z" + mac: ENC[AES256_GCM,data:2SpDKL7Mwu/h7KLQoBXnk9iB84XNaex8hVbaUqmq4myIHAzvntb/zLXOexhsKPbQ0Ea7QDOKZIpkAG2dBPtRMtZWTr9uPpMoHzQG2lDGnYKGvBJXW/7WmaCdXlDf1FukqnYJZ3YoY+5xpTpYpXbWv1fyygp1YWmjKzY5qfcjtvw=,iv:TNbbiRmRRvPuQKiBjan7CVylNrt+eTjXxwKTJbeOhLw=,tag:9bqc9L4LlSq/d+oT257rsQ==,type:str] + encrypted_regex: ^(data|stringData|email)$ + version: 3.12.1 diff --git a/kubernetes/app/grocy/service.yaml b/kubernetes/app/grocy/service.yaml new file mode 100644 index 0000000..6a88bd0 --- /dev/null +++ b/kubernetes/app/grocy/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: grocy + namespace: grocy +spec: + selector: + app: grocy + ports: + - port: 80 + targetPort: 80 + name: http diff --git a/kubernetes/config/cluster-vars.sops.yaml b/kubernetes/config/cluster-vars.sops.yaml index bf55794..9c0c306 100644 --- a/kubernetes/config/cluster-vars.sops.yaml +++ b/kubernetes/config/cluster-vars.sops.yaml @@ -4,39 +4,41 @@ metadata: name: cluster-vars namespace: flux-system stringData: - LUBELOGGER_HOST: ENC[AES256_GCM,data:OvDY/XIE/YW8lSDJmhHYI63r4eLQOojsMjjkUIge,iv:v1JafZB4cmVFjX+yA7FjjoXfx7jPpZQaq1HyXvNXvsY=,tag:+h5Gg/q3bKP3l7xCNLaBqA==,type:str] - AUTHELIA_DOMAIN: ENC[AES256_GCM,data:mioy6n5AqiN8jPU9cMTO,iv:HFjyN0UCohNxuJkmt9dgcvnjHSTSAr7svin9Fjjykk8=,tag:2aknDljwRFGJBTzzmQ2UFA==,type:str] - QBITTORRENT_HOST: ENC[AES256_GCM,data:OxaHKav3STl9FKV0qtJ0FpfTHgSrvCXrkP25,iv:wzfie/2YkZH0A6R3wF3BJV8U5aKhewjQ7c9AfstFQMI=,tag:rxHw0XhzqBm/rN4OytclgQ==,type:str] - SONARR_HOST: ENC[AES256_GCM,data:dMEgQYHxa0tIilY8HPkppFgOWzH52Q==,iv:yCUF8ZVOSY2IfULa9B44ALGjgFyZyQrQWPZsyQzqwbM=,tag:kfhsZhPE1rZNYUJ3X2rRSQ==,type:str] - RADARR_HOST: ENC[AES256_GCM,data:lsWSI+D/qzru3qHGvJjKRepYEGHe5Q==,iv:cq9yNVCMuon+ZUpFwfkwBvVg9oIT0MXagjDi6l/29YA=,tag:koGF34SrtHe0brRiNKP8rg==,type:str] - MEDIA_NFS_PATH: ENC[AES256_GCM,data:BSDMu0n2Vx4koYBIMF8=,iv:c9kGdcTxObNaaaTzEhSRkyHvo+dxSN+o+96n9UqJieU=,tag:W9+MbyAuK85xajjwntRi0Q==,type:str] - IMMICH_HOST: ENC[AES256_GCM,data:KnzX89wzQvb5Pa/MqX4YiHZ0JS5geA==,iv:05jEIwQEjJnvZ1Ot33Lkfs1TB3L/mwX5dqaTfsugcx4=,tag:LFzOLZSqHQ58bL3oVvGM9g==,type:str] - IMMICH_UPLOAD_NFS_PATH: ENC[AES256_GCM,data:l8F1AkmhGkNxo29X5UER,iv:Z/u0yLNv5ClQu44lPPzGIB2bEsADFCD/mCd+Kw8kuhc=,tag:a8QGaUEYF3iJbZKcAiRKUg==,type:str] - JELLYFIN_HOST: ENC[AES256_GCM,data:88I8uzcJa/VwsWOJDe69bUsdGbXzTIGI,iv:TWIALVMMDV9VV7iz0OMsVJ8Cvh13VI54KmACR2utlJI=,tag:yDx1vGk/WfFXaQrnLbhLVA==,type:str] - JELLYFIN_INTERNAL_HOST: ENC[AES256_GCM,data:YejsUFRECjSKRYqq35NwV2kH4KM0,iv:H4iPxmlxXZk3XCfatpRBDgg/+H7FS5CDJInRDe0+QQc=,tag:wLOFdyZUhj15dT64u54o8Q==,type:str] - ARCHMIRROR_HOST: ENC[AES256_GCM,data:lCi7iVRn7yITYLi63kWdZXw7mCGXoe4=,iv:vuk/YuwfiBZhLS2+k1+WkNq96XrWA6BWtGjjWkKqTXc=,tag:Z0HJzMAmFSJvPkVPpIdFzg==,type:str] - ARCHMIRROR_NFS_PATH: ENC[AES256_GCM,data:RHNbu/Jobo8Q5DzKjF4RojvrYQ==,iv:khpEqK0KzdZeZm8qKZ3MJQDk2P799FBCNPOJGx4Tdhk=,tag:CKHeuRZttLRwN6noSaehDQ==,type:str] - ARCHMIRROR_MIRROR_URL: ENC[AES256_GCM,data:cIORJWshvr4fL/OqyvplXllcrMdh3UMrt11cBqwgS12O3wGBgyULJNDcP7c2,iv:8Efs43us8xlUvkafWf15K5wqBoJnYLmC50j094taoFs=,tag:6hV2emMunQ1jOteRCANRsA==,type:str] - PODSYNC_HOST: ENC[AES256_GCM,data:MK+WWo8R2uS45U8suBDusOp922YqngM=,iv:7QfuVU6ICEmpNwtgpnXa2phwP0+0pcmv8w3CJSLwvrA=,tag:z6qizhm8fzzDZq/726kKsQ==,type:str] - PODSYNC_NFS_PATH: ENC[AES256_GCM,data:O1ZHSOsmwe57nY0T42pHOHcc/aB9,iv:FS4Yb9F4mzrvKni0hg6HD22R83v3YoGlDAeEPBc4RzE=,tag:f+Wi8BOPIVod/8upGZmw5A==,type:str] - PIHOLE_HOST: ENC[AES256_GCM,data:LysbDrRB3nmYkuJrvnNTJ4mlN52w3Q==,iv:pp1wubLuF69IRFJtkLlPC1EeW/whQNLwXeOiNvFlsPI=,tag:rSgcD4HmzJsynuPwU4GB/Q==,type:str] - PAPERLESS_HOST: ENC[AES256_GCM,data:M9h/Z0jesAhEZ30Lm9SrXesfVlTrL3EkxA==,iv:ZOXF8kRnD/2tu/uFRJ1IAwQ1MYR29aepJleBxfrBm8k=,tag:3NQ742Y2zeJbyz/8Od2GLA==,type:str] - PAPERLESS_MEDIA_NFS_PATH: ENC[AES256_GCM,data:anrMuEdnLC5+EmvgZeXXsJSg,iv:aJDdeUAvMy33HKGd+y4YWFVPRqgxi7hAuTVZSEnHKMI=,tag:zCKmxT0BCyzUubaQOkbXHg==,type:str] - PAPERLESS_CONSUME_NFS_PATH: ENC[AES256_GCM,data:q4s+bz9Zvs9dXRoCO3MyaHe/7h5fw0Y=,iv:CkInWz0cI1FMWMxJD+Tfy+IJL3HXQX0fY3iEZ4qed3A=,tag:PwCnIqMoRiVWPFQ1uNGODA==,type:str] - PAPERLESS_DATA_NFS_PATH: ENC[AES256_GCM,data:N3JgoXmQkZULA0WcABuPcuKkoOgoyPcnB5EpqS3iykGRtU0=,iv:BUnaXtjMWibztesA6T5nm76RDZFfp+gmzSPa8oinyKc=,tag:yb7/3aHut+y0JJXjqinVag==,type:str] - BACKUP_LOCAL_HOST: ENC[AES256_GCM,data:kqF7CnCVd4lEnQL2xWOibTR4jG25obGjVLA=,iv:EPlmBtLeNtEu5e9AGuMt7hjn53dgpWSVScOfPDqQMwM=,tag:fHdiv+FPG/6MlJiS4dcPTg==,type:str] + LUBELOGGER_HOST: ENC[AES256_GCM,data:HrDEsPVsHq11duKPoDAoE1joPbit19hG5WQSnXWy,iv:ev5942LVrGgCpoXQxQnn4PEfSdVkFtczqFXccrjA7NE=,tag:4nROFq9x677vedwDRy31Lg==,type:str] + AUTHELIA_DOMAIN: ENC[AES256_GCM,data:LsvZ4BILErmKx6PrIjh+,iv:4zx5TaNp4gJESYzXeNS3/rgUdWTJwI0io/Gor27+DoQ=,tag:Lb8vV9wAgCtjiGoWbrmcUA==,type:str] + QBITTORRENT_HOST: ENC[AES256_GCM,data:N33q1ZbT9cBmZoiWjU+qIrJspQv0cdqh31mc,iv:VbpFAytIWAFgfUsNzzkUkAbR1oK9itPQ8FXDtep56VE=,tag:ZSJNA+iV/VgirnarIxH4XA==,type:str] + SONARR_HOST: ENC[AES256_GCM,data:TA6Rg9C7GN5Ks2Uav039hxXNeAZPFw==,iv:HwliibyhhCp+tL21lpLraPmgIh5uaz5FYS8+pSu56U0=,tag:50OmAJnI3JZAifGOcJWBUw==,type:str] + RADARR_HOST: ENC[AES256_GCM,data:R1LqeTlMSKPmwROUmOhq/qv6Y87W1w==,iv:goiAYymGKAOXGwmVuBGFyR+fMJS2JaJQjys1sa1+aRE=,tag:aWkfuUQ2ZkBVT7FyroksFg==,type:str] + MEDIA_NFS_PATH: ENC[AES256_GCM,data:G6YG9daKWl6xhmGwTyU=,iv:xb36BVGukweHKnYgK3cVM0jxrEZ10VLpHpLtxxFhiMQ=,tag:Dt+W/wY4Je1a2lcBgQaSLQ==,type:str] + IMMICH_HOST: ENC[AES256_GCM,data:cRh5kj/PmchHM2Eq/13NSgyX8ttTJQ==,iv:04tFK3B333g0+U9JmxpssQitrig2A0KJYNvqWjIxhrY=,tag:UpSP8RLeFmzF2CJ/J5THXA==,type:str] + IMMICH_UPLOAD_NFS_PATH: ENC[AES256_GCM,data:JLzKt9Ftmd2wgRuMqecI,iv:5zwRZRcap4G9ULqD8OhDmNr5cj+Om7eOQMPVZXZf5aw=,tag:leX3nFtmTESQs7S94P6POA==,type:str] + JELLYFIN_HOST: ENC[AES256_GCM,data:zkVOPUcmML7n8kfLEtqhPpPW0DV8I+Ya,iv:kbmkFXiaZqBSrwgArEjw2OpbCUGME+avKZkmNrTARjU=,tag:SNZ9BrgZLCjdBrkYBVTnQw==,type:str] + JELLYFIN_INTERNAL_HOST: ENC[AES256_GCM,data:H2mIXWExMTNK/KGgZ23yJwU9UgrA,iv:fExcIONjgoZ4wXtg3m07dDpNC8HiwYpdI1xe/M2rbKI=,tag:qCHfqYz2XxOTbIHNmZ/zhA==,type:str] + ARCHMIRROR_HOST: ENC[AES256_GCM,data:0Zi3kKC93BzGx2q8rkgaZXXcG84aphc=,iv:znQil98xPn3I16M8cSLePAZS+yI3fcoAHCxgzRFtEqg=,tag:l4t4Fi5bxgw25mGEP534Yg==,type:str] + ARCHMIRROR_NFS_PATH: ENC[AES256_GCM,data:3+1W0DToTqCoqawe7yM1mFFOdQ==,iv:QEhlVpYkfvDn6JaklNc4Qcot1quXMZXQRhjsaQ2SCVM=,tag:ZD5+E7v4XbfR6V4CJ3dOuw==,type:str] + ARCHMIRROR_MIRROR_URL: ENC[AES256_GCM,data:9xkMcri7BtWKFXjLZQlsfPQ2xhNGB3K4ECCrz1QO4JnkjsAx5+IZSOWXZjmi,iv:fuQtuS45TGTQKXJhkvWlpgjLgdxWEfepMocQlbt/yRk=,tag:+s3/mB6sf+rU5iS1YWm4aQ==,type:str] + PODSYNC_HOST: ENC[AES256_GCM,data:ThdS4iciwg/+00f+Akx1AbF7KvNb478=,iv:VXIfWEexxS0cYbQNGVLZ50cQXjtpFsHQnU0TH3Il+Q0=,tag:9+KtDDgCB09mMt8H4w7PsA==,type:str] + PODSYNC_NFS_PATH: ENC[AES256_GCM,data:JxMLRc8xDGZu5FiOigcjRTkxtipV,iv:NFmcgi8e3dorqjl+aPJEOwUecj/IVdKU2IaxxSufkMc=,tag:Ym/SqUM6uzat7xhAknC5rg==,type:str] + PIHOLE_HOST: ENC[AES256_GCM,data:3iGSFW7p+HvSYcyihGrvdzGwmK1L0A==,iv:/RH+TQmOZv1P4mIPjYAcgycJnJCbTDPSSs3UA/c/Lxc=,tag:aOTSsQGi2eoG6pK613ZRXA==,type:str] + PAPERLESS_HOST: ENC[AES256_GCM,data:j/s9gPdiT8wfwQnHlrgJSK+tybTyNLCHGg==,iv:m0uyAlmJqaDAHLdiOHXmFHrYejLSdqBLXRdCowYJoSE=,tag:BKPjq0VMvCZKbshHaghyzg==,type:str] + PAPERLESS_MEDIA_NFS_PATH: ENC[AES256_GCM,data:SYkyeeRi6thDKAv3qrBgLZxy,iv:5V3yzW1XbbDBnFFlrYRmBh+GZsvKFifoFg44UDIAHrw=,tag:r1+l74lBPjEk+hpXgRpPZg==,type:str] + PAPERLESS_CONSUME_NFS_PATH: ENC[AES256_GCM,data:8HATBIPqLrhERNoL98GC8L8WewvLRYw=,iv:QMPMbNOuSMAbpIxmL70EkxyrrmUGFWENVYDS6gc1IYE=,tag:E4NmSUSod10/EiXU7Z9NoQ==,type:str] + PAPERLESS_DATA_NFS_PATH: ENC[AES256_GCM,data:kOP2lFrnB8s2ijdJKyKYRjMsOb6J0qe4BC7mnhkTbXtgh20=,iv:IOFdMHRtd4mrWs+YEaKQw2J0CNDP30fVYyRu1jRXuBU=,tag:knbRcx3ILjlkZ56xoEUj0A==,type:str] + GROCY_HOST: ENC[AES256_GCM,data:3HpFEEHZk4xF/dxEGAbMl6GdNOBO,iv:swKQ5b2BRd6b6PThVt3n5SuA2mRSQI5t1WgAhXEcosI=,tag:iIA8waTfhZvTxJpT1rAN4A==,type:str] + GROCY_NFS_PATH: ENC[AES256_GCM,data:C4aYF6rk0p4bj+CflrIxouGxXhXEWtrEFeA188g/PB0G,iv:p3LSCFp4AeL+TSENgF06ZYdnV/R7ISGpN/v317Qm0DE=,tag:SmUPCsvoqj6dZU+R6jxP3g==,type:str] + BACKUP_LOCAL_HOST: ENC[AES256_GCM,data:hjDPylUCm7KHbxy+VFNTqo+QYyXDeLCzBKQ=,iv:ca1FgSI9qSE6jEcxnmAM7ua3jc4RltPzeRuVoB8PebE=,tag:Kt5IQSlmf5WusPahLgJ3Jw==,type:str] sops: age: - recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnQnMvTXBXZUg3eUhLTUtv - NlMxTmw2R0VVeXFBREdiYllweVE0elNqL0hRCjczS3NqVzlaTDhRSFdLMm5WREQx - ZG54Q2tRUk50bXZkd3FLQ3VXRUdaNEEKLS0tIDdpdSswc3pVQ1hFb1VhUWR3dFN4 - LzhUN3Z4cExIL1IyS3ZCNWh5aWpLbDgKQ7c3MmLykA00NaLoctKVDfJvPqTqh3Ia - cDZJUc6jYJXOJYM6YYyZOYcCL2z8V2RpIfA9sPg8PB2eiipZxjk+Cg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4aXRVYkp5ZVJqUVVPSEtt + S0Q4bHlidVZweldGUHFVOGpGTThnbWNiaHpVCjBuUDVqdkZUNFM4ZjJDamtqSC9R + bnRqYlYrMjBVa3UxSE1aRU1DWFhhZVUKLS0tIHRqUWtRak9XeFZsbFJFVDI1VnNF + OFl5QUJ3WXBXRkpXMWR5QU1ySjRzQ0EKA/B+4ulXXMkXgZi6E1sud549vwTtdK2h + N5eoVgO66EOTHUPNzsq4uWGh1ra1Qfyla8jt0C56fq8m6OBGkhtWtw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-11T12:09:29Z" - mac: ENC[AES256_GCM,data:slhySxwlC4iLR/Qcr6jloPWbJiWiIyy1aMsYYqatu3pM1bOyBDkrILU8SmsFky8lRG1ImYPMxb6nSmWqkA1i8QWQE9mkGSRN6dUw6E33d2l9ooA6vz5EMmjmO5vg/tzyrskCkeZqdGP+XecvwZMKkA4bLYr7ChKCRlmLOn9O4g4=,iv:b92aWORGUORbCNCg3ZcHr+BRntaOYg3q3aBPV84q680=,tag:OidID+Ymq38NpGH006CaJQ==,type:str] + lastmodified: "2026-03-11T15:53:22Z" + mac: ENC[AES256_GCM,data:bxwYEmbk6iDUVvDLnmjp4Nv+t+Pprb8fvzSXH41q42j5FbDVtxH6BvB2bkspcAur39py1oaUu0uA2eJlBkN2pGCjjXFGI2SoN6gtgJeiB+MbkTpegn7Otqw5w3z1zwmxbLxuxaay8iXOHSmrM8mvKE8GYAzF5xm0UyxR6RJtkDw=,iv:ydhHsGZAN16B2OccObSC0zg5i6Wfi/1Xh74/ZLo/XlY=,tag:WO0zKwUjzU3JazGjO5PdEA==,type:str] encrypted_regex: ^(data|stringData|email)$ version: 3.12.1