fix(platform): migrate ACME HTTP-01 to ingressClassName API (#2436)

## What this PR does

HTTP-01 ACME issuance in Cozystack has been relying on deprecated
cert-manager fields that happen to still work, but point at a
non-existent ingress class on default installs.

**The bug:**
- `ClusterIssuer`s (`letsencrypt-prod`, `letsencrypt-stage`) hardcode
`http01.ingress.class: nginx`, but Cozystack's nginx ingress classes are
named after tenants (`tenant-root`, `tenant-*`) — there is no class
called `nginx`.
- Every ingress that needs a cert overrides this with the deprecated
annotation `acme.cert-manager.io/http01-ingress-class: <class>`.
cert-manager still honors it, which is why issuance works at all.
- Mixing the modern `ingressClassName` field with the legacy
`http01-ingress-class` annotation produces `fields ingressClassName and
class cannot be set at the same time` (cert-manager#6651), so the
migration has to be atomic.

**The fix:**
- Parameterize the `ClusterIssuer` HTTP-01 solver from
`_cluster.expose-ingress` (default `tenant-root`) using the modern
`ingressClassName` field.
- Rename the override annotation on all ingresses to the modern
`acme.cert-manager.io/http01-ingress-ingressclassname`.
- No new features, no behavior change for operators who already set
`_cluster.expose-ingress` correctly — just removes the dependency on the
deprecated API and stops pointing at a phantom class.

Touched ingresses (9 templates): keycloak, dashboard, linstor-gui,
bucket, grafana, alerta, bootbox/matchbox, seaweedfs, harbor. Plus
`seaweedfs` values.yaml default annotation and the
`cert-manager-issuers` ClusterIssuer template.

Verified renders for `http01` + `tenant-root`, `http01` + custom class,
and `dns01` (correctly omits the http01 branch).

### Release note

```release-note
fix(platform): ACME HTTP-01 challenges now use the modern `ingressClassName` API and target the tenant ingress class from `_cluster.expose-ingress` (default `tenant-root`) instead of a hardcoded `nginx` class that did not exist on most installs. Ingress templates switched from the deprecated `acme.cert-manager.io/http01-ingress-class` annotation to `acme.cert-manager.io/http01-ingress-ingressclassname`.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Chores**
* Updated cert-manager ACME HTTP-01 solver annotations across ingress
configurations to use the newer `ingressclassname` format for improved
compatibility with current cert-manager versions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
myasnikovdaniil 2026-04-21 18:39:28 +05:00 committed by GitHub
commit aa8ea10392
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 18 additions and 17 deletions

View file

@ -15,7 +15,7 @@ metadata:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $ingress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }}
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:

View file

@ -10,7 +10,7 @@ metadata:
app: bootbox
annotations:
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $ingress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }}
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
{{- if .Values.whitelistHTTP }}

View file

@ -243,7 +243,7 @@ spec:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $ingress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }}
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
tls:

View file

@ -12,7 +12,7 @@ metadata:
nginx.ingress.kubernetes.io/proxy-read-timeout: "99999"
nginx.ingress.kubernetes.io/proxy-send-timeout: "99999"
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $ingress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }}
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:

View file

@ -1,6 +1,7 @@
{{- $solver := (index .Values._cluster "solver") | default "http01" }}
{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }}
apiVersion: cert-manager.io/v1
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
@ -17,9 +18,9 @@ spec:
name: cloudflare-api-token-secret
key: api-token
{{- else }}
http01:
ingress:
class: nginx
http01:
ingress:
ingressClassName: {{ $exposeIngress }}
{{- end }}
---
@ -41,9 +42,9 @@ spec:
name: cloudflare-api-token-secret
key: api-token
{{- else }}
http01:
ingress:
class: nginx
http01:
ingress:
ingressClassName: {{ $exposeIngress }}
{{- end }}
---

View file

@ -11,7 +11,7 @@ metadata:
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $exposeIngress }}
{{- end }}
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/client-max-body-size: 100m

View file

@ -11,7 +11,7 @@ metadata:
{{- with .Values.ingress.annotations }}
annotations:
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $exposeIngress }}
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
{{- toYaml . | nindent 4 }}

View file

@ -22,7 +22,7 @@ metadata:
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $exposeIngress }}
{{- end }}
nginx.ingress.kubernetes.io/proxy-body-size: 100m
# Keycloak access+refresh+id tokens make the oauth2-proxy session

View file

@ -181,7 +181,7 @@ metadata:
app: alerta
annotations:
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: {{ $ingress }}
acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }}
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:

View file

@ -74,7 +74,7 @@ spec:
metadata:
annotations:
{{- if eq $solver "http01" }}
acme.cert-manager.io/http01-ingress-class: "{{ $ingress }}"
acme.cert-manager.io/http01-ingress-ingressclassname: "{{ $ingress }}"
{{- end }}
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:

View file

@ -111,7 +111,7 @@ seaweedfs:
nginx.ingress.kubernetes.io/client-body-timeout: "3600"
nginx.ingress.kubernetes.io/client-header-timeout: "120"
nginx.ingress.kubernetes.io/service-upstream: "true"
acme.cert-manager.io/http01-ingress-class: tenant-root
acme.cert-manager.io/http01-ingress-ingressclassname: tenant-root
cert-manager.io/cluster-issuer: letsencrypt-prod
tls:
- hosts: