diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a1a063f76..bd3630fdf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1276,6 +1276,10 @@ jobs: --set httpRoute.enabled=true \ --set 'httpRoute.parentRefs[0].name=gateway' \ > "$out/http-route.yaml" + helm template trek charts/trek \ + --set 'persistence.data.accessModes[0]=ReadWriteMany' \ + --set 'persistence.uploads.accessModes[0]=ReadWriteMany' \ + > "$out/access-modes.yaml" helm template trek charts/trek \ --set podSecurityContext.runAsUser=1000 \ --set podSecurityContext.runAsGroup=1000 \ diff --git a/charts/README.md b/charts/README.md index 2d7e8dc3e..62060538b 100644 --- a/charts/README.md +++ b/charts/README.md @@ -43,7 +43,8 @@ See `values.yaml` for more options. ## Notes - Ingress is off by default. Enable and configure hosts for your domain. - PVCs use the cluster's default StorageClass. Set `persistence.data.storageClassName` and/or `persistence.uploads.storageClassName` to bind a specific class. -- To use your own PVCs, set `persistence.data.existingClaim` and/or `persistence.uploads.existingClaim`. The other values for that volume (size, storageClassName, annotations) are then ignored. +- Both PVCs are `ReadWriteOnce`. Set `persistence.data.accessModes` and/or `persistence.uploads.accessModes` to override, for example `[ReadWriteMany]` so a backup pod can mount the volume. On the data volume such a pod may only read: SQLite corrupts `travel.db` when a second process writes it over a network filesystem. +- To use your own PVCs, set `persistence.data.existingClaim` and/or `persistence.uploads.existingClaim`. The other values for that volume (size, storageClassName, accessModes, annotations) are then ignored. - With `persistence.enabled: false`, the data and uploads volumes use an `emptyDir` — storage is ephemeral and lost on pod restart. Intended for testing only. - `JWT_SECRET` is managed entirely by the server — auto-generated into the data PVC on first start and rotatable via the admin panel (Settings → Danger Zone). No Helm configuration needed. - `ENCRYPTION_KEY` encrypts stored secrets (API keys, MFA, SMTP, OIDC) at rest. Recommended: set via `secretEnv.ENCRYPTION_KEY` or `existingSecret`. If left empty, the server falls back automatically: existing installs use `data/.jwt_secret` (no action needed on upgrade); fresh installs auto-generate a key persisted to the data PVC. diff --git a/charts/trek/templates/pvc.yaml b/charts/trek/templates/pvc.yaml index 5e6872dea..149175081 100644 --- a/charts/trek/templates/pvc.yaml +++ b/charts/trek/templates/pvc.yaml @@ -11,7 +11,7 @@ metadata: {{- end }} spec: accessModes: - - ReadWriteOnce + {{- toYaml (.Values.persistence.data.accessModes | default (list "ReadWriteOnce")) | nindent 4 }} {{- with .Values.persistence.data.storageClassName }} storageClassName: {{ . | quote }} {{- end }} @@ -33,7 +33,7 @@ metadata: {{- end }} spec: accessModes: - - ReadWriteOnce + {{- toYaml (.Values.persistence.uploads.accessModes | default (list "ReadWriteOnce")) | nindent 4 }} {{- with .Values.persistence.uploads.storageClassName }} storageClassName: {{ . | quote }} {{- end }} diff --git a/charts/trek/values.yaml b/charts/trek/values.yaml index c2a4a4c53..648058884 100644 --- a/charts/trek/values.yaml +++ b/charts/trek/values.yaml @@ -247,12 +247,21 @@ persistence: size: 1Gi # Leave empty to use the cluster's default StorageClass; set to bind a specific class. storageClassName: "" - # Bind an existing PVC. The other values (size, storageClassName, annotations) are then ignored. + # Access modes of the claim. ReadWriteMany lets another pod mount the volume, for + # example a backup sidecar, but only for reading: SQLite needs every writer on one + # host, so two pods writing travel.db over a network filesystem corrupt it. + accessModes: + - ReadWriteOnce + # Bind an existing PVC. The other values (size, storageClassName, accessModes, + # annotations) are then ignored. existingClaim: "" annotations: {} uploads: size: 1Gi storageClassName: "" + # Access modes of the claim; ReadWriteMany lets other pods read or add uploads. + accessModes: + - ReadWriteOnce # Specify an existing PVC to bind. The other values are then ignored. existingClaim: "" annotations: {} diff --git a/wiki/Install-Helm.md b/wiki/Install-Helm.md index a8fa64102..b51846b9b 100644 --- a/wiki/Install-Helm.md +++ b/wiki/Install-Helm.md @@ -190,6 +190,17 @@ persistence: size: 1Gi # uploaded files — increase if you expect large media uploads ``` +Both claims are `ReadWriteOnce` by default. Set `persistence.data.accessModes` or `persistence.uploads.accessModes` to change that, for example so a backup container in another pod can mount the volume: + +```yaml +persistence: + data: + accessModes: + - ReadWriteMany +``` + +> **Warning:** A `ReadWriteMany` data volume is only safe for pods that read it. SQLite needs every process that writes `travel.db` on the same host, so a second writer over a network filesystem corrupts the database. Keep `updateStrategy: Recreate` either way. + ### Security Context ```yaml