diff --git a/clusters/cl01tl/helm/blocky/values.yaml b/clusters/cl01tl/helm/blocky/values.yaml index 6ad4b49d1..407baa3a9 100644 --- a/clusters/cl01tl/helm/blocky/values.yaml +++ b/clusters/cl01tl/helm/blocky/values.yaml @@ -123,6 +123,7 @@ blocky: gatus IN CNAME traefik-cl01tl gitea IN CNAME traefik-cl01tl grafana IN CNAME traefik-cl01tl + grimmory IN CNAME traefik-cl01tl harbor IN CNAME traefik-cl01tl headlamp IN CNAME traefik-cl01tl home IN CNAME traefik-cl01tl diff --git a/clusters/cl01tl/helm/gatus/values.yaml b/clusters/cl01tl/helm/gatus/values.yaml index b96cfc845..7da86bd18 100644 --- a/clusters/cl01tl/helm/gatus/values.yaml +++ b/clusters/cl01tl/helm/gatus/values.yaml @@ -167,6 +167,9 @@ gatus: - name: booklore url: https://booklore.alexlebens.net <<: *defaults + - name: grimmory + url: https://grimmory.alexlebens.net + <<: *defaults - name: directus url: https://directus.alexlebens.net <<: *defaults diff --git a/clusters/cl01tl/helm/grimmory/Chart.lock b/clusters/cl01tl/helm/grimmory/Chart.lock new file mode 100644 index 000000000..b95a61ca9 --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/Chart.lock @@ -0,0 +1,12 @@ +dependencies: +- name: app-template + repository: https://bjw-s-labs.github.io/helm-charts/ + version: 4.6.2 +- name: mariadb-cluster + repository: https://helm.mariadb.com/mariadb-operator + version: 26.3.0 +- name: volsync-target + repository: oci://harbor.alexlebens.net/helm-charts + version: 0.8.0 +digest: sha256:6ee403da03c1bcc0289a9abdef0508344072d51173da996eda69b8305d5feefa +generated: "2026-03-23T20:35:19.743257-05:00" diff --git a/clusters/cl01tl/helm/grimmory/Chart.yaml b/clusters/cl01tl/helm/grimmory/Chart.yaml new file mode 100644 index 000000000..170e7a21e --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/Chart.yaml @@ -0,0 +1,31 @@ +apiVersion: v2 +name: grimmory +version: 1.0.0 +description: Grimmory +keywords: + - grimmory + - books +home: https://docs.alexlebens.dev/applications/grimmory/ +sources: + - https://github.com/grimmory-tools/grimmory + - https://github.com/grimmory-tools/grimmory/pkgs/container/grimmory + - https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template + - https://github.com/mariadb-operator/mariadb-operator/tree/main/deploy/charts/mariadb-cluster + - https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/volsync-target +maintainers: + - name: alexlebens +dependencies: + - name: app-template + alias: grimmory + repository: https://bjw-s-labs.github.io/helm-charts/ + version: 4.6.2 + - name: mariadb-cluster + version: 26.3.0 + repository: https://helm.mariadb.com/mariadb-operator + - name: volsync-target + alias: volsync-target-config + version: 0.8.0 + repository: oci://harbor.alexlebens.net/helm-charts +icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/grimmory.png +# renovate: datasource=github-releases depName=grimmory-tools/grimmory +appVersion: v2.3.0 diff --git a/clusters/cl01tl/helm/grimmory/templates/external-secret.yaml b/clusters/cl01tl/helm/grimmory/templates/external-secret.yaml new file mode 100644 index 000000000..9fca43d78 --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/templates/external-secret.yaml @@ -0,0 +1,143 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: grimmory-database-secret + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-database-secret + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + secretStoreRef: + kind: ClusterSecretStore + name: vault + data: + - secretKey: password + remoteRef: + key: /cl01tl/grimmory/database + property: password + +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: grimmory-data-replication-secret + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-data-replication-secret + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + secretStoreRef: + kind: ClusterSecretStore + name: vault + data: + - secretKey: psk.txt + remoteRef: + key: /cl01tl/grimmory/replication + property: psk.txt + +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: grimmory-mariadb-cluster-backup-secret-external + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-mariadb-cluster-backup-secret-external + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + secretStoreRef: + kind: ClusterSecretStore + name: vault + data: + - secretKey: access + remoteRef: + key: /digital-ocean/home-infra/mariadb-backups + property: access + - secretKey: secret + remoteRef: + key: /digital-ocean/home-infra/mariadb-backups + property: secret + +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: grimmory-mariadb-cluster-backup-secret-garage + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-mariadb-cluster-backup-secret-garage + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + secretStoreRef: + kind: ClusterSecretStore + name: vault + data: + - secretKey: access + remoteRef: + key: /garage/home-infra/mariadb-backups + property: access + - secretKey: secret + remoteRef: + key: /garage/home-infra/mariadb-backups + property: secret + +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: booklore-config-backup-secret-local + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: booklore-config-backup-secret-local + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + secretStoreRef: + kind: ClusterSecretStore + name: vault + target: + template: + engineVersion: v2 + mergePolicy: Merge + data: + RESTIC_REPOSITORY: '{{ .BUCKET_ENDPOINT }}/booklore/booklore-config' + data: + - remoteRef: + conversionStrategy: Default + decodingStrategy: None + key: /volsync/restic/garage-local + metadataPolicy: None + property: BUCKET_ENDPOINT + secretKey: BUCKET_ENDPOINT + - remoteRef: + conversionStrategy: Default + decodingStrategy: None + key: /volsync/restic/garage-local + metadataPolicy: None + property: RESTIC_PASSWORD + secretKey: RESTIC_PASSWORD + - remoteRef: + conversionStrategy: Default + decodingStrategy: None + key: /garage/home-infra/volsync-backups + metadataPolicy: None + property: ACCESS_REGION + secretKey: AWS_DEFAULT_REGION + - remoteRef: + conversionStrategy: Default + decodingStrategy: None + key: /garage/home-infra/volsync-backups + metadataPolicy: None + property: ACCESS_KEY_ID + secretKey: AWS_ACCESS_KEY_ID + - remoteRef: + conversionStrategy: Default + decodingStrategy: None + key: /garage/home-infra/volsync-backups + metadataPolicy: None + property: ACCESS_SECRET_KEY + secretKey: AWS_SECRET_ACCESS_KEY diff --git a/clusters/cl01tl/helm/grimmory/templates/namespace.yaml b/clusters/cl01tl/helm/grimmory/templates/namespace.yaml new file mode 100644 index 000000000..7fb67e59e --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/templates/namespace.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: grimmory + annotations: + volsync.backube/privileged-movers: "true" + labels: + app.kubernetes.io/name: grimmory + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + pod-security.kubernetes.io/audit: privileged + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/warn: privileged diff --git a/clusters/cl01tl/helm/grimmory/templates/persistent-volume-claim.yaml b/clusters/cl01tl/helm/grimmory/templates/persistent-volume-claim.yaml new file mode 100644 index 000000000..18a0b7bb0 --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/templates/persistent-volume-claim.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: grimmory-books-nfs-storage + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-books-nfs-storage + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + volumeName: grimmory-books-nfs-storage + storageClassName: nfs-client + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: grimmory-books-import-nfs-storage + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-books-import-nfs-storage + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + volumeName: grimmory-books-import-nfs-storage + storageClassName: nfs-client + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi diff --git a/clusters/cl01tl/helm/grimmory/templates/persistent-volume.yaml b/clusters/cl01tl/helm/grimmory/templates/persistent-volume.yaml new file mode 100644 index 000000000..3ec10052a --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/templates/persistent-volume.yaml @@ -0,0 +1,48 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: grimmory-books-nfs-storage + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-books-nfs-storage + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs-client + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + nfs: + path: /volume2/Storage/Books + server: synologybond.alexlebens.net + mountOptions: + - vers=4 + - minorversion=1 + - noac + +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: grimmory-books-import-nfs-storage + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-books-import-nfs-storage + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs-client + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + nfs: + path: /volume2/Storage/Books Import + server: synologybond.alexlebens.net + mountOptions: + - vers=4 + - minorversion=1 + - noac diff --git a/clusters/cl01tl/helm/grimmory/templates/replication-destination.yaml b/clusters/cl01tl/helm/grimmory/templates/replication-destination.yaml new file mode 100644 index 000000000..97bb9368d --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/templates/replication-destination.yaml @@ -0,0 +1,16 @@ +apiVersion: volsync.backube/v1alpha1 +kind: ReplicationDestination +metadata: + name: grimmory-config-restore + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grimmory-config-restore + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + trigger: + manual: restore-once + restic: + repository: booklore-config-backup-secret-local + destinationPVC: grimmory-config + copyMethod: Direct diff --git a/clusters/cl01tl/helm/grimmory/values.yaml b/clusters/cl01tl/helm/grimmory/values.yaml new file mode 100644 index 000000000..addbca236 --- /dev/null +++ b/clusters/cl01tl/helm/grimmory/values.yaml @@ -0,0 +1,233 @@ +grimmory: + controllers: + main: + type: deployment + replicas: 0 + strategy: Recreate + pod: + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: OnRootMismatch + containers: + main: + image: + repository: ghcr.io/grimmory-tools/grimmory + tag: v2.3.0@sha256:9014247f591074529894f81115ca40f899db697e89f72c2fe91ec530e3f19597 + env: + - name: TZ + value: America/Chicago + - name: USER_ID + value: 1000 + - name: GROUP_ID + value: 1000 + - name: DATABASE_URL + value: jdbc:mariadb://grimmory-mariadb-cluster-primary.grimmory:3306/booklore + - name: DATABASE_USERNAME + value: grimmory + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: grimmory-database-secret + key: password + - name: GRIMMORY_PORT + value: 6060 + - name: SWAGGER_ENABLED + value: false + resources: + requests: + cpu: 10m + memory: 1Gi + service: + main: + controller: main + ports: + http: + port: 80 + targetPort: 6060 + protocol: HTTP + route: + main: + kind: HTTPRoute + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: traefik-gateway + namespace: traefik + hostnames: + - grimmory.alexlebens.net + rules: + - backendRefs: + - name: grimmory + port: 80 + matches: + - path: + type: PathPrefix + value: / + persistence: + config: + forceRename: grimmory-config + storageClass: ceph-block + accessMode: ReadWriteOnce + size: 5Gi + advancedMounts: + main: + main: + - path: /app/data + readOnly: false + books-import: + type: emptyDir + advancedMounts: + main: + main: + - path: /bookdrop + readOnly: false + data: + existingClaim: grimmory-books-nfs-storage + advancedMounts: + main: + main: + - path: /data + readOnly: false + ingest: + existingClaim: grimmory-books-import-nfs-storage + advancedMounts: + main: + main: + - path: /bookdrop/ingest + readOnly: false +mariadb-cluster: + mariadb: + rootPasswordSecretKeyRef: + generate: false + name: grimmory-database-secret + key: password + storage: + size: 5Gi + replicas: 3 + galera: + enabled: true + bootstrapFrom: + s3: + bucket: mariadb-backups-b230a2f5aecf080a4b372c08 + prefix: cl01tl/booklore + endpoint: nyc3.digitaloceanspaces.com + region: us-east-1 + accessKeyIdSecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-external + key: access + secretAccessKeySecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-external + key: secret + tls: + enabled: true + backupContentType: Physical + databases: + - name: booklore + characterSet: utf8 + collate: utf8_general_ci + cleanupPolicy: Delete + requeueInterval: 10h + users: + - name: grimmory + passwordSecretKeyRef: + name: grimmory-database-secret + key: password + host: '%' + cleanupPolicy: Delete + requeueInterval: 10h + retryInterval: 30s + grants: + - name: grimmory + privileges: + - "ALL PRIVILEGES" + database: "booklore" + table: "*" + username: grimmory + grantOption: true + host: '%' + cleanupPolicy: Delete + requeueInterval: 10h + retryInterval: 30s + physicalBackups: + - name: backup-external + schedule: + cron: "0 0 * * 0" + suspend: false + immediate: true + compression: gzip + maxRetention: 2160h + successfulJobsHistoryLimit: 1 + storage: + s3: + bucket: mariadb-backups-b230a2f5aecf080a4b372c08 + prefix: cl01tl/grimmory + endpoint: nyc3.digitaloceanspaces.com + region: us-east-1 + accessKeyIdSecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-external + key: access + secretAccessKeySecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-external + key: secret + tls: + enabled: true + - name: backup-remote + schedule: + cron: "0 0 * * 0" + suspend: false + immediate: true + compression: gzip + maxRetention: 2160h + successfulJobsHistoryLimit: 1 + storage: + s3: + bucket: mariadb-backups + prefix: cl01tl/grimmory + endpoint: garage-ps10rp.boreal-beaufort.ts.net:3900 + region: us-east-1 + accessKeyIdSecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-garage + key: access + secretAccessKeySecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-garage + key: secret + tls: + enabled: true + - name: backup-garage + schedule: + cron: "0 0 * * *" + suspend: false + immediate: true + compression: gzip + maxRetention: 360h + successfulJobsHistoryLimit: 1 + storage: + s3: + bucket: mariadb-backups + prefix: cl01tl/grimmory + endpoint: garage-main.garage:3900 + region: us-east-1 + accessKeyIdSecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-garage + key: access + secretAccessKeySecretKeyRef: + name: grimmory-mariadb-cluster-backup-secret-garage + key: secret +volsync-target-config: + pvcTarget: grimmory-config + moverSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: OnRootMismatch + local: + enabled: true + schedule: 12 8 * * * + remote: + enabled: true + schedule: 12 9 * * * + external: + enabled: true + schedule: 12 10 * * * diff --git a/clusters/cl01tl/helm/homepage/values.yaml b/clusters/cl01tl/helm/homepage/values.yaml index 46cf4d48a..2bf9cd2ea 100644 --- a/clusters/cl01tl/helm/homepage/values.yaml +++ b/clusters/cl01tl/helm/homepage/values.yaml @@ -211,8 +211,8 @@ homepage: - Books: icon: sh-booklore.webp description: Grimmory - href: https://booklore.alexlebens.net - siteMonitor: http://booklore.booklore:80 + href: https://grimmory.alexlebens.net + siteMonitor: http://grimmory.grimmory:80 statusStyle: dot - Public: - Site: diff --git a/hosts/ps08rp/blocky/config.yml b/hosts/ps08rp/blocky/config.yml index e65db852e..686dc38d6 100644 --- a/hosts/ps08rp/blocky/config.yml +++ b/hosts/ps08rp/blocky/config.yml @@ -98,6 +98,7 @@ customDNS: gatus IN CNAME traefik-cl01tl gitea IN CNAME traefik-cl01tl grafana IN CNAME traefik-cl01tl + grimmory IN CNAME traefik-cl01tl harbor IN CNAME traefik-cl01tl headlamp IN CNAME traefik-cl01tl home IN CNAME traefik-cl01tl diff --git a/hosts/ps09rp/blocky/config.yml b/hosts/ps09rp/blocky/config.yml index b9e854262..2284e4491 100644 --- a/hosts/ps09rp/blocky/config.yml +++ b/hosts/ps09rp/blocky/config.yml @@ -119,6 +119,7 @@ customDNS: gatus IN CNAME traefik-cl01tl gitea IN CNAME traefik-cl01tl grafana IN CNAME traefik-cl01tl + grimmory IN CNAME traefik-cl01tl harbor IN CNAME traefik-cl01tl headlamp IN CNAME traefik-cl01tl home IN CNAME traefik-cl01tl