Helm chart now ingress controller agnostic
Starting with Helm chart version 4.0.0, Eclipse Ditto’s Kubernetes deployment is no longer tied to a specific ingress controller. The chart now provides clean, standard Kubernetes Ingress resources that work with any ingress controller — whether you use ingress-nginx, Traefik, HAProxy, Kong, or any other implementation.
What changed
Previously, the Ditto Helm chart bundled an entire ingress-nginx controller deployment (854 lines of RBAC,
Deployments, Services, admission webhooks, and IngressClass) and hardcoded nginx.ingress.kubernetes.io/* annotations
across all Ingress resource templates. This forced users to use ingress-nginx and prevented adoption of other ingress
controllers.
In version 4.0.0, we made the following changes:
- Removed the bundled ingress-nginx controller deployment — users bring their own ingress controller
- Removed all nginx-specific annotations from Ingress resources — annotations are now empty by default
- Simplified path types to standard
PrefixandExact— no more controller-specific regex paths - Added per-group
enabledflags — each route group (api, ws, ui, devops) can be independently toggled - Replaced the
backendSuffixpattern with explicitservice.namereferences
Breaking changes
This is a major version bump (3.x → 4.0.0) with breaking changes to values.yaml:
ingress.controller.*— entire block removed (no longer deploying a controller)ingress.annotations— global nginx-specific annotations removedingress.api.kubernetesAuthAnnotations— removedingress.className— default changed from"nginx"to""(empty)ingress.host— default changed from"localhost"to""(catch-all)backendSuffix— replaced byservice.namein each path entry- All per-group nginx-specific annotation blocks — removed
New values.yaml structure
The ingress section is now clean and controller-agnostic:
ingress:
enabled: false
className: "" # Set to your controller's IngressClass
host: "" # Optional hostname — if empty, no host rule (catch-all)
tls: []
api:
enabled: true
annotations: {} # Add your controller-specific annotations here
paths:
- path: /api
pathType: Prefix
service:
name: gateway
- path: /stats
pathType: Prefix
service:
name: gateway
- path: /overall
pathType: Prefix
service:
name: gateway
ws:
enabled: true
annotations: {}
paths:
- path: /ws
pathType: Prefix
service:
name: gateway
ui:
enabled: true
annotations: {}
# defaultBackend serves as the catch-all for unmatched paths (e.g. the landing page)
defaultBackend:
service:
name: nginx
paths:
- path: /
pathType: Exact
service:
name: nginx
- path: /apidoc
pathType: Prefix
service:
name: swaggerui
- path: /ui
pathType: Prefix
service:
name: dittoui
devops:
enabled: true
annotations: {}
paths:
- path: /devops
pathType: Prefix
service:
name: gateway
- path: /health
pathType: Prefix
service:
name: gateway
- path: /status
pathType: Prefix
service:
name: gateway
- path: /api/2/connections
pathType: Prefix
service:
name: gateway
Deployment modes
The chart supports three deployment modes:
Standalone nginx pod (default, unchanged)
The standalone nginx reverse proxy remains the default for local and development setups. No ingress controller needed — access Ditto via port-forward:
helm install ditto ditto/ditto
kubectl port-forward svc/ditto-nginx 8080:8080
Ingress with nginx pod
Use Ingress resources for external access while keeping the nginx pod for the landing page and static resources:
helm install ditto ditto/ditto \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.host=ditto.example.com
Ingress only (no nginx pod)
For production setups where the landing page is not needed, disable the nginx pod and the UI ingress’s root path:
helm install ditto ditto/ditto \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.host=ditto.example.com \
--set nginx.enabled=false
Controller-specific configuration
Since controller-specific behavior (authentication, CORS, timeouts, URL rewriting) is now the user’s responsibility, here are examples for common ingress controllers.
ingress-nginx
For the Ditto UI and Swagger API docs, ingress-nginx requires regex paths and a rewrite annotation to strip the path prefix before forwarding to the backend.
Note that when use-regex is enabled, the root path / must be specified as /$ with pathType: ImplementationSpecific
to ensure it matches only the exact root path and does not conflict with the ingress controller’s default catch-all:
ingress:
enabled: true
className: nginx
host: ditto.example.com
api:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "70"
nginx.ingress.kubernetes.io/proxy-send-timeout: "70"
ws:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
ui:
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
paths:
- path: /$
pathType: ImplementationSpecific
service:
name: nginx
- path: /apidoc(/|$)(.*)
pathType: ImplementationSpecific
service:
name: swaggerui
- path: /ui(/|$)(.*)
pathType: ImplementationSpecific
service:
name: dittoui
Traefik
Traefik requires a Middleware CRD to strip path prefixes. First, create the middleware in the Ditto namespace:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: strip-prefix
namespace: ditto
spec:
stripPrefix:
prefixes:
- /ui
- /apidoc
Then reference it in the ingress configuration:
ingress:
enabled: true
className: traefik
host: ditto.example.com
ui:
annotations:
traefik.ingress.kubernetes.io/router.middlewares: ditto-strip-prefix@kubernetescrd
HAProxy
ingress:
enabled: true
className: haproxy
host: ditto.example.com
ui:
annotations:
haproxy.org/path-rewrite: "/ /"
What stays the same
- The standalone nginx pod for local/development deployments is unchanged
- The OpenShift Route template is unchanged
- All Ditto service templates (gateway, things, policies, connectivity, etc.) are unchanged
- The 4 route groups (api, ws, ui, devops) cover all Ditto endpoints — the root landing page is now part of the ui group
Migrating from 3.x
- Install your ingress controller separately (e.g., via its own Helm chart)
- Update your values.yaml to match the new structure — replace
backendSuffixwithservice.name, removeingress.controller.*and global annotations - Add controller-specific annotations to the appropriate route groups
- Upgrade the chart to version 4.0.0
–
The Eclipse Ditto team