* Adds StatefulSet support # Conflicts: # helm/opengist/templates/pvc.yaml * Adds statefulset support for replicaCount gt 1 * Improves the setup of multiple replicas in a stateful set * Adds config wrangling logic to the secret template * Adds shared PV functionality * Adds missing pvc-shared template * Adds stateful set and documentation --------- Co-authored-by: Guillem Riera <guillem@rieragalm.es>
Opengist Helm Chart
Opengist Helm chart for Kubernetes.
Install
helm repo add opengist https://helm.opengist.io
helm install opengist opengist/opengist
Configuration
This part explains how to configure the Opengist instance using the Helm chart. The config.yml file used by Opengist
is mounted from a Kubernetes Secret with a key config.yml and the values formatted as YAML.
Using values
Using Helm values, you can define the values from a key name config
config:
log-level: "warn"
log-output: "stdout"
This will create a Kubernetes secret named opengist mounted to the pod as a file with the YAML content of the secret,
used by Opengist.
Using an existing secret
If you wish to not store sensitive data in your Helm values, you can create a Kubernetes secret with a key config.yml
and values formatted as YAML. You can then reference this secret in the Helm chart with the configExistingSecret key.
If defined, this existing secret will be used instead of creating a new one.
configExistingSecret: <name of the secret>
Dependencies
Meilisearch Indexer
By default, Opengist uses the bleve indexer. It is NOT available if there is multiple replicas of the opengist pod (only one pod can open the index at the same time).
Instead, for multiple replicas setups, you MUST use the meilisearch indexer.
By setting meilisearch.enabled: true, the Meilisearch chart will be deployed aswell.
You must define the meilisearch.host (Kubernetes Service) and meilisearch.key (value created by Meilisearch) values to connect to the Meilisearch instance in your Opengist config :
index: meilisearch
index.meili.host: http://opengist-meilisearch:7700 # pointing to the K8S Service
index.meili.api-key: MASTER_KEY # generated by Meilisearch
If you want to use the bleve indexer, you need to set the replicas to 1.
Passing Meilisearch configuration via nested Helm values
When using the Helm CLI with --set, avoid mixing a scalar config.index value with nested config.index.meili.* keys. Instead use a nested map and a type field which the chart flattens automatically. Example:
helm template opengist ./helm/opengist \
--set statefulSet.enabled=true \
--set replicaCount=2 \
--set persistence.enabled=true \
--set persistence.existingClaim=opengist-shared-rwx \
--set postgresql.enabled=false \
--set config.db-uri="postgres://user:pass@db-host:5432/opengist" \
--set meilisearch.enabled=true \
--set config.index.type=meilisearch \
--set config.index.meili.host="http://opengist-meilisearch:7700" \
--set config.index.meili.api-key="MASTER_KEY"
Rendered config.yml fragment:
index: meilisearch
index.meili.host: http://opengist-meilisearch:7700
index.meili.api-key: MASTER_KEY
How it works:
- You provide a map under
config.indexwith keystypeandmeili. - The template detects
config.index.typeand rewritesindex: <type>. - Nested
config.index.meili.host/api-keyare lifted to flat keysindex.meili.hostandindex.meili.api-keyrequired by Opengist.
If you set --set config.index=meilisearch directly and also try to set --set config.index.meili.host=..., Helm will first create the nested structure then overwrite it with the scalar, losing the host. Always prefer the config.index.type pattern for CLI usage.
PostgreSQL Database
By default, Opengist uses the sqlite database. If needed, this chart also deploys a PostgreSQL instance.
By setting postgresql.enabled: true, the Bitnami PostgreSQL chart will be deployed aswell.
You must define the postgresql.host, postgresql.port, postgresql.database, postgresql.username and postgresql.password values to connect to the PostgreSQL instance.
Then define the connection string in your Opengist config:
db-uri: postgres://user:password@opengist-postgresql:5432/opengist
Note: opengist-postgresql is the name of the K8S Service deployed by this chart.
Database Configuration
You can supply an externally managed database connection explicitly via config.db-uri (PostgreSQL/MySQL) or enable the bundled PostgreSQL subchart.
Behavior:
- If
postgresql.enabled: trueandconfig.db-uriis omitted, the chart auto-generates:postgres://<username>:<password>@<release-name>-postgresql:<port>/<database>using values underpostgresql.global.postgresql.auth.*. - If any of username/password/database are missing, templating fails fast with an error message.
- If you prefer an external database or a different Postgres distribution, set
postgresql.enabled: falseand provideconfig.db-uriyourself.
Licensing note: Bitnami's PostgreSQL distribution may have licensing constraints. For strictly open alternatives use an external managed PostgreSQL/MySQL service and disable the subchart.
Multi-Replica Requirements
Running more than one Opengist replica (Deployment or StatefulSet) requires:
- Non-SQLite database (
config.db-urimust start withpostgres://ormysql://). - Shared RWX storage if using StatefulSet with
replicaCount > 1(providepersistence.existingClaim). The chart now fails fast if you attemptreplicaCount > 1without an explicit shared claim to prevent silent data divergence across per‑pod PVCs.
The chart will fail fast during templating if these conditions are not met when scaling above 1 replica.
Examples:
- External PostgreSQL:
postgresql:
enabled: false
config:
db-uri: postgres://user:pass@db-host:5432/opengist
index: meilisearch
statefulSet:
enabled: true
replicaCount: 2
persistence:
existingClaim: opengist-shared-rwx
Bundled PostgreSQL (auto db-uri):
postgresql:
enabled: true
config:
index: meilisearch
statefulSet:
enabled: true
replicaCount: 2
persistence:
existingClaim: opengist-shared-rwx
Recovering from an initial misconfiguration
If you previously scaled a StatefulSet above 1 replica without an existingClaim, each pod received its own PVC and only one held the authoritative /opengist data. To consolidate:
- Scale down to 1 replica (keep the pod with the desired data):
kubectl scale sts/opengist --replicas=1
- (Optional) Inspect other PVCs and manually copy any missing files by temporarily attaching them to a debug pod.
- Create or provision a ReadWriteMany (NFS / CephFS / Longhorn RWX / etc.) PersistentVolumeClaim named (for example)
opengist-shared-rwx. - Update values with
persistence.existingClaim: opengist-shared-rwxand re‑deploy. - Scale back up:
kubectl scale sts/opengist --replicas=2
Going forward, all replicas mount the same shared volume and data remains consistent.
Quick Start Examples
Common deployment scenarios with copy-paste configurations:
Scenario 1: Single replica with SQLite (default)
Minimal local development setup with ephemeral or persistent storage:
# Ephemeral (emptyDir)
statefulSet:
enabled: true
replicaCount: 1
persistence:
enabled: false
# OR with persistent RWO storage
statefulSet:
enabled: true
replicaCount: 1
persistence:
enabled: true
mode: perReplica # default
Scenario 2: Multi-replica with external PostgreSQL + existing RWX PVC
Production HA setup with your own database and storage:
statefulSet:
enabled: true
replicaCount: 2
postgresql:
enabled: false
config:
db-uri: "postgres://user:pass@db-host:5432/opengist"
index: meilisearch # required for multi-replica
persistence:
enabled: true
mode: shared
existingClaim: "opengist-shared-rwx" # pre-created RWX PVC
meilisearch:
enabled: true
Scenario 3: Multi-replica with bundled PostgreSQL + auto-created RWX PVC
Chart manages both database and storage:
statefulSet:
enabled: true
replicaCount: 2
postgresql:
enabled: true
global:
postgresql:
auth:
username: opengist
password: changeme
database: opengist
config:
index: meilisearch
persistence:
enabled: true
mode: shared
existingClaim: "" # empty to trigger auto-creation
create:
enabled: true
accessModes: [ReadWriteMany]
storageClass: "nfs-client" # your RWX-capable storage class
size: 20Gi
meilisearch:
enabled: true
Persistence Modes
The chart supports two persistence strategies controlled by persistence.mode:
| Mode | Behavior | Scaling | Storage Objects | Recommended Use |
|---|---|---|---|---|
perReplica (default) |
One PVC per pod via StatefulSet volumeClaimTemplates (RWO) when no existingClaim |
Safe only at replicaCount=1 unless you supply existingClaim |
One PVC per replica | Local dev, quick single-node trials |
shared |
Single RWX PVC (existing or auto-created) mounted by all pods | Horizontally scalable | One shared PVC | Production / HA |
Configuration examples:
Per-replica (single node):
statefulSet:
enabled: true
persistence:
mode: perReplica
enabled: true
accessModes:
- ReadWriteOnce
Shared (scale ready) with an existing RWX claim:
statefulSet:
enabled: true
replicaCount: 2
persistence:
mode: shared
existingClaim: opengist-shared-rwx
Shared with chart-created RWX PVC:
statefulSet:
enabled: true
replicaCount: 2
persistence:
mode: shared
existingClaim: "" # leave empty
create:
enabled: true
accessModes: [ReadWriteMany]
size: 10Gi
When mode=shared and existingClaim is empty, the chart creates a single PVC named <release>-shared (suffix configurable via persistence.create.nameSuffix).
Fail-fast conditions:
replicaCount>1& missing external DB (still enforced).replicaCount>1& persistence disabled.replicaCount>1& neitherexistingClaimnormode=shared.mode=shared& create.enabled=true butaccessModeslacksReadWriteMany.
Migration (perReplica → shared): scale down to 1, create RWX claim (or rely on create.enabled), copy data, switch mode to shared, scale up.
Troubleshooting
Common Errors and Solutions
Error: "replicaCount=2 requires PostgreSQL/MySQL config.db-uri; scheme 'sqlite' unsupported"
- Cause: Multi-replica with SQLite database
- Solution: Either scale down to
replicaCount: 1or configure external database:
config:
db-uri: "postgres://user:pass@host:5432/opengist"
Error: "replicaCount=2 requires either persistence.existingClaim OR persistence.mode=shared"
- Cause: Multi-replica without shared storage
- Solution: Choose one approach:
# Option A: Use existing PVC
persistence:
existingClaim: "my-rwx-pvc"
# Option B: Let chart create PVC
persistence:
mode: shared
create:
enabled: true
accessModes: [ReadWriteMany]
Error: "persistence.mode=shared create.accessModes must include ReadWriteMany for multi-replica"
- Cause: Chart-created PVC lacks RWX access mode
- Solution: Ensure RWX is specified:
persistence:
create:
accessModes:
- ReadWriteMany
Pods mount different data (data divergence)
- Cause: Previously scaled with
perReplicamode andreplicaCount > 1 - Solution: Follow recovery steps in "Recovering from an initial misconfiguration" section above
PVC creation fails: "no storage class available with ReadWriteMany"
- Cause: Cluster lacks RWX-capable storage provisioner
- Solution: Install a storage provider (NFS, CephFS, Longhorn) or use external managed storage and provide
existingClaim