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.
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 |
| MinIO Console | 9001 |
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, MinIO) |
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 MinIO 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
MinIO credentials¶
Upgrading from pre-v1.0.0-b1 — rotate MinIO credentials
From v1.0.0-b1 onwards MinIO 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 MinIO root credentials after the upgrade:
- Update
secrets.minioRootUserandsecrets.minioRootPasswordin your values file (or a sealed secret / external-secrets source). - Run
helm upgradeto apply the new Secret. - Restart the MinIO pod so it picks up the new credentials:
kubectl rollout restart deployment/depictio-minio -n depictio
External S3 / Bring Your Own MinIO¶
# my-values.yaml
minio:
enabled: false # disable bundled MinIO
backend:
env:
DEPICTIO_MINIO_PUBLIC_URL: "https://your-minio-host.example.com"
DEPICTIO_MINIO_EXTERNAL_SERVICE: "true"
DEPICTIO_MINIO_ROOT_USER: "your-access-key"
DEPICTIO_MINIO_ROOT_PASSWORD: "your-secret-key"
The bucket does not have to exist
From v1.6.0 the backend creates DEPICTIO_MINIO_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 MinIO console 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 MinIO | minio.ingress.separateRoute: true |
Same idea for MinIO — typically when MinIO 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"
minio:
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 MinIO 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 MinIO. parentRefs is the only
required key; per-route filters live under backend.httpRoute and
minio.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)
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.