-
-
Notifications
You must be signed in to change notification settings - Fork 0
Kubernetes
IRIS-NG ships a Helm chart at deploy/kubernetes/charts
(chart 0.6.0, appVersion IRIS-NG-v1.2.0).
Status. The chart tracks the current stack: published images, an AI worker deployment, and a normal cluster volume instead of a node-local one. Verified on a live single-node cluster (kind, Kubernetes 1.34) — all five pods reach
Running, the schema is created, and the app serves HTTP 200. It has not been tested on a managed multi-node cluster, where node rescheduling and a real CSI driver are the parts that differ. See Test results. Docker Compose on a single host remains the configuration this project tests continuously.
DigitalOcean Kubernetes (DOKS) is a straightforward place to run the chart, and the badge above is a referral link — it gives you free starting credit, and credits this project. Nothing in IRIS-NG depends on DigitalOcean; the chart is plain Helm and runs on any conformant cluster.
Public images are on GHCR, multi-arch (linux/amd64, linux/arm64), pullable
anonymously — no registry secret needed.
The chart does not pin an image tag. values.yaml ships tag: "" for the
iris-ng images and the templates fall back to the chart's own appVersion, so a
packaged chart always deploys the release it shipped with. Override per component
if you need to (irisapp.tag, irisworker.tag, irisaiworker.tag,
postgres.tag); rabbitmq is an upstream image on its own version and is
unaffected.
Charts attached to releases before
IRIS-NG-v1.0.1did pin, and the one attached toIRIS-NG-v1.0.0pinned the previous release's images — installing from that asset deploysv2.5.0-beta.1+iris-ng.7despite the chart being labelled v1.0.0. UseIRIS-NG-v1.0.1or later.
docker pull ghcr.io/zach115th/iriswebapp_app:IRIS-NG-v1.2.0
docker pull ghcr.io/zach115th/iriswebapp_db:IRIS-NG-v1.2.0The image tag matches the release name under the current
IRIS-NG-v<x.y.z>scheme. Releases made under the older+iris-ng.<build>scheme substitute-for+in their image tags, since+is not valid in a Docker tag.
The app image runs three roles; the entrypoint target selects which. There is no
nginx deployment — the ingress controller terminates TLS in its place.
git clone https://github.com/zach115th/iris-ng.git && cd iris-ng
# Ingress controller (once per cluster)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress ingress-nginx/ingress-nginx -n iris --create-namespace
cp deploy/kubernetes/charts/values.yaml my-values.yaml
$EDITOR my-values.yaml # see "What you must change" below
helm install iris-ng ./deploy/kubernetes/charts -n iris -f my-values.yamlPoint DNS at the ingress load balancer once it has an external IP:
kubectl get svc -n iris ingress-ingress-nginx-controllerThe chart installs with defaults, but three things are placeholders you are expected to replace.
The ingress hostname. ingress.hosts[0].host and ingress.tls[0].hosts[0] both
default to iris.example.com.
Every secret. IRIS_SECRET_KEY, IRIS_SECURITY_PASSWORD_SALT, the Postgres
passwords and IRIS_ADM_PASSWORD all ship with well-known development values, and
they appear in values.yaml in plaintext. Change them, and prefer wiring them to a
Kubernetes Secret rather than committing a filled-in values file.
Storage size. postgres.persistence.size defaults to 20 GiB.
Case data, evidence metadata and AI artifacts all live in Postgres, so the database volume is the thing that matters.
By default the chart now requests a normal ReadWriteOnce volume from the cluster
default StorageClass (do-block-storage on DOKS). Earlier chart versions hardcoded
a hostPath PersistentVolume with ReadWriteMany, which is wrong twice over on a
managed cluster: hostPath is node-local, so the database comes up silently empty
if the pod ever reschedules onto another node, and ReadWriteMany is unsupported by
most block-storage CSI drivers.
postgres:
persistence:
enabled: true
storageClass: "" # "" = cluster default
accessMode: ReadWriteOnce
size: 20Gi
hostPath:
enabled: false # true only for kind/minikube single-node clustersConfirm the claim actually bound before putting anything real on it:
kubectl get pvc -n irisBack up that volume. scripts/import_vanilla_db.sh covers migrating an existing
database in.
irisaiworker is deployed by default and consumes the dedicated ai_queue at
concurrency 1 — one model call in flight at a time.
Keep replicaCount at 1. The bound is deliberate; scaling it up multiplies concurrent
load on whatever backend is serving the model.
If you are not using the AI layer you can set irisaiworker.enabled: false. Do not
disable it while an AI backend is configured — the executive case summary and case
chat would enqueue jobs that nothing consumes, and the UI would show them queued
forever rather than reporting an error. See
AI Features → Async job queue.
The model itself runs outside the cluster in most setups; if that is a local LM Studio or Ollama, it must be reachable from the pods.
The app and worker mount four Secrets built from files under charts/certificates/
via .Files.Glob. That directory is not shipped with the chart, so this is off by
default (certificates.enabled: false) — otherwise the Secrets render empty and
mount an empty directory where the CA file should be.
Enable it only after placing rootCA/irisRootCACert.pem, rootCA/*,
web_certificates/* and ldap/* under charts/certificates/. This is for the
application's own trust store and LDAP; for ingress TLS use
cert-manager with a ClusterIssuer plus ingress.tls.
postgres.POSTGRES_HOST_AUTH_METHOD now defaults to scram-sha-256. Earlier chart
versions hardcoded trust, which accepts any connection reaching the service with no
password at all. Set it back to trust only if you deliberately want an
unauthenticated database.
| Component | Requests |
|---|---|
iris_app |
1 CPU / 2 GB |
iris_worker |
0.5 CPU / 1 GB |
ai_worker |
0.5 CPU / 1 GB |
postgres |
1 CPU / 2 GB + 20 GB volume |
rabbitmq |
0.25 CPU / 512 MB |
Two 4 GB nodes is a reasonable starting point.
For evaluation, a single 4 GB Droplet running the compose stack is faster to stand up and is the configuration this project actually tests:
git clone https://github.com/zach115th/iris-ng.git && cd iris-ng
bash scripts/generate_dev_certs.sh
bash scripts/iris_helper.sh --init
docker compose -f docker-compose.dev.yml up -d --buildFull walkthrough in Getting Started.
Verified on kind, Kubernetes 1.34, single node, installing with the shipped defaults and no overrides:
| Check | Result |
|---|---|
helm install with defaults |
succeeds, no overrides needed |
| Pods | 5/5 Running — app, worker, ai-worker, postgres, rabbitmq |
| PVC |
Bound, 20Gi, RWO, cluster default StorageClass |
| Schema | 95 tables, Alembic at head, migrations ran |
| App |
HTTP 200 on /login, locally and cross-pod via Service DNS |
| AI worker | bound to ai_queue, concurrency: 1, reports ready |
| Postgres auth |
pg_hba shows scram-sha-256 and the app connects |
irisaiworker.enabled=false |
AI worker cleanly removed, rest unaffected |
That last Postgres row is the meaningful one: password auth is enforced and the application authenticates, which could not happen while the env var was misspelled.
Not covered: any managed multi-node cluster. Node rescheduling, a real CSI driver, ingress-nginx with a cloud load balancer and cert-manager are exactly the parts a single-node test cannot exercise.
- Only single-node tested — see Test results.
- Secrets are plaintext values, not Kubernetes Secrets.
-
No HorizontalPodAutoscaler, PodDisruptionBudget, NetworkPolicy or resource
defaults —
resources: {}means pods are BestEffort until you set them. -
Postgres is a Deployment, not a StatefulSet, with
replicaCountexposed; running more than one replica against one RWO volume will not work.
Reports from a real install are welcome — see CONTRIBUTING.md.