diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml
index 9a9a0441c22..62eda1a58b0 100644
--- a/.github/workflows/helm-chart.yml
+++ b/.github/workflows/helm-chart.yml
@@ -63,9 +63,9 @@ jobs:
# which a folder exists at
# https://github.com/yannh/kubernetes-json-schema/
k8s:
- - v1.28.13
- - v1.29.8
- - v1.30.4
+ - v1.33.7
+ - v1.34.3
+ - v1.35.1
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -92,9 +92,9 @@ jobs:
# available for the docker.io/kindest/node image
# https://hub.docker.com/r/kindest/node/tags
k8s:
- - v1.28.13
- - v1.29.8
- - v1.30.4
+ - v1.33.7
+ - v1.34.3
+ - v1.35.1
steps:
- name: Checkout
uses: actions/checkout@v6
diff --git a/deployment/helm/ditto/Chart.yaml b/deployment/helm/ditto/Chart.yaml
index 6e40119e311..1bc58246896 100644
--- a/deployment/helm/ditto/Chart.yaml
+++ b/deployment/helm/ditto/Chart.yaml
@@ -16,8 +16,8 @@ description: |
A digital twin is a virtual, cloud based, representation of his real world counterpart
(real world “Things”, e.g. devices like sensors, smart heating, connected cars, smart grids, EV charging stations etc).
type: application
-version: 3.8.19 # chart version is effectively set by release-job
-appVersion: 3.9.0-M2
+version: 4.0.0 # chart version is effectively set by release-job
+appVersion: 3.9.0-M3
keywords:
- iot-chart
- digital-twin
diff --git a/deployment/helm/ditto/ci/ci-workflow-values.yaml b/deployment/helm/ditto/ci/ci-workflow-values.yaml
index f47e2e3a19c..6f441790d0b 100644
--- a/deployment/helm/ditto/ci/ci-workflow-values.yaml
+++ b/deployment/helm/ditto/ci/ci-workflow-values.yaml
@@ -18,8 +18,6 @@
ingress:
enabled: true
host: ditto.example.com
- annotations:
- # kubernetes.io/tls-acme: "true"
tls:
- secretName: ditto-tls
hosts:
diff --git a/deployment/helm/ditto/templates/nginx-ingress-api.yaml b/deployment/helm/ditto/templates/ingress-api.yaml
similarity index 56%
rename from deployment/helm/ditto/templates/nginx-ingress-api.yaml
rename to deployment/helm/ditto/templates/ingress-api.yaml
index 96394c2fd7a..0702d37f5b7 100644
--- a/deployment/helm/ditto/templates/nginx-ingress-api.yaml
+++ b/deployment/helm/ditto/templates/ingress-api.yaml
@@ -8,7 +8,7 @@
# http://www.eclipse.org/legal/epl-2.0
#
# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.enabled -}}
+{{- if and .Values.ingress.enabled .Values.ingress.api.enabled }}
{{- $fullName := include "ditto.fullname" . -}}
---
apiVersion: networking.k8s.io/v1
@@ -17,48 +17,32 @@ metadata:
name: {{ $fullName }}-api
namespace: {{ .Release.Namespace }}
labels:
- app.kubernetes.io/name: {{ include "ditto.name" . }}-nginx
-{{ include "ditto.labels" . | indent 4 }}
- annotations:
- {{- with .Values.ingress.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
- {{ tpl .Values.ingress.api.kubernetesAuthAnnotations . | nindent 4}}
+ {{- include "ditto.labels" . | nindent 4 }}
{{- with .Values.ingress.api.annotations }}
+ annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
+ {{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
- defaultBackend:
- service:
- name: {{ $fullName }}-{{ .Values.ingress.defaultBackendSuffix }}
- port:
- name: http
-{{- if .Values.ingress.tls }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
tls:
- {{- range .Values.ingress.tls }}
- - hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
+ {{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
-{{- end }}
rules:
- - host: {{ .Values.ingress.host | quote }}
+ - {{- if .Values.ingress.host }}
+ host: {{ .Values.ingress.host | quote }}
+ {{- end }}
http:
paths:
{{- range .Values.ingress.api.paths }}
- path: {{ .path }}
- {{- if .pathType }}
pathType: {{ .pathType }}
- {{- else }}
- pathType: Prefix
- {{- end }}
backend:
service:
- name: {{ $fullName }}-{{ .backendSuffix }}
+ name: {{ $fullName }}-{{ .service.name }}
port:
name: http
{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/deployment/helm/ditto/templates/nginx-ingress-devops.yaml b/deployment/helm/ditto/templates/ingress-devops.yaml
similarity index 54%
rename from deployment/helm/ditto/templates/nginx-ingress-devops.yaml
rename to deployment/helm/ditto/templates/ingress-devops.yaml
index d01c7ea9016..f938344d0f4 100644
--- a/deployment/helm/ditto/templates/nginx-ingress-devops.yaml
+++ b/deployment/helm/ditto/templates/ingress-devops.yaml
@@ -8,7 +8,7 @@
# http://www.eclipse.org/legal/epl-2.0
#
# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.enabled -}}
+{{- if and .Values.ingress.enabled .Values.ingress.devops.enabled }}
{{- $fullName := include "ditto.fullname" . -}}
---
apiVersion: networking.k8s.io/v1
@@ -17,54 +17,32 @@ metadata:
name: {{ $fullName }}-devops
namespace: {{ .Release.Namespace }}
labels:
- app.kubernetes.io/name: {{ include "ditto.name" . }}-nginx
-{{ include "ditto.labels" . | indent 4 }}
- annotations:
- {{- with .Values.ingress.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
- {{- if .Values.ingress.devops.annotations }}
+ {{- include "ditto.labels" . | nindent 4 }}
{{- with .Values.ingress.devops.annotations }}
+ annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
- {{- else }}
- {{- with .Values.ingress.api.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
- {{- end }}
-
spec:
+ {{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
- defaultBackend:
- service:
- name: {{ $fullName }}-{{ .Values.ingress.defaultBackendSuffix }}
- port:
- name: http
-{{- if .Values.ingress.tls }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
tls:
- {{- range .Values.ingress.tls }}
- - hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
+ {{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
-{{- end }}
rules:
- - host: {{ .Values.ingress.host | quote }}
+ - {{- if .Values.ingress.host }}
+ host: {{ .Values.ingress.host | quote }}
+ {{- end }}
http:
paths:
{{- range .Values.ingress.devops.paths }}
- path: {{ .path }}
- {{- if .pathType }}
pathType: {{ .pathType }}
- {{- else }}
- pathType: Prefix
- {{- end }}
backend:
service:
- name: {{ $fullName }}-{{ .backendSuffix }}
+ name: {{ $fullName }}-{{ .service.name }}
port:
name: http
{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/deployment/helm/ditto/templates/nginx-ingress-ui.yaml b/deployment/helm/ditto/templates/ingress-ui.yaml
similarity index 62%
rename from deployment/helm/ditto/templates/nginx-ingress-ui.yaml
rename to deployment/helm/ditto/templates/ingress-ui.yaml
index e1d7b999603..c73cdabaaae 100644
--- a/deployment/helm/ditto/templates/nginx-ingress-ui.yaml
+++ b/deployment/helm/ditto/templates/ingress-ui.yaml
@@ -8,7 +8,7 @@
# http://www.eclipse.org/legal/epl-2.0
#
# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.enabled -}}
+{{- if and .Values.ingress.enabled .Values.ingress.ui.enabled }}
{{- $fullName := include "ditto.fullname" . -}}
---
apiVersion: networking.k8s.io/v1
@@ -17,47 +17,39 @@ metadata:
name: {{ $fullName }}-ui
namespace: {{ .Release.Namespace }}
labels:
- app.kubernetes.io/name: {{ include "ditto.name" . }}-nginx
-{{ include "ditto.labels" . | indent 4 }}
- annotations:
- {{- with .Values.ingress.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
+ {{- include "ditto.labels" . | nindent 4 }}
{{- with .Values.ingress.ui.annotations }}
+ annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
+ {{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
+ {{- end }}
+ {{- if .Values.ingress.ui.defaultBackend }}
defaultBackend:
service:
- name: {{ $fullName }}-{{ .Values.ingress.defaultBackendSuffix }}
+ name: {{ $fullName }}-{{ .Values.ingress.ui.defaultBackend.service.name }}
port:
name: http
-{{- if .Values.ingress.tls }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
tls:
- {{- range .Values.ingress.tls }}
- - hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
+ {{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
-{{- end }}
rules:
- - host: {{ .Values.ingress.host | quote }}
+ - {{- if .Values.ingress.host }}
+ host: {{ .Values.ingress.host | quote }}
+ {{- end }}
http:
paths:
{{- range .Values.ingress.ui.paths }}
- path: {{ .path }}
- {{- if .pathType }}
pathType: {{ .pathType }}
- {{- else }}
- pathType: Prefix
- {{- end }}
backend:
service:
- name: {{ $fullName }}-{{ .backendSuffix }}
+ name: {{ $fullName }}-{{ .service.name }}
port:
name: http
{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/deployment/helm/ditto/templates/nginx-ingress-ws.yaml b/deployment/helm/ditto/templates/ingress-ws.yaml
similarity index 56%
rename from deployment/helm/ditto/templates/nginx-ingress-ws.yaml
rename to deployment/helm/ditto/templates/ingress-ws.yaml
index 02d1656d757..d5c11760225 100644
--- a/deployment/helm/ditto/templates/nginx-ingress-ws.yaml
+++ b/deployment/helm/ditto/templates/ingress-ws.yaml
@@ -8,7 +8,7 @@
# http://www.eclipse.org/legal/epl-2.0
#
# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.enabled -}}
+{{- if and .Values.ingress.enabled .Values.ingress.ws.enabled }}
{{- $fullName := include "ditto.fullname" . -}}
---
apiVersion: networking.k8s.io/v1
@@ -17,48 +17,32 @@ metadata:
name: {{ $fullName }}-ws
namespace: {{ .Release.Namespace }}
labels:
- app.kubernetes.io/name: {{ include "ditto.name" . }}-nginx
-{{ include "ditto.labels" . | indent 4 }}
- annotations:
- {{- with .Values.ingress.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
+ {{- include "ditto.labels" . | nindent 4 }}
{{- with .Values.ingress.ws.annotations }}
+ annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
- {{ tpl .Values.ingress.api.kubernetesAuthAnnotations . | nindent 4}}
spec:
+ {{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
- defaultBackend:
- service:
- name: {{ $fullName }}-{{ .Values.ingress.defaultBackendSuffix }}
- port:
- name: http
-{{- if .Values.ingress.tls }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
tls:
- {{- range .Values.ingress.tls }}
- - hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
+ {{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
-{{- end }}
rules:
- - host: {{ .Values.ingress.host | quote }}
+ - {{- if .Values.ingress.host }}
+ host: {{ .Values.ingress.host | quote }}
+ {{- end }}
http:
paths:
{{- range .Values.ingress.ws.paths }}
- path: {{ .path }}
- {{- if .pathType }}
pathType: {{ .pathType }}
- {{- else }}
- pathType: Prefix
- {{- end }}
backend:
service:
- name: {{ $fullName }}-{{ .backendSuffix }}
+ name: {{ $fullName }}-{{ .service.name }}
port:
name: http
{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/deployment/helm/ditto/templates/nginx-ingress-auth.yaml b/deployment/helm/ditto/templates/nginx-ingress-auth.yaml
deleted file mode 100644
index 6d2adeb77f7..00000000000
--- a/deployment/helm/ditto/templates/nginx-ingress-auth.yaml
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (c) 2023 Contributors to the Eclipse Foundation
-#
-# See the NOTICE file(s) distributed with this work for additional
-# information regarding copyright ownership.
-#
-# This program and the accompanying materials are made available under the
-# terms of the Eclipse Public License 2.0 which is available at
-# http://www.eclipse.org/legal/epl-2.0
-#
-# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.enabled -}}
-{{- $releaseName := .Release.Name -}}
-{{- $name := include "ditto.name" . -}}
-{{- $labels := include "ditto.labels" . -}}
----
-apiVersion: v1
-kind: Secret
-metadata:
- name: {{ $releaseName }}-nginx-ingress-htpasswd
- namespace: {{ .Release.Namespace }}
- labels:
- app.kubernetes.io/name: {{ $name }}-nginx-ingress-config
-{{ $labels | indent 4 }}
-type: Opaque
-stringData:
- auth: |-
-{{- if .Values.global.hashedBasicAuthUsers }}
- {{ range .Values.global.hashedBasicAuthUsers }}
- {{- . | indent 4 }}
- {{ end }}
-{{- else }}
- {{- if (quote .Values.global.existingSecret | empty) }}
- {{ range $key, $value := .Values.global.basicAuthUsers }}
- {{- (htpasswd $value.user $value.password) | indent 4 }}
- {{ end }}
- {{- else }}
- {{- $secret := lookup "v1" "Secret" $.Release.Namespace .Values.global.existingSecret }}
- {{- if $secret }}
- {{- range $user, $password := $secret.data }}
- {{ htpasswd $user ($password | b64dec) | indent 4 }}
- {{- end }}
- {{- else}}
- {{- fail (printf "Missing provided existingSecret for basicAuthUsers: %s" .Values.global.existingSecret) }}
- {{- end }}
- {{ end }}
-{{ end }}
----
-{{- end }}
diff --git a/deployment/helm/ditto/templates/nginx-ingress-root.yaml b/deployment/helm/ditto/templates/nginx-ingress-root.yaml
deleted file mode 100644
index ef292c2409d..00000000000
--- a/deployment/helm/ditto/templates/nginx-ingress-root.yaml
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (c) 2023 Contributors to the Eclipse Foundation
-#
-# See the NOTICE file(s) distributed with this work for additional
-# information regarding copyright ownership.
-#
-# This program and the accompanying materials are made available under the
-# terms of the Eclipse Public License 2.0 which is available at
-# http://www.eclipse.org/legal/epl-2.0
-#
-# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.enabled -}}
-{{- $fullName := include "ditto.fullname" . -}}
----
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: {{ $fullName }}-root
- namespace: {{ .Release.Namespace }}
- labels:
- app.kubernetes.io/name: {{ include "ditto.name" . }}-nginx
-{{ include "ditto.labels" . | indent 4 }}
- annotations:
- {{- with .Values.ingress.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
- {{- with .Values.ingress.root.annotations }}
- {{- toYaml . | nindent 4 }}
- {{- end }}
-spec:
- ingressClassName: {{ .Values.ingress.className }}
- defaultBackend:
- service:
- name: {{ $fullName }}-{{ .Values.ingress.defaultBackendSuffix }}
- port:
- name: http
-{{- if .Values.ingress.tls }}
- tls:
- {{- range .Values.ingress.tls }}
- - hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
- {{- end }}
-{{- end }}
- rules:
- - host: {{ .Values.ingress.host | quote }}
- http:
- paths:
- {{- range .Values.ingress.root.paths }}
- - path: {{ .path }}
- {{- if .pathType }}
- pathType: {{ .pathType }}
- {{- else }}
- pathType: Prefix
- {{- end }}
- backend:
- service:
- name: {{ $fullName }}-{{ .backendSuffix }}
- port:
- name: http
- {{- end }}
-{{- end }}
diff --git a/deployment/helm/ditto/templates/nginx-ingress.yaml b/deployment/helm/ditto/templates/nginx-ingress.yaml
deleted file mode 100644
index b6e337cdde6..00000000000
--- a/deployment/helm/ditto/templates/nginx-ingress.yaml
+++ /dev/null
@@ -1,854 +0,0 @@
-# Copyright (c) 2023 Contributors to the Eclipse Foundation
-#
-# See the NOTICE file(s) distributed with this work for additional
-# information regarding copyright ownership.
-#
-# This program and the accompanying materials are made available under the
-# terms of the Eclipse Public License 2.0 which is available at
-# http://www.eclipse.org/legal/epl-2.0
-#
-# SPDX-License-Identifier: EPL-2.0
-{{- if .Values.ingress.controller.enabled -}}
----
-apiVersion: v1
-kind: Namespace
-metadata:
- name: "{{ .Values.ingress.controller.namespace }}"
- labels:
- name: "{{ .Values.ingress.controller.namespace }}"
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: nginx-node-health-check-conf
- namespace: "{{ .Values.ingress.controller.namespace }}"
-data:
- nginx-node-health-check.conf: |
- # config for health check container running together with the ingress controller
- worker_processes 1;
-
- events {
- worker_connections 1024;
- }
-
- http {
- charset utf-8;
-
- server {
- listen 8080;
- server_name localhost;
-
- location /healthz {
- add_header Content-Type text-plain;
- return 200 'ok';
- }
-
- }
- }
-
----
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.namespace }}"
- name: "{{ .Values.ingress.controller.namespace }}"
- namespace: "{{ .Values.ingress.controller.namespace }}"
-spec:
- selector:
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- ports:
- - name: tcp
- port: 80
- protocol: TCP
-
----
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxIngressVersion }}"
- name: nginx-ingress-controller-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
-spec:
- ports:
- - appProtocol: https
- name: https-webhook
- port: 443
- targetPort: webhook
- selector:
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- type: ClusterIP
-
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-configuration
- namespace: "{{ .Values.ingress.controller.namespace }}"
-data:
- allow-snippet-annotations: "True"
- worker-processes: "{{ .Values.ingress.controller.config.workerProcesses }}"
- max-worker-connections: "{{ .Values.ingress.controller.config.workerConnections }}" # 0 will use the value of max-worker-open-files
- max-worker-open-files: "{{ .Values.ingress.controller.config.workerOpenFiles }}" # the default of 0 means "max open files (system's limit) / worker-processes - 1024"
- server-tokens: "False"
- use-gzip: "True"
- gzip-level: "6"
- gzip-types: "text/plain text/css text/js text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss"
- location-snippet: |
- more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains";
- more_set_headers 'X-Content-Type-Options: "nosniff"';
- more_set_headers 'X-Frame-Options: "SAMEORIGIN"';
- more_set_headers 'X-XSS-Protection: "1; mode=block"';
- default_type application/octet-stream;
- gzip_disable "msie6";
- gzip_min_length 1100;
- gzip_buffers 16 8k;
- gzip_proxied any;
- gunzip on;
- gzip_static always;
- gzip_vary on;
-
- tcp_nopush on;
-
- # timeouts are configured slightly higher than gateway read-timeout of 60 seconds
- send_timeout 70; # seconds, default: 60
-
- # ignore X-Original-URI in the request
- proxy_hide_header X-Original-URI;
-
-
- # set ditto-specific forwarded headers - needed in the location for registry.k8s.io/ingress-nginx/controller
- proxy_set_header X-Forwarded-User $remote_user;
- proxy_set_header x-ditto-pre-authenticated "nginx:$remote_user";
-
- proxy-connect-timeout: "10" # seconds, default: 60
- # timeouts are configured slightly higher than gateway read-timeout of 60 seconds
- proxy-send-timeout: "70" # seconds, default: 60
- proxy-read-timeout: "70" # seconds, default: 60
- # will try another upstream if an error or timeout occurred during the connection
- # or if the upstream returns 502 response
- proxy-next-upstream: "error timeout http_502"
- # will retry up to 4 times to find another upstream to connect to
- proxy-next-upstream-tries: "4"
- # will try for max. 50s to find another upstream to connect to
- proxy-next-upstream-timeout: "50"
- client-header-buffer-size: "8k" # allow longer URIs + headers (default: 1k)
- large-client-header-buffers: "4 16k"
- keep-alive: "75" #seconds, default: 75
- log-format-upstream: '$remote_addr - "$remote_user" [$time_local] "$host" "$request" $status $bytes_sent "$upstream_addr" "$http_referer" "$http_user_agent" "$http_origin" "$http_content_type"'
- use-forwarded-headers: "True"
- http-snippet: |
- charset utf-8;
- sendfile on;
-
- # timeouts are configured slightly higher than gateway read-timeout of 60 seconds
- send_timeout 70; # seconds, default: 60
-
- merge_slashes off; # allow multiple slashes for CRS Authentication
-
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: tcp-services
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: udp-services
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-serviceaccount
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: Role
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-role
- namespace: "{{ .Values.ingress.controller.namespace }}"
-rules:
- - apiGroups:
- - ""
- resources:
- - namespaces
- verbs:
- - get
- - apiGroups:
- - ""
- resources:
- - configmaps
- - pods
- - secrets
- - endpoints
- - services
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - networking.k8s.io
- resources:
- - ingresses
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - networking.k8s.io
- resources:
- - ingresses/status
- verbs:
- - update
- - apiGroups:
- - networking.k8s.io
- resources:
- - ingressclasses
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resourceNames:
- - ingress-controller-leader
- resources:
- - configmaps
- verbs:
- - get
- - update
- - apiGroups:
- - ""
- resources:
- - configmaps
- verbs:
- - create
- - apiGroups:
- - coordination.k8s.io
- resourceNames:
- - ingress-controller-leader
- resources:
- - leases
- verbs:
- - get
- - update
- - apiGroups:
- - coordination.k8s.io
- resources:
- - leases
- verbs:
- - create
- - apiGroups:
- - ""
- resources:
- - events
- verbs:
- - create
- - patch
- - apiGroups:
- - discovery.k8s.io
- resources:
- - endpointslices
- verbs:
- - list
- - watch
- - get
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: Role
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
-rules:
- - apiGroups:
- - ""
- resources:
- - secrets
- verbs:
- - get
- - create
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- labels:
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: "{{ .Values.ingress.controller.namespace }}-clusterrole"
-rules:
- - apiGroups:
- - ""
- resources:
- - configmaps
- - endpoints
- - nodes
- - pods
- - secrets
- - namespaces
- verbs:
- - list
- - watch
- - apiGroups:
- - coordination.k8s.io
- resources:
- - leases
- verbs:
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - nodes
- verbs:
- - get
- - apiGroups:
- - ""
- resources:
- - services
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - networking.k8s.io
- resources:
- - ingresses
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - ""
- resources:
- - events
- verbs:
- - create
- - patch
- - apiGroups:
- - networking.k8s.io
- resources:
- - ingresses/status
- verbs:
- - update
- - apiGroups:
- - networking.k8s.io
- resources:
- - ingressclasses
- verbs:
- - get
- - list
- - watch
- - apiGroups:
- - discovery.k8s.io
- resources:
- - endpointslices
- verbs:
- - list
- - watch
- - get
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission
-rules:
- - apiGroups:
- - admissionregistration.k8s.io
- resources:
- - validatingwebhookconfigurations
- verbs:
- - get
- - update
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-role-binding
- namespace: "{{ .Values.ingress.controller.namespace }}"
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: Role
- name: nginx-ingress-role
-subjects:
-- kind: ServiceAccount
- name: nginx-ingress-serviceaccount
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: Role
- name: nginx-ingress-admission
-subjects:
- - kind: ServiceAccount
- name: nginx-ingress-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- labels:
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: "{{ .Values.ingress.controller.namespace }}-clusterrole-binding"
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: ClusterRole
- name: "{{ .Values.ingress.controller.namespace }}-clusterrole"
-subjects:
-- kind: ServiceAccount
- name: nginx-ingress-serviceaccount
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: ClusterRole
- name: nginx-ingress-admission
-subjects:
- - kind: ServiceAccount
- name: nginx-ingress-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
-
----
-apiVersion: scheduling.k8s.io/v1
-kind: PriorityClass
-metadata:
- name: high-priority
-value: 1000000
-globalDefault: false
-description: "This priority class is used for the things and gateway service pods only."
-
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-controller
- namespace: "{{ .Values.ingress.controller.namespace }}"
-spec:
- replicas: {{ .Values.ingress.controller.replicaCount }}
- selector:
- matchLabels:
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- strategy:
- type: {{ .Values.ingress.controller.updateStrategy.type }}
- rollingUpdate:
- maxSurge: {{ .Values.ingress.controller.updateStrategy.rollingUpdate.maxSurge }}
- maxUnavailable: {{ .Values.ingress.controller.updateStrategy.rollingUpdate.maxUnavailable }}
- minReadySeconds: {{ .Values.ingress.controller.minReadySeconds }}
- revisionHistoryLimit: {{ .Values.ingress.controller.revisionHistoryLimit }}
- template:
- metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- annotations:
- prometheus.io/port: "10254"
- prometheus.io/scrape: "true"
- checksum/nginx-auth: {{ include (print $.Template.BasePath "/nginx-ingress-auth.yaml") . | sha256sum }}
- spec:
- priorityClassName: high-priority
- serviceAccountName: nginx-ingress-serviceaccount
- dnsPolicy: ClusterFirst
- nodeSelector:
- ingress.node: "master"
- terminationGracePeriodSeconds: 100
- imagePullSecrets:
- - name: acr-secret
- securityContext:
- fsGroup: 101
- supplementalGroups: [101]
- seccompProfile:
- type: RuntimeDefault
- topologySpreadConstraints:
- - maxSkew: {{ .Values.ingress.controller.topologySpreadConstraints.maxSkew }}
- topologyKey: {{ .Values.ingress.controller.topologySpreadConstraints.topologyKey }}
- whenUnsatisfiable: {{ .Values.ingress.controller.topologySpreadConstraints.whenUnsatisfiable }}
- labelSelector:
- matchLabels:
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- containers:
- - name: nginx-node-health-check
- image: docker.io/library/nginx:{{ .Values.ingress.controller.nginxVersion }}
- imagePullPolicy: Always
- ports:
- - name: healthz-port
- containerPort: 8080
- hostPort: 31005
- livenessProbe:
- httpGet:
- path: /healthz
- port: 8080
- scheme: HTTP
- initialDelaySeconds: 10
- periodSeconds: 15
- timeoutSeconds: 6
- successThreshold: 1
- failureThreshold: 4
- readinessProbe:
- httpGet:
- path: /healthz
- port: 8080
- scheme: HTTP
- initialDelaySeconds: 10
- periodSeconds: 10
- timeoutSeconds: 2
- failureThreshold: 3
- successThreshold: 1
- volumeMounts:
- - name: nginx-node-health-check-conf
- mountPath: /etc/nginx/nginx.conf
- subPath: nginx-node-health-check.conf
- - name: nginx-ingress-controller
- image: registry.k8s.io/ingress-nginx/controller:{{ .Values.ingress.controller.nginxIngressVersion }}
- imagePullPolicy: IfNotPresent
- args:
- - /nginx-ingress-controller
- - --publish-service=$(POD_NAMESPACE)/{{ .Values.ingress.controller.namespace }}
- - --election-id=ingress-controller-leader
- - --controller-class=k8s.io/{{ .Values.ingress.controller.namespace }}
- - --ingress-class={{ .Values.ingress.className }}
- - --configmap=$(POD_NAMESPACE)/nginx-configuration
- - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- - --shutdown-grace-period=65
- - --validating-webhook=:8443
- - --validating-webhook-certificate=/usr/local/certificates/cert
- - --validating-webhook-key=/usr/local/certificates/key
- securityContext:
- capabilities:
- drop:
- - ALL
- add:
- - NET_BIND_SERVICE
- # www-data -> 101
- runAsUser: 101
- runAsGroup: 101
- runAsNonRoot: true
- allowPrivilegeEscalation: true
- seccompProfile:
- type: RuntimeDefault
- lifecycle:
- preStop:
- exec:
- command: ["sleep", "{{ .Values.ingress.controller.preStopWait }}"]
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- - name: LD_PRELOAD
- value: /usr/local/lib/libmimalloc.so
- ports:
- - name: http
- containerPort: 80
- hostPort: 30005
- - name: https
- containerPort: 443
- protocol: TCP
- - name: health
- containerPort: 10254
- - name: webhook
- containerPort: 8443
- protocol: TCP
- livenessProbe:
- httpGet:
- path: /healthz
- port: 10254
- scheme: HTTP
- initialDelaySeconds: 10
- periodSeconds: 15
- timeoutSeconds: 6
- successThreshold: 1
- failureThreshold: 4
- readinessProbe:
- httpGet:
- path: /healthz
- port: 10254
- scheme: HTTP
- initialDelaySeconds: 10
- periodSeconds: 10
- timeoutSeconds: 2
- failureThreshold: 3
- successThreshold: 1
- resources:
- requests:
- cpu: {{ mulf .Values.ingress.controller.resources.cpu 1000 }}m
- memory: {{ .Values.ingress.controller.resources.memoryMi }}Mi
- volumeMounts:
- - mountPath: /usr/local/certificates/
- name: webhook-cert
- readOnly: true
- volumes:
- - name: nginx-node-health-check-conf
- configMap:
- name: nginx-node-health-check-conf
- - name: webhook-cert
- secret:
- secretName: nginx-ingress-admission
----
-apiVersion: batch/v1
-kind: Job
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission-create
- namespace: "{{ .Values.ingress.controller.namespace }}"
-spec:
- template:
- metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission-create
- spec:
- containers:
- - args:
- - create
- - --host=nginx-ingress-controller-admission.$(POD_NAMESPACE).svc
- - --namespace=$(POD_NAMESPACE)
- - --secret-name=nginx-ingress-admission
- env:
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f
- imagePullPolicy: IfNotPresent
- name: create
- securityContext:
- allowPrivilegeEscalation: false
- nodeSelector:
- kubernetes.io/os: linux
- restartPolicy: OnFailure
- securityContext:
- fsGroup: 2000
- runAsNonRoot: true
- runAsUser: 2000
- serviceAccountName: nginx-ingress-admission
-
----
-apiVersion: batch/v1
-kind: Job
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission-patch
- namespace: "{{ .Values.ingress.controller.namespace }}"
-spec:
- template:
- metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission-patch
- spec:
- containers:
- - args:
- - patch
- - --webhook-name=nginx-ingress-admission-{{ .Values.ingress.controller.namespace }}
- - --namespace=$(POD_NAMESPACE)
- - --patch-mutating=false
- - --secret-name=nginx-ingress-admission
- - --patch-failure-policy=Fail
- env:
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f
- imagePullPolicy: IfNotPresent
- name: patch
- securityContext:
- allowPrivilegeEscalation: false
- nodeSelector:
- kubernetes.io/os: linux
- restartPolicy: OnFailure
- securityContext:
- fsGroup: 2000
- runAsNonRoot: true
- runAsUser: 2000
- serviceAccountName: nginx-ingress-admission
-
----
-apiVersion: networking.k8s.io/v1
-kind: IngressClass
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: "{{ .Values.ingress.className }}"
-spec:
- controller: k8s.io/{{ .Values.ingress.controller.namespace }}
-
----
-apiVersion: admissionregistration.k8s.io/v1
-kind: ValidatingWebhookConfiguration
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/name: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/part-of: "{{ .Values.ingress.controller.namespace }}"
- app.kubernetes.io/version: "{{ .Values.ingress.controller.nginxVersion }}"
- name: nginx-ingress-admission-{{ .Values.ingress.controller.namespace }}
-webhooks:
- - admissionReviewVersions:
- - v1
- clientConfig:
- service:
- name: nginx-ingress-controller-admission
- namespace: "{{ .Values.ingress.controller.namespace }}"
- path: /networking/v1/ingresses
- failurePolicy: Fail
- matchPolicy: Equivalent
- name: validate.nginx.ingress.kubernetes.io
- rules:
- - apiGroups:
- - networking.k8s.io
- apiVersions:
- - v1
- operations:
- - CREATE
- - UPDATE
- resources:
- - ingresses
- sideEffects: None
-{{- end }}
diff --git a/deployment/helm/ditto/values.yaml b/deployment/helm/ditto/values.yaml
index 08013402233..8ce1b3d5597 100644
--- a/deployment/helm/ditto/values.yaml
+++ b/deployment/helm/ditto/values.yaml
@@ -355,244 +355,96 @@ dbconfig:
# uriSecret: my-uri-secret
## ----------------------------------------------------------------------------
-## ingress configures the Ingress
+## ingress configures the Ingress resources
+## Users must bring their own ingress controller (e.g. ingress-nginx, traefik, haproxy, etc.)
+## Controller-specific behavior (auth, CORS, timeouts, etc.) should be configured via annotations
ingress:
- # enabled whether Ingress should be enabled as alternative to the contained nginx
+ # enabled controls whether Ingress resources are created
enabled: false
- # className is the 'ingressClassName' to configure in the Ingress spec
- className: nginx
- # host the hostname of the Ingress shared for all: api, ws and ui
- host: localhost
- # defaultBackendSuffix the suffix to add to the internal fullname to use as Ingress "defaultBackend"
- defaultBackendSuffix: nginx
- # annotations common annotations for all 3 Ingresses of Ditto
- controller:
- # enabled whether Ingress controller should be enabled
- enabled: false
- # replicaCount configuration for the ingress controller
- replicaCount: 1
- # Exposes the ingress controller settings in order to configure its behavior.
- config:
- # Sets the number of worker processes that should be started by the ingress controller.
- # Depending on the load of the ingress controller, this value can be increased or decreased.
- # When not sure setting it to auto is also fine, but take cares as that will increase RAM usage.
- workerProcesses: 2
- # Sets the maximum number of simultaneous connections that can be opened by each worker process.
- # 0 will use the value of max-worker-open-files. default: 16384
- workerConnections: 0
- # Sets the maximum number of files that can be opened by each worker process.
- # The default of 0 means "max open files (system's limit) - 1024".
- workerOpenFiles: 0
- updateStrategy:
- type: RollingUpdate
- rollingUpdate:
- maxSurge: 1
- maxUnavailable: 1
- # minReadySeconds configures the minimum number of seconds for which a newly created Pod should be ready without any
- # of its containers crashing, for it to be considered available
- # ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#min-ready-seconds
- minReadySeconds: 10
- # as NGINX Ingress Controller on its pod shutdown tends to interrupt connections, we need to include
- # some wait time so that existing connections are fully handled before the pod is really shut down.
- # ref: https://medium.com/codecademy-engineering/kubernetes-nginx-and-zero-downtime-in-production-2c910c6a5ed8
- preStopWait: 15
- # specify how many old ReplicaSets for ingress controller deployment will be retained
- # ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy
- revisionHistoryLimit: 5
- # resources configures the resources available/to use for the policies service
- resources:
- # cpu defines the "required" CPU of a node so that the service is placed there
- cpu: 0.75
- # memoryMi defines the memory in mebibyte (MiB) used as "required" and "limit" in k8s
- memoryMi: 1024
- # ephemeralStorageMi defines the storage in mebibyte (MiB) used as "required" and "limit" in k8s
- ephemeralStorageMi: 2048
- # namespace for ingress controller, managed by helm, should not be created manually
- namespace: ingress-nginx
- # Ingress-NGINX version. Check Supported Versions table from https://github.com/kubernetes/ingress-nginx to match k8s version.
- nginxIngressVersion: "v1.11.5"
- # Nginx Version. Check Supported Versions table from https://github.com/kubernetes/ingress-nginx to match k8s version.
- nginxVersion: "1.25.5"
- # Pod topology spread constraints for nginx-ingress controller
- # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
- topologySpreadConstraints:
- maxSkew: 1
- topologyKey: topology.kubernetes.io/zone
- whenUnsatisfiable: ScheduleAnyway
- annotations:
- nginx.ingress.kubernetes.io/service-upstream: "true"
- nginx.ingress.kubernetes.io/server-snippet: |
- charset utf-8;
- default_type application/json;
- chunked_transfer_encoding off;
-
- send_timeout 70; # seconds, default: 60
- client_header_buffer_size 8k; # allow longer URIs + headers (default: 1k)
- large_client_header_buffers 4 16k;
+ # className is the IngressClass to use — set to your ingress controller's class name
+ className: ""
+ # host is the optional hostname for all Ingress resources — if empty, no host rule is set (catch-all)
+ host: ""
+ # tls configures TLS for ingress
+ tls: []
+ # - secretName: ditto-tls
+ # hosts:
+ # - ditto.example.com
- proxy_http_version 1.1;
- proxy_set_header X-Forwarded-Host $http_host;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header X-Forwarded-For $remote_addr;
- proxy_set_header Host $host;
- # api the /api, /stats and /overall Ingress configuration
+ # api configures the Ingress for API routes (/api, /stats, /overall)
api:
- # paths configures ingress paths
+ enabled: true
+ # annotations for controller-specific configuration (auth, timeouts, CORS, etc.)
+ annotations: {}
paths:
- # negative lookahead, so we don't accept /api/2/connections, which is devops responsibility
- - path: /api/2/(?!connections)
- pathType: ImplementationSpecific
- backendSuffix: gateway
+ - path: /api
+ pathType: Prefix
+ service:
+ name: gateway
- path: /stats
- backendSuffix: gateway
+ pathType: Prefix
+ service:
+ name: gateway
- path: /overall
- backendSuffix: gateway
- kubernetesAuthAnnotations: |
- nginx.ingress.kubernetes.io/auth-type: basic
- nginx.ingress.kubernetes.io/auth-secret: {{ .Release.Name }}-nginx-ingress-htpasswd
- nginx.ingress.kubernetes.io/auth-realm: 'Authentication required to use HTTP API!'
- # annotations defines k8s annotations to add to the Ingress
- annotations:
- nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
- nginx.ingress.kubernetes.io/proxy-send-timeout: "70"
- nginx.ingress.kubernetes.io/proxy-read-timeout: "70"
- nginx.ingress.kubernetes.io/proxy-next-upstream: "error timeout http_502"
- nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "4"
- nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "50"
- nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
- nginx.ingress.kubernetes.io/configuration-snippet: |
- set $cors $http_origin;
-
- # Allow-listed origins for CORS - enforces https for those
- #if ($http_origin ~ '^https://eclipse-ditto\.github\.io(:\d+)?)$') {
- # set $cors $http_origin;
- #}
- # Allows http for localhost (on any port)
- #if ($http_origin ~ '^http://(localhost|127\.0\.0\.1)(:\d+)?') {
- # set $cors $http_origin;
- #}
-
- if ($cors != "") {
- add_header 'Access-Control-Allow-Origin' '$cors' always;
- add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
- add_header 'Access-Control-Allow-Credentials' 'true' always;
- add_header 'Access-Control-Allow-Headers' '$http_access_control_request_headers' always;
- add_header 'Access-Control-Expose-Headers' 'correlation-id, response-required, dry-run, channel, etag, ditto-originator, requested-acks, timeout, location, ditto-metadata, traceparent, tracestate, entity-revision' always;
- }
+ pathType: Prefix
+ service:
+ name: gateway
- if ($request_method = 'OPTIONS') {
- # Tell client that this pre-flight info is valid for 20 days
- add_header 'Access-Control-Max-Age' 1728000;
- add_header 'Access-Control-Allow-Origin' '$cors' always;
- add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
- add_header 'Access-Control-Allow-Credentials' 'true' always;
- add_header 'Access-Control-Allow-Headers' '$http_access_control_request_headers' always;
- add_header 'Access-Control-Expose-Headers' 'correlation-id, response-required, dry-run, channel, etag, ditto-originator, requested-acks, timeout, location, ditto-metadata, traceparent, tracestate, entity-revision' always;
- add_header 'Content-Type' 'text/plain charset=UTF-8';
- add_header 'Content-Length' 0;
- return 204;
- }
-
- # security relevant headers:
- add_header "Content-Security-Policy" "default-src 'none'; frame-ancestors 'none'" always;
- add_header "Strict-Transport-Security" "max-age=63072000; includeSubdomains;" always;
- add_header "Cache-Control" "no-cache" always;
- add_header "X-Content-Type-Options" "nosniff" always;
- add_header "X-Frame-Options" "SAMEORIGIN" always;
- add_header "X-XSS-Protection" "1; mode=block" always;
-
- # set ditto-specific forwarded headers
- proxy_set_header X-Forwarded-User $remote_user;
- proxy_set_header x-ditto-pre-authenticated "nginx:$remote_user";
- # ws the /ws (WebSocket) Ingress configuration
+ # ws configures the Ingress for WebSocket routes (/ws)
ws:
- # paths configures ingress paths
+ enabled: true
+ # annotations for controller-specific configuration (long timeouts, buffering, etc.)
+ annotations: {}
paths:
- path: /ws
- backendSuffix: gateway
- # annotations defines k8s annotations to add to the Ingress
- annotations:
- nginx.ingress.kubernetes.io/proxy-send-timeout: "86400"
- nginx.ingress.kubernetes.io/proxy-read-timeout: "86400"
- nginx.ingress.kubernetes.io/proxy-next-upstream: "error timeout http_502"
- nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "4"
- nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "50"
- nginx.ingress.kubernetes.io/proxy-buffering: "off"
- # the / Ingress configuration for serving the landing page and static resources
- root:
- # paths configures ingress paths
- paths:
- - path: /
- pathType: Exact
- backendSuffix: nginx
- - path: /index.html
- pathType: ImplementationSpecific
- backendSuffix: nginx
- - path: /ditto-up.svg
- pathType: ImplementationSpecific
- backendSuffix: nginx
- - path: /ditto-down.svg
- pathType: ImplementationSpecific
- backendSuffix: nginx
- # annotations defines k8s annotations to add to the Ingress
- annotations:
- nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
- nginx.ingress.kubernetes.io/configuration-snippet: |
- # security relevant headers:
- add_header "Content-Security-Policy" "default-src 'self'; script-src-elem 'self' 'sha256-Kq9eqc/CtX2tgHPLJUEf8vDO9eNiGaRBrwAYYXTroVc=' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; worker-src 'self' blob:; object-src 'none';" always;
- add_header "Strict-Transport-Security" "max-age=63072000; includeSubdomains;" always;
- add_header "Cache-Control" "no-cache" always;
- add_header "X-Content-Type-Options" "nosniff" always;
- add_header "X-Frame-Options" "SAMEORIGIN" always;
- add_header "X-XSS-Protection" "1; mode=block" always;
- # ui the /ui and /apidoc Ingress configuration
+ pathType: Prefix
+ service:
+ name: gateway
+
+ # ui configures the Ingress for the landing page, Ditto UI and Swagger API docs
ui:
- # paths configures ingress paths
+ enabled: true
+ # annotations for controller-specific configuration (URL rewriting, etc.)
+ annotations: {}
+ # defaultBackend serves as the catch-all for unmatched paths (e.g. the landing page)
+ defaultBackend:
+ service:
+ name: nginx
paths:
- path: /
pathType: Exact
- backendSuffix: nginx
- - path: /apidoc(/|$)(.*)
- pathType: ImplementationSpecific
- backendSuffix: swaggerui
- - path: /ui(/|$)(.*)
- pathType: ImplementationSpecific
- backendSuffix: dittoui
- # annotations defines k8s annotations to add to the Ingress
- annotations:
- nginx.ingress.kubernetes.io/use-regex: "true"
- nginx.ingress.kubernetes.io/rewrite-target: /$2
- nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
- nginx.ingress.kubernetes.io/configuration-snippet: |
- # security relevant headers:
- add_header "Content-Security-Policy" "default-src 'self'; script-src-elem 'self' 'sha256-Ve/Ec/6YDEeTc+9y+QCJ+e9OhyGWAj3bYxCzNGfOn6U=' 'sha256-Kq9eqc/CtX2tgHPLJUEf8vDO9eNiGaRBrwAYYXTroVc=' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; img-src 'self' data: https://raw.githubusercontent.com; font-src 'self' https://cdnjs.cloudflare.com; worker-src 'self' blob:; connect-src 'self' localhost http://localhost:8080; object-src 'none';" always;
- add_header "Strict-Transport-Security" "max-age=63072000; includeSubdomains;" always;
- add_header "Cache-Control" "no-cache" always;
- add_header "X-Content-Type-Options" "nosniff" always;
- add_header "X-Frame-Options" "SAMEORIGIN" always;
- add_header "X-XSS-Protection" "1; mode=block" always;
- rewrite ^(/ui)$ $1/ permanent;
- rewrite ^(/apidoc)$ $1/ permanent;
- # devops the /devops, /api/2/connections, /status and /health commands Ingress configuration
+ service:
+ name: nginx
+ - path: /apidoc
+ pathType: Prefix
+ service:
+ name: swaggerui
+ - path: /ui
+ pathType: Prefix
+ service:
+ name: dittoui
+
+ # devops configures the Ingress for DevOps routes (/devops, /health, /status, /api/2/connections)
devops:
- # paths configures ingress paths
+ enabled: true
+ annotations: {}
paths:
- path: /devops
- backendSuffix: gateway
- - path: /status
- backendSuffix: gateway
+ pathType: Prefix
+ service:
+ name: gateway
- path: /health
- backendSuffix: gateway
+ pathType: Prefix
+ service:
+ name: gateway
+ - path: /status
+ pathType: Prefix
+ service:
+ name: gateway
- path: /api/2/connections
- backendSuffix: gateway
- # annotations defines k8s annotations to add to the Ingress
- # if undefined, api ingress annotations are reused
- annotations:
- # tls configures the TLS for ingress
- tls: []
- # - secretName: ditto-tls
- # hosts:
- # - localhost
+ pathType: Prefix
+ service:
+ name: gateway
## ----------------------------------------------------------------------------
diff --git a/documentation/src/main/resources/_posts/2026-04-01-ingress-controller-agnostic-helm-chart.md b/documentation/src/main/resources/_posts/2026-04-01-ingress-controller-agnostic-helm-chart.md
new file mode 100644
index 00000000000..dac5b17c956
--- /dev/null
+++ b/documentation/src/main/resources/_posts/2026-04-01-ingress-controller-agnostic-helm-chart.md
@@ -0,0 +1,267 @@
+---
+title: "Helm chart now ingress controller agnostic"
+published: true
+permalink: 2026-04-01-ingress-controller-agnostic-helm-chart.html
+layout: post
+author: kalin_kostashki
+tags: [blog, kubernetes, helm]
+hide_sidebar: true
+sidebar: false
+toc: true
+---
+
+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 `Prefix` and `Exact` — no more controller-specific regex paths
+- **Added** per-group `enabled` flags — each route group (api, ws, ui, devops) can be independently toggled
+- **Replaced** the `backendSuffix` pattern with explicit `service.name` references
+
+## 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 removed
+- `ingress.api.kubernetesAuthAnnotations` — removed
+- `ingress.className` — default changed from `"nginx"` to `""` (empty)
+- `ingress.host` — default changed from `"localhost"` to `""` (catch-all)
+- `backendSuffix` — replaced by `service.name` in each path entry
+- All per-group nginx-specific annotation blocks — removed
+
+## New values.yaml structure
+
+The ingress section is now clean and controller-agnostic:
+
+```yaml
+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:
+
+```bash
+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:
+
+```bash
+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:
+
+```bash
+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:
+
+```yaml
+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:
+
+```yaml
+apiVersion: traefik.io/v1alpha1
+kind: Middleware
+metadata:
+ name: strip-prefix
+ namespace: ditto
+spec:
+ stripPrefix:
+ prefixes:
+ - /ui
+ - /apidoc
+```
+
+Then reference it in the ingress configuration:
+
+```yaml
+ingress:
+ enabled: true
+ className: traefik
+ host: ditto.example.com
+ ui:
+ annotations:
+ traefik.ingress.kubernetes.io/router.middlewares: ditto-strip-prefix@kubernetescrd
+```
+
+### HAProxy
+
+```yaml
+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
+
+1. **Install your ingress controller separately** (e.g., via its own Helm chart)
+2. **Update your values.yaml** to match the new structure — replace `backendSuffix` with `service.name`,
+ remove `ingress.controller.*` and global annotations
+3. **Add controller-specific annotations** to the appropriate route groups
+4. **Upgrade the chart** to version 4.0.0
+
+
+
+{% include image.html file="ditto.svg" alt="Ditto" max-width=500 %}
+--
+The Eclipse Ditto team