{{- if and .Values.ingress.enabled .Values.landing.enabled }} {{- /* The landing catch-all lives in its own Ingress so it can carry an explicit Traefik router priority. Traefik derives router priority from the length of the generated rule string. With the catch-all in the same Ingress as the API paths, Path(`/health`) and PathPrefix(`/`) are both 15 characters — an exact tie, broken arbitrarily, and in practice the landing nginx won and /health returned 404 through the ingress while the service answered 200 in-cluster. PathPrefix(`/v1`) is longer, so /v1 was unaffected, which is why the fault looked like a /health-only bug. An explicit low priority here keeps the browser landing page as a true fallback: every API route outranks it regardless of rule length. */}} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "reuse.landingFullname" . }} labels: {{- include "reuse.labels" . | nindent 4 }} annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.priority: {{ .Values.landing.ingress.priority | quote }} spec: ingressClassName: {{ .Values.ingress.className }} {{- if .Values.ingress.tls }} tls: - hosts: - {{ .Values.ingress.host }} secretName: {{ include "reuse.fullname" . }}-tls {{- end }} rules: - host: {{ .Values.ingress.host }} http: paths: - path: / pathType: Prefix backend: service: name: {{ include "reuse.landingFullname" . }} port: number: {{ .Values.landing.service.port }} {{- end }}