From 6bbb6dfeee2f4d075505b246d122960bbb66d77a Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Fri, 15 May 2026 08:01:25 +0100 Subject: [PATCH 1/6] Prototype docs for delayed ACME challenge acceptance Signed-off-by: Richard Wall --- content/docs/configuration/acme/README.md | 54 +++++++++++++++++++++++ content/docs/troubleshooting/acme.md | 8 ++++ 2 files changed, 62 insertions(+) diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md index 118cf5aed2d..6cb08a73591 100644 --- a/content/docs/configuration/acme/README.md +++ b/content/docs/configuration/acme/README.md @@ -81,6 +81,60 @@ Solvers come in the form of [`dns01`](./dns01/README.md) and these solver types, visit their respective documentation - [DNS01](./dns01/README.md), [HTTP01](./http01/README.md). +### Optional delayed acceptance when self-check cannot succeed + +> ⚠️ Prototype documentation for a proposed feature. +> +> This section is intended to explain and review a possible API shape before the +> feature is merged. + +A proposed solver option, `acceptChallengeAfter`, would allow cert-manager to +continue attempting the self-check as it does today, but to proceed after a +configured delay if the self-check still cannot succeed from cert-manager's own +network or DNS viewpoint. + +This is aimed at environments such as: + +- NAT loopback limitations, where cert-manager cannot reach the public address that the + ACME server can reach; +- split-horizon DNS, where cert-manager resolves a different address than the + ACME server does; or +- public/private ingress topologies where cert-manager only sees the internal + path but the ACME server validates against the external path. + +The intended behavior is: + +- cert-manager presents the challenge as usual; +- cert-manager still runs the self-check; +- if the self-check succeeds, cert-manager proceeds immediately; and +- if the self-check does not succeed, cert-manager proceeds once the configured + delay since presentation has elapsed. + +For example: + +```yaml +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + email: user@example.com + server: https://acme-staging-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: example-issuer-account-key + solvers: + - http01: + ingress: + ingressClassName: nginx-public + acceptChallengeAfter: 30s +``` + +This should be understood as an advanced escape hatch rather than a general +replacement for the self-check. It keeps the current default behavior for most +users, but provides a clear per-solver option for cases where cert-manager +cannot directly observe the same validation path as the ACME server. + ### ACME Certificate Profiles > ℹ️ This feature is available in cert-manager `>= v1.18.0`. diff --git a/content/docs/troubleshooting/acme.md b/content/docs/troubleshooting/acme.md index 7763b9ed29a..279e2a3ce59 100644 --- a/content/docs/troubleshooting/acme.md +++ b/content/docs/troubleshooting/acme.md @@ -194,6 +194,14 @@ $ kubectl get challenge -ojsonpath='{.spec.authorizationURL}' ### HTTP01 troubleshooting First of all check if you can see the challenge URL from the public internet, if this does not work check your Ingress and firewall configuration as well as the service and pod cert-manager created to solve the ACME challenge. + +If the ACME server can reach the challenge URL from the public internet but +cert-manager's self-check cannot, you may be in one of the environments +mentioned on the [ACME configuration](../configuration/acme/README.md) page: +NAT loopback limitations, split-horizon DNS, or a public/private ingress split. A +proposed feature under discussion would allow a per-solver delay before +challenge acceptance so that cert-manager can still proceed after waiting for a +configured amount of time. If this does work check if your cluster can see it too. It is important to test this from inside a Pod. If you get a connection error it is suggested to check the cluster's network configuration. If you receive a `tls: handshake failure`, try setting the annotation `cert-manager.io/issue-temporary-certificate: "true"` on the Ingress or Certificate resource. This will issue a temporary self signed certificate for the ingress controller to use before the actual certificate is issued. If you still are having issues, there may be an issue with your ingress controller handling multiple resources for the same hostname, in this case, the annotation `acme.cert-manager.io/http01-edit-in-place: "true"` is likely required. From ed64ef41ca57059e6649d882cea38f180c58f7cc Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Thu, 21 May 2026 07:53:23 +0100 Subject: [PATCH 2/6] Polish ACME delayed challenge acceptance docs Signed-off-by: Richard Wall --- content/docs/configuration/acme/README.md | 9 ++++++++- content/docs/troubleshooting/acme.md | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md index 6cb08a73591..d36ff0ea4b7 100644 --- a/content/docs/configuration/acme/README.md +++ b/content/docs/configuration/acme/README.md @@ -83,7 +83,7 @@ these solver types, visit their respective documentation - ### Optional delayed acceptance when self-check cannot succeed -> ⚠️ Prototype documentation for a proposed feature. +> ⚠️ Draft documentation for a proposed feature. > > This section is intended to explain and review a possible API shape before the > feature is merged. @@ -93,6 +93,9 @@ continue attempting the self-check as it does today, but to proceed after a configured delay if the self-check still cannot succeed from cert-manager's own network or DNS viewpoint. +The same field would be available on either an `http01` or `dns01` solver +entry. + This is aimed at environments such as: - NAT loopback limitations, where cert-manager cannot reach the public address that the @@ -135,6 +138,10 @@ replacement for the self-check. It keeps the current default behavior for most users, but provides a clear per-solver option for cases where cert-manager cannot directly observe the same validation path as the ACME server. +Choose the delay conservatively. If it is too short, the ACME server may still +start validation before your solver resources are reachable. If it is too long, +certificate issuance will wait longer than necessary. + ### ACME Certificate Profiles > ℹ️ This feature is available in cert-manager `>= v1.18.0`. diff --git a/content/docs/troubleshooting/acme.md b/content/docs/troubleshooting/acme.md index 279e2a3ce59..15e1a7aa100 100644 --- a/content/docs/troubleshooting/acme.md +++ b/content/docs/troubleshooting/acme.md @@ -198,10 +198,13 @@ First of all check if you can see the challenge URL from the public internet, if If the ACME server can reach the challenge URL from the public internet but cert-manager's self-check cannot, you may be in one of the environments mentioned on the [ACME configuration](../configuration/acme/README.md) page: -NAT loopback limitations, split-horizon DNS, or a public/private ingress split. A -proposed feature under discussion would allow a per-solver delay before +NAT loopback limitations, split-horizon DNS, or a public/private ingress split. +A proposed feature under discussion would allow a per-solver delay before challenge acceptance so that cert-manager can still proceed after waiting for a configured amount of time. + +A similar issue can also affect DNS01 if cert-manager can only query internal +DNS views while the ACME server validates against the public TXT record. If this does work check if your cluster can see it too. It is important to test this from inside a Pod. If you get a connection error it is suggested to check the cluster's network configuration. If you receive a `tls: handshake failure`, try setting the annotation `cert-manager.io/issue-temporary-certificate: "true"` on the Ingress or Certificate resource. This will issue a temporary self signed certificate for the ingress controller to use before the actual certificate is issued. If you still are having issues, there may be an issue with your ingress controller handling multiple resources for the same hostname, in this case, the annotation `acme.cert-manager.io/http01-edit-in-place: "true"` is likely required. From 19295d500ac02b82df91ded75736abee83036738 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Thu, 21 May 2026 07:55:07 +0100 Subject: [PATCH 3/6] Write ACME delayed challenge acceptance docs as final copy Signed-off-by: Richard Wall --- content/docs/configuration/acme/README.md | 15 +++++---------- content/docs/troubleshooting/acme.md | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md index d36ff0ea4b7..ea2dfa7df04 100644 --- a/content/docs/configuration/acme/README.md +++ b/content/docs/configuration/acme/README.md @@ -83,15 +83,10 @@ these solver types, visit their respective documentation - ### Optional delayed acceptance when self-check cannot succeed -> ⚠️ Draft documentation for a proposed feature. -> -> This section is intended to explain and review a possible API shape before the -> feature is merged. - -A proposed solver option, `acceptChallengeAfter`, would allow cert-manager to -continue attempting the self-check as it does today, but to proceed after a -configured delay if the self-check still cannot succeed from cert-manager's own -network or DNS viewpoint. +The `acceptChallengeAfter` solver option allows cert-manager to continue +attempting the self-check as it does today, but to proceed after a configured +delay if the self-check still cannot succeed from cert-manager's own network or +DNS viewpoint. The same field would be available on either an `http01` or `dns01` solver entry. @@ -105,7 +100,7 @@ This is aimed at environments such as: - public/private ingress topologies where cert-manager only sees the internal path but the ACME server validates against the external path. -The intended behavior is: +The behavior is: - cert-manager presents the challenge as usual; - cert-manager still runs the self-check; diff --git a/content/docs/troubleshooting/acme.md b/content/docs/troubleshooting/acme.md index 15e1a7aa100..c63051d35bb 100644 --- a/content/docs/troubleshooting/acme.md +++ b/content/docs/troubleshooting/acme.md @@ -199,7 +199,7 @@ If the ACME server can reach the challenge URL from the public internet but cert-manager's self-check cannot, you may be in one of the environments mentioned on the [ACME configuration](../configuration/acme/README.md) page: NAT loopback limitations, split-horizon DNS, or a public/private ingress split. -A proposed feature under discussion would allow a per-solver delay before +The `acceptChallengeAfter` solver option allows a per-solver delay before challenge acceptance so that cert-manager can still proceed after waiting for a configured amount of time. From 646bd68d50df0bbf6993e291cff5edcf9629ead9 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Thu, 21 May 2026 19:51:51 +0100 Subject: [PATCH 4/6] Add release note for ACME delayed challenge acceptance Signed-off-by: Richard Wall --- content/docs/configuration/acme/README.md | 2 ++ .../releases/release-notes/release-notes-1.21.md | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md index ea2dfa7df04..f88fdfbd46d 100644 --- a/content/docs/configuration/acme/README.md +++ b/content/docs/configuration/acme/README.md @@ -83,6 +83,8 @@ these solver types, visit their respective documentation - ### Optional delayed acceptance when self-check cannot succeed +> ℹ️ This feature is available in cert-manager `>= v1.21.0`. + The `acceptChallengeAfter` solver option allows cert-manager to continue attempting the self-check as it does today, but to proceed after a configured delay if the self-check still cannot succeed from cert-manager's own network or diff --git a/content/docs/releases/release-notes/release-notes-1.21.md b/content/docs/releases/release-notes/release-notes-1.21.md index 0b5222a0a2b..93bfc7ee0c9 100644 --- a/content/docs/releases/release-notes/release-notes-1.21.md +++ b/content/docs/releases/release-notes/release-notes-1.21.md @@ -9,7 +9,17 @@ cert-manager v1.21 includes: ## Major Themes -### TODO +### Delayed ACME challenge acceptance + +cert-manager 1.21 adds the `acceptChallengeAfter` solver option for ACME +HTTP01 and DNS01 challenges. This allows cert-manager to continue attempting +its self-check as usual, but to proceed after a configured delay in +environments where cert-manager cannot reliably observe the same validation +path as the ACME server. + +See [Optional delayed acceptance when self-check cannot +succeed](../../configuration/acme/README.md#optional-delayed-acceptance-when-self-check-cannot-succeed) +for configuration details. ## Community @@ -41,7 +51,7 @@ And finally, thanks to the cert-manager steering committee for their feedback in ### Feature -TODO +- Add the `acceptChallengeAfter` solver option for ACME HTTP01 and DNS01 challenges, allowing cert-manager to proceed after a configured delay when self-checks cannot succeed from cert-manager's own network or DNS viewpoint. See the [ACME issuer documentation](../../configuration/acme/README.md#optional-delayed-acceptance-when-self-check-cannot-succeed) for configuration details. ### Documentation From c7aa448e5f59ec391b5812519a438c6c452705c0 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Thu, 21 May 2026 19:55:35 +0100 Subject: [PATCH 5/6] Tighten ACME delayed acceptance wording Signed-off-by: Richard Wall Signed-off-by: Richard Wall --- .spelling | 1 + content/docs/configuration/acme/README.md | 30 ++++++++----------- .../release-notes/release-notes-1.21.md | 19 ++++++------ content/docs/troubleshooting/acme.md | 6 ++-- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/.spelling b/.spelling index 35412e5ebc8..853368b6fc4 100644 --- a/.spelling +++ b/.spelling @@ -426,6 +426,7 @@ goroutine gosec hardcodes hardcoded +hairpinning healthz honour hostname diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md index f88fdfbd46d..9ddaf597aad 100644 --- a/content/docs/configuration/acme/README.md +++ b/content/docs/configuration/acme/README.md @@ -81,17 +81,15 @@ Solvers come in the form of [`dns01`](./dns01/README.md) and these solver types, visit their respective documentation - [DNS01](./dns01/README.md), [HTTP01](./http01/README.md). -### Optional delayed acceptance when self-check cannot succeed +### Skip the self-check with `waitInsteadOfSelfCheck` > ℹ️ This feature is available in cert-manager `>= v1.21.0`. -The `acceptChallengeAfter` solver option allows cert-manager to continue -attempting the self-check as it does today, but to proceed after a configured -delay if the self-check still cannot succeed from cert-manager's own network or -DNS viewpoint. +The `waitInsteadOfSelfCheck` solver option skips cert-manager's own self-check +and instead waits a configured duration after presentation before asking the +ACME server to validate the challenge. -The same field would be available on either an `http01` or `dns01` solver -entry. +You can set this field on either an `http01` or `dns01` solver entry. This is aimed at environments such as: @@ -102,13 +100,13 @@ This is aimed at environments such as: - public/private ingress topologies where cert-manager only sees the internal path but the ACME server validates against the external path. -The behavior is: +The behavior when `waitInsteadOfSelfCheck` is set is: - cert-manager presents the challenge as usual; -- cert-manager still runs the self-check; -- if the self-check succeeds, cert-manager proceeds immediately; and -- if the self-check does not succeed, cert-manager proceeds once the configured - delay since presentation has elapsed. +- cert-manager records the time of first presentation in `status.presentedAt`; +- cert-manager skips its own self-check; and +- once the configured duration has elapsed since `status.presentedAt`, + cert-manager asks the ACME server to validate the challenge. For example: @@ -127,13 +125,11 @@ spec: - http01: ingress: ingressClassName: nginx-public - acceptChallengeAfter: 30s + waitInsteadOfSelfCheck: 30s ``` -This should be understood as an advanced escape hatch rather than a general -replacement for the self-check. It keeps the current default behavior for most -users, but provides a clear per-solver option for cases where cert-manager -cannot directly observe the same validation path as the ACME server. +This is an advanced escape hatch for cases where cert-manager cannot directly +observe the same validation path as the ACME server. Choose the delay conservatively. If it is too short, the ACME server may still start validation before your solver resources are reachable. If it is too long, diff --git a/content/docs/releases/release-notes/release-notes-1.21.md b/content/docs/releases/release-notes/release-notes-1.21.md index 93bfc7ee0c9..614f0b3798e 100644 --- a/content/docs/releases/release-notes/release-notes-1.21.md +++ b/content/docs/releases/release-notes/release-notes-1.21.md @@ -9,16 +9,17 @@ cert-manager v1.21 includes: ## Major Themes -### Delayed ACME challenge acceptance +### Skip the self-check with `waitInsteadOfSelfCheck` -cert-manager 1.21 adds the `acceptChallengeAfter` solver option for ACME -HTTP01 and DNS01 challenges. This allows cert-manager to continue attempting -its self-check as usual, but to proceed after a configured delay in -environments where cert-manager cannot reliably observe the same validation -path as the ACME server. +cert-manager 1.21 adds the `waitInsteadOfSelfCheck` solver option for ACME +HTTP01 and DNS01 challenges. When set, cert-manager skips its own self-check +and instead waits the configured duration after presentation before asking the +ACME server to validate. This is an escape hatch for environments where +cert-manager cannot reliably observe the same validation path as the ACME +server, such as split-horizon DNS or NAT loopback (or hairpinning). -See [Optional delayed acceptance when self-check cannot -succeed](../../configuration/acme/README.md#optional-delayed-acceptance-when-self-check-cannot-succeed) +See [Skip the self-check with +`waitInsteadOfSelfCheck`](../../configuration/acme/README.md#skip-the-self-check-with-waitinsteadofselfcheck) for configuration details. ## Community @@ -51,7 +52,7 @@ And finally, thanks to the cert-manager steering committee for their feedback in ### Feature -- Add the `acceptChallengeAfter` solver option for ACME HTTP01 and DNS01 challenges, allowing cert-manager to proceed after a configured delay when self-checks cannot succeed from cert-manager's own network or DNS viewpoint. See the [ACME issuer documentation](../../configuration/acme/README.md#optional-delayed-acceptance-when-self-check-cannot-succeed) for configuration details. +- Add the `waitInsteadOfSelfCheck` solver option for ACME HTTP01 and DNS01 challenges, allowing cert-manager to skip its own self-check and ask the ACME server to validate after a configured wait. See the [ACME issuer documentation](../../configuration/acme/README.md#skip-the-self-check-with-waitinsteadofselfcheck) for configuration details. ### Documentation diff --git a/content/docs/troubleshooting/acme.md b/content/docs/troubleshooting/acme.md index c63051d35bb..985fc221d24 100644 --- a/content/docs/troubleshooting/acme.md +++ b/content/docs/troubleshooting/acme.md @@ -199,9 +199,9 @@ If the ACME server can reach the challenge URL from the public internet but cert-manager's self-check cannot, you may be in one of the environments mentioned on the [ACME configuration](../configuration/acme/README.md) page: NAT loopback limitations, split-horizon DNS, or a public/private ingress split. -The `acceptChallengeAfter` solver option allows a per-solver delay before -challenge acceptance so that cert-manager can still proceed after waiting for a -configured amount of time. +The [`waitInsteadOfSelfCheck`](../configuration/acme/README.md#skip-the-self-check-with-waitinsteadofselfcheck) +solver option skips the self-check entirely and instead waits a configured +duration after presentation before asking the ACME server to validate. A similar issue can also affect DNS01 if cert-manager can only query internal DNS views while the ACME server validates against the public TXT record. From 99e4988cc83a4b659e7666e4fdec5b1701d450bf Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Fri, 12 Jun 2026 17:04:02 +0000 Subject: [PATCH 6/6] Document waitInsteadOfSelfCheck zero value and validation - Explain that a value of 0 skips the self-check and asks the ACME server to validate immediately, relying on the server's own validation retries (RFC 8555 section 8.2). - Note that negative durations are rejected by the validating webhook. Aligns the docs with the final API behaviour in cert-manager/cert-manager#8858. Signed-off-by: Richard Wall Signed-off-by: Richard Wall Co-authored-by: Claude Signed-off-by: Richard Wall --- content/docs/configuration/acme/README.md | 11 ++++++++++- content/docs/troubleshooting/acme.md | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md index 9ddaf597aad..dccb04bfc4c 100644 --- a/content/docs/configuration/acme/README.md +++ b/content/docs/configuration/acme/README.md @@ -85,7 +85,8 @@ these solver types, visit their respective documentation - > ℹ️ This feature is available in cert-manager `>= v1.21.0`. -The `waitInsteadOfSelfCheck` solver option skips cert-manager's own self-check +The `waitInsteadOfSelfCheck` solver option skips cert-manager's own +[self-check](../../concepts/acme-orders-challenges.md#challenge-lifecycle) and instead waits a configured duration after presentation before asking the ACME server to validate the challenge. @@ -125,6 +126,7 @@ spec: - http01: ingress: ingressClassName: nginx-public + # or use dns01: instead of http01: for split-horizon DNS scenarios waitInsteadOfSelfCheck: 30s ``` @@ -135,6 +137,13 @@ Choose the delay conservatively. If it is too short, the ACME server may still start validation before your solver resources are reachable. If it is too long, certificate issuance will wait longer than necessary. +A value of `0` is permitted: cert-manager skips the self-check and asks the ACME +server to validate immediately after presentation. In this case cert-manager +relies on the ACME server's own validation retries +([RFC 8555 section 8.2](https://www.rfc-editor.org/rfc/rfc8555#section-8.2)) to +succeed once the challenge has propagated. Negative durations are rejected by the +validating webhook. + ### ACME Certificate Profiles > ℹ️ This feature is available in cert-manager `>= v1.18.0`. diff --git a/content/docs/troubleshooting/acme.md b/content/docs/troubleshooting/acme.md index 985fc221d24..596cc85180b 100644 --- a/content/docs/troubleshooting/acme.md +++ b/content/docs/troubleshooting/acme.md @@ -196,7 +196,7 @@ $ kubectl get challenge -ojsonpath='{.spec.authorizationURL}' First of all check if you can see the challenge URL from the public internet, if this does not work check your Ingress and firewall configuration as well as the service and pod cert-manager created to solve the ACME challenge. If the ACME server can reach the challenge URL from the public internet but -cert-manager's self-check cannot, you may be in one of the environments +cert-manager's [self-check](../concepts/acme-orders-challenges.md#challenge-lifecycle) cannot, you may be in one of the environments mentioned on the [ACME configuration](../configuration/acme/README.md) page: NAT loopback limitations, split-horizon DNS, or a public/private ingress split. The [`waitInsteadOfSelfCheck`](../configuration/acme/README.md#skip-the-self-check-with-waitinsteadofselfcheck) @@ -205,6 +205,7 @@ duration after presentation before asking the ACME server to validate. A similar issue can also affect DNS01 if cert-manager can only query internal DNS views while the ACME server validates against the public TXT record. + If this does work check if your cluster can see it too. It is important to test this from inside a Pod. If you get a connection error it is suggested to check the cluster's network configuration. If you receive a `tls: handshake failure`, try setting the annotation `cert-manager.io/issue-temporary-certificate: "true"` on the Ingress or Certificate resource. This will issue a temporary self signed certificate for the ingress controller to use before the actual certificate is issued. If you still are having issues, there may be an issue with your ingress controller handling multiple resources for the same hostname, in this case, the annotation `acme.cert-manager.io/http01-edit-in-place: "true"` is likely required.