Kubernetes Installation¶
Deploy Depictio on a Kubernetes cluster using the official Helm chart.
Prerequisites: Kubernetes 1.19+, Helm 3.2.0+, a PV provisioner (if persistence is enabled).
Quick Start¶
Step 1 — Clone and install¶
git clone https://github.com/depictio/depictio.git
cd depictio
helm install depictio helm-charts/depictio \
-f helm-charts/depictio/values.yaml \
-n depictio --create-namespace
Step 2 — Wait for pods¶
All pods should reach Running status: backend, viewer, mongo, minio, redis, celery-worker. The minio pod runs the S3 store, SeaweedFS since v1.12.0; it keeps its name so that an upgrade reuses the same volume.
Upgrading a release from before v1.12.0?
The bundled store starts empty after the upgrade: export the bucket before
running helm upgrade. See
Upgrading to v1.12.0: MinIO → SeaweedFS.
Step 3 — Access Depictio¶
By default services are ClusterIP. Use port-forwarding to access locally:
Then open http://localhost:5080.
| Service | Port |
|---|---|
| Frontend (React viewer) | 5080 |
| Backend API | 8058 |
| S3 API (SeaweedFS) | 9000 |
The SeaweedFS admin UI is off by default. s3.adminUI.enabled: true serves it on
s3.service.adminPort (23646), behind the S3 root credentials.
Advanced Configuration¶
Custom values file¶
Create a my-values.yaml to override defaults and pass it at install time:
helm install depictio helm-charts/depictio \
-f helm-charts/depictio/values.yaml \
-f my-values.yaml \
-n depictio --create-namespace
To see all configurable parameters:
Real-world example (EMBL)¶
The repository includes the EMBL demo deployment values files as a reference. They demonstrate the layered approach: a shared base file overlaid by environment-specific files.
| File | Purpose |
|---|---|
values-embl-demo-base.yaml |
Shared settings (storage, resources, auth, S3) |
values-embl-demo.yaml |
Demo overlay (ingress, image tags, replicas) |
values-embl-demo-dev.yaml |
Dev overlay (debug flags, reduced resources) |
values-embl-auth.yaml |
Multi-user auth + Google OAuth |
Usage pattern:
helm install depictio helm-charts/depictio \
-f helm-charts/depictio/values.yaml \
-f helm-charts/depictio/values-embl-demo-base.yaml \
-f helm-charts/depictio/values-embl-demo.yaml \
-n depictio --create-namespace
Secrets file
values-embl-secrets.yaml is gitignored — it holds the S3 passwords and OAuth
secrets that must be created locally. See values-embl-auth.yaml for the
expected key names.
Single-user vs Multi-user mode¶
# my-values.yaml
backend:
env:
DEPICTIO_AUTH_SINGLE_USER_MODE: "true" # default — no login required
# DEPICTIO_AUTH_PUBLIC_MODE: "true" # public read-only with sign-in
S3 credentials¶
These keys were secrets.minioRootUser and secrets.minioRootPassword before
v1.12.0. The old keys, and a minio: values block, still work and print a
deprecation warning in the upgrade notes. See
Renamed settings.
Upgrading from pre-v1.0.0-b1 — rotate the S3 credentials
From v1.0.0-b1 onwards the S3 root credentials are stored exclusively
in a Kubernetes Secret. Earlier releases stored them in the ConfigMap,
which was readable via kubectl describe and stored in etcd as plain text.
If you are upgrading from an older release, rotate your S3 root credentials after the upgrade:
- Update
secrets.s3RootUserandsecrets.s3RootPasswordin your values file (or a sealed secret / external-secrets source). - Run
helm upgradeto apply the new Secret. - Restart the store's pod so it picks up the new credentials:
kubectl rollout restart deployment/depictio-minio -n depictio
External S3¶
# my-values.yaml
s3:
enabled: false # no bundled store (minio.enabled before v1.12.0)
backend:
env:
DEPICTIO_S3_PUBLIC_URL: "https://your-s3-host.example.com"
DEPICTIO_S3_EXTERNAL_SERVICE: "true"
DEPICTIO_S3_ROOT_USER: "your-access-key"
DEPICTIO_S3_ROOT_PASSWORD: "your-secret-key"
An external S3 is not affected by the move from MinIO to SeaweedFS, and the
DEPICTIO_MINIO_* names of earlier values files still work.
The bucket does not have to exist
From v1.6.0 the backend creates DEPICTIO_S3_BUCKET at startup when it is
missing, then verifies it; an existing bucket is left untouched. See
Required S3 permissions.
Ingress¶
Depictio's Helm chart supports three ingress topologies. Pick based on how your cluster's auth and TLS termination work.
| Topology | Toggle | When to use |
|---|---|---|
| Single ingress (default) | ingress.enabled: true only |
Viewer, backend API, and S3 store all share one ingress + annotation set. Right for small/dev clusters or when one OIDC layer covers everything. |
| Viewer + dedicated backend | backend.ingress.separateRoute: true |
Apply different auth annotations (or no auth) on the API. Useful when the API needs a different OIDC scope, or when programmatic clients hit /depictio/api/* with mTLS or API tokens. |
| Viewer + dedicated S3 | s3.ingress.separateRoute: true |
Same idea for the S3 store — typically when it is exposed for direct S3 access from CI runners and shouldn't sit behind the user-facing OIDC. |
You can combine the toggles to get all three ingresses separate.
Per-route annotations¶
Each ingress has its own annotations block, applied in isolation:
# my-values.yaml
ingress:
enabled: true
host: depictio.yourdomain.com
tls:
enabled: true
secretName: depictio-tls
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
# OIDC annotations applied to the viewer ingress only
backend:
ingress:
separateRoute: true
inheritDefaultAnnotations: false # don't copy ingress.annotations
annotations:
nginx.ingress.kubernetes.io/auth-method: "BASIC" # different auth
nginx.ingress.kubernetes.io/proxy-body-size: "200m"
s3:
ingress:
separateRoute: true
inheritDefaultAnnotations: false
annotations: {} # no auth — restrict at network policy
inheritDefaultAnnotations controls whether ingress.annotations are
merged into the per-route ingress. Set false when the per-route ingress
needs a fundamentally different auth chain.
Network restrictions on dedicated routes
A dedicated S3 or backend ingress with annotations: {} is
unauthenticated at the ingress layer. Restrict access via Kubernetes
NetworkPolicies, ingress controller IP whitelisting, or a dedicated
private DNS — don't rely on obscurity.
Gateway API instead of Ingress (v1.1.4+)¶
On clusters that have moved to the Gateway API,
gateway.enabled: true emits HTTPRoute resources instead of Ingress objects:
one for the viewer, one for the API, one for the S3 store. parentRefs is the only
required key; per-route filters live under backend.httpRoute and
s3.httpRoute, and gateway.filters applies to the viewer route alone.
# my-values.yaml
ingress:
enabled: false
gateway:
enabled: true
parentRefs:
- name: nginx-gateway
namespace: nginx-gateway
Gateway API has no equivalent of the nginx.ingress.kubernetes.io/*
annotations, so raw nginx config goes through gateway.snippetsFilter. Setting
enabled: true with a list of snippets emits a SnippetsFilter and wires it
into the viewer route. Both keys are ignored while gateway.enabled is false.
Init container image pull policy¶
All init containers must use pullPolicy: Always. Capsule and Pod Security
Admission (PSA) webhooks on restricted namespaces reject pods whose init
containers use IfNotPresent, which can leave the release stuck in Pending.
# my-values.yaml
initContainerImage:
pullPolicy: Always # required on clusters with Capsule/PSA admission webhooks
curlInitContainerImage:
pullPolicy: Always # same requirement for the curl-based readiness init container
These keys map directly to the initContainerImage.pullPolicy and
curlInitContainerImage.pullPolicy fields in values.yaml.
Service link environment variables¶
Kubernetes injects a block of legacy Docker-link environment variables
(<SVC>_SERVICE_HOST, <SVC>_PORT_<port>_TCP_ADDR, and several more) into every
pod, once per service in the namespace. On a busy namespace that set grows large
enough to overflow the process argument limit, and the viewer crashloops with
envsubst: Argument list too long before nginx ever starts.
Since v1.4.0 the chart sets enableServiceLinks: false on every pod it owns,
which is the opposite of Kubernetes' own default
(#946):
Depictio's own services address each other by DNS name, so nothing in the
application reads those variables. Set it back to true only if something else in
your deployment does.
What stays injected
KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT are injected by the
kubelet regardless of this setting, so in-cluster API clients are unaffected.
Pods created by the Percona MongoDB operator are also untouched, since the
operator owns those pod specs.
Celery workers (background callbacks)¶
The Celery worker is included and enabled by default (celery.enabled: true).
Design mode always requires Celery. View mode behaviour is controlled separately:
# my-values.yaml
celery:
replicas: 1
env:
DEPICTIO_CELERY_WORKERS: "4"
DEPICTIO_CELERY_ENABLED: "true" # async view mode (recommended for production)
No ingestion worker in the chart (v1.15.0)
The chart's worker reads only the default celery queue, and the chart has no
ingestion worker to read the ingestion queue. Leave
DEPICTIO_INGESTION_ASYNC_DELTATABLE_UPSERT and DEPICTIO_INGESTION_BROWSER_TRIGGER
off on Kubernetes: with either on, the jobs they create are never picked up.
Resource limits¶
# my-values.yaml
backend:
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "4Gi"
cpu: "2"
viewer:
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "1"
Google Analytics¶
# my-values.yaml — or use the bundled example
helm upgrade depictio helm-charts/depictio \
-f helm-charts/depictio/values.yaml \
-f helm-charts/depictio/examples/values-google-analytics.yaml
Managing Releases¶
| Action | Command |
|---|---|
| Upgrade | helm upgrade depictio helm-charts/depictio -f values.yaml -n depictio |
| Rollback | helm rollback depictio -n depictio |
| Uninstall | helm uninstall depictio -n depictio |
| Show history | helm history depictio -n depictio |
Troubleshooting¶
# Check pod status
kubectl get pods -n depictio
# Inspect logs
kubectl logs -n depictio deployment/depictio-backend
kubectl logs -n depictio deployment/depictio-viewer
# Describe a failing pod
kubectl describe pod -n depictio <pod-name>
Common causes: insufficient storage class, PVC pending, image pull errors.