Production dependencies
Moyai on-prem · 3 November 2026
Moyai's release carries Moyai only. Everything under it is the site's, and each piece runs highly available, backed up, and monitored.
- easterisland
- moyai-harbor
- CloudNativePG Postgres 17
- SeaweedFS S3
- Lakekeeper Iceberg
- Valkey cache · optional
- Traefik
- cert-manager
- Prometheus
- metrics-server
- 3+ workers
- default StorageClass
- off-site S3 for backups
| Component | Chart | Version | Production shape |
|---|---|---|---|
| CloudNativePG | cnpg/cloudnative-pg |
0.29.1 (operator 1.30.1) | 3 instances per database, WAL archived off-site |
| Backups for Postgres | cnpg/plugin-barman-cloud |
0.8.1 | daily base backup, 30-day retention |
| SeaweedFS | seaweedfs/seaweedfs |
4.52.0 | 3 masters, 3 volume servers, 2 filers on Postgres, 2 S3 gateways |
| Lakekeeper | manifests from easterisland-data |
v0.14.1 | 2 replicas, catalog on CloudNativePG |
| Valkey | valkey/valkey |
0.12.1 (Valkey 9.1.3) | primary + 2 replicas, password auth |
| Traefik | traefik/traefik |
41.5.0 | 2 replicas |
| cert-manager | jetstack/cert-manager |
v1.21.2 | ClusterIssuer, or the site's own CA |
| kube-prometheus-stack | prometheus-community/kube-prometheus-stack |
92.10.1 | scrapes every component above |
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo add seaweedfs https://seaweedfs.github.io/seaweedfs/helm
helm repo add valkey https://valkey.io/valkey-helm/
helm repo add traefik https://traefik.github.io/charts
helm repo add jetstack https://charts.jetstack.io
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
CloudNativePG
Install the operator, then the backup plugin (it needs cert-manager):
helm upgrade --install cnpg cnpg/cloudnative-pg --version 0.29.1 -n cnpg-system --create-namespace --wait
helm upgrade --install barman-cloud cnpg/plugin-barman-cloud --version 0.8.1 -n cnpg-system --wait
Every database Moyai needs (easterisland-db, lakekeeper-db, seaweedfs-filer-db) uses the same shape. Backups go to S3 outside this cluster, so a lost cluster does not take its backups with it.
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: offsite
namespace: easterisland-system
spec:
retentionPolicy: "30d"
configuration:
destinationPath: s3://moyai-backups/easterisland-db
endpointURL: https://s3.backup.example.internal
s3Credentials:
accessKeyId: {name: backup-s3, key: ACCESS_KEY_ID}
secretAccessKey: {name: backup-s3, key: ACCESS_SECRET_KEY}
wal:
compression: gzip
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: easterisland-db
namespace: easterisland-system
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.11
storage: {size: 20Gi}
walStorage: {size: 5Gi}
affinity:
enablePodAntiAffinity: true
podAntiAffinityType: required
monitoring:
enablePodMonitor: true
bootstrap:
initdb: {database: easterisland, owner: easterisland}
plugins:
- name: barman-cloud.cloudnative-pg.io
isWALArchiver: true
parameters: {barmanObjectName: offsite}
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: easterisland-db-daily
namespace: easterisland-system
spec:
schedule: "0 0 2 * * *"
cluster: {name: easterisland-db}
method: plugin
pluginConfiguration: {name: barman-cloud.cloudnative-pg.io}
required anti-affinity puts the three instances on three different nodes. Restore into a scratch cluster once before go-live; an untested backup is not a backup.
SeaweedFS
Moyai's own cluster runs a single SeaweedFS pod today. In production it is split into its roles, with filer metadata in CloudNativePG instead of a local disk:
# seaweedfs-values.yaml
master:
replicas: 3
defaultReplication: "001" # every file on two volume servers
data: {type: persistentVolumeClaim, size: 10Gi}
volume:
replicas: 3
dataDirs:
- name: data1
type: persistentVolumeClaim
size: 500Gi
maxVolumes: 0
filer:
replicas: 2
extraEnvironmentVars:
WEED_LEVELDB2_ENABLED: "false"
WEED_POSTGRES2_ENABLED: "true"
WEED_POSTGRES2_HOSTNAME: seaweedfs-filer-db-rw
WEED_POSTGRES2_PORT: "5432"
WEED_POSTGRES2_DATABASE: filer
WEED_POSTGRES2_SSLMODE: require
secretExtraEnvironmentVars:
WEED_POSTGRES2_USERNAME: {secretKeyRef: {name: seaweedfs-filer-db-app, key: username}}
WEED_POSTGRES2_PASSWORD: {secretKeyRef: {name: seaweedfs-filer-db-app, key: password}}
s3:
enabled: true
replicas: 2
enableAuth: true
existingConfigSecret: seaweedfs-s3-config
helm upgrade --install seaweedfs seaweedfs/seaweedfs --version 4.52.0 \
-n easterisland-data --create-namespace -f seaweedfs-values.yaml
seaweedfs-filer-db is a CloudNativePG cluster shaped like the one above (database filer). The Secret seaweedfs-s3-config holds the S3 identities under the key seaweedfs_s3_config: one read-write key for easterisland and Lakekeeper, nothing anonymous. Size volume.dataDirs for the trace volume you expect, times two for replication.
Valkey
Moyai's current release does not use Valkey. Install it when a release lists it (cache, queues, rate limits), in this shape:
# valkey-values.yaml
auth:
enabled: true
usersExistingSecret: valkey-users # key "default" holds the password
aclUsers:
default:
permissions: "~* &* +@all"
replica:
enabled: true
replicas: 2
minReplicasToWrite: 1
persistence: {size: 8Gi}
podDisruptionBudget: {enabled: true}
metrics:
enabled: true
serviceMonitor: {enabled: true}
helm upgrade --install valkey valkey/valkey --version 0.12.1 -n easterisland-system -f valkey-values.yaml
This chart replicates but does not fail over by itself: if the primary's node dies, writes stop until it is back. Where that matters, run Valkey with the valkey-operator chart (0.8.0) from the same repository instead.
Lakekeeper, ingress, TLS, monitoring
- Lakekeeper: take the manifests from Moyai's
easterisland-datastack, set 2 replicas, and point it at its own CloudNativePG cluster (lakekeeper-db, 3 instances). Generate a newLAKEKEEPER__PG_ENCRYPTION_KEYper site (openssl rand -base64 48) and keep it with the database backups: without it the catalog cannot be read. - Ingress and TLS: Traefik 41.5.0 with 2 replicas; cert-manager v1.21.2 with a ClusterIssuer, or certificates from the site's own CA on air-gapped sites.
- Monitoring: kube-prometheus-stack 92.10.1. CloudNativePG, SeaweedFS and Valkey all ship metrics; turn on their PodMonitor or ServiceMonitor as above.
Credential mapping
Moyai reads two Secrets, easterisland-env and moyai-harbor-env.
| Moyai setting | Comes from | Supplied by |
|---|---|---|
PLANETSCALE_DB_HOST, _NAME, _USER, _PASSWORD |
Secret easterisland-db-app |
CloudNativePG |
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY |
The read-write S3 identity in seaweedfs-s3-config |
Customer |
AWS_ENDPOINT_URL, AWS_REGION |
http://seaweedfs-s3.easterisland-data:8333, us-east-1 |
Customer |
OTEL_S3_BUCKET, OTEL_S3_TABLE_* |
Trace bucket and catalog | Customer, values confirmed by Moyai |
OPENAI_API_KEY, OPENAI_BASE_URL, ANTHROPIC_API_KEY, GEMINI_API_KEY |
The site's model endpoint | Customer |
LITELLM_LOCAL_MODEL_COST_MAP=True |
Needed without internet | Customer |
WORKOS_*, LOGFIRE_*, TAU2_* |
Sign-in, telemetry, evaluation | Moyai |
SLACK_*, POLAR_* |
Optional integrations | Moyai decides |
Go-live checklist
- Every CloudNativePG cluster shows 3 ready instances on 3 nodes, and one restore from backup has been done
- SeaweedFS: 3 masters with a leader, files replicated (
001), S3 refuses anonymous requests - Valkey, if used: primary and 2 replicas in sync, password required
- Moyai's hostnames serve a valid certificate
- Prometheus scrapes CloudNativePG, SeaweedFS, Lakekeeper and Valkey