← Start of tutorial

WIUNIX ACADEMY

cert-manager DNS-01 renewal stuck? Trace Certificate, Order and authoritative TXT

Page 2 of 3. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Rocky Linux 9Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment12 editable values
05

LET’S BUILD

Separate presentation failure from propagation

Challenge presented=false with provider errors points toward solver selection, Secret reference, API permission, zone detection or provider availability. Presented=true means the solver believes it presented the record; it does not prove authoritative public visibility. Narrow DNS credentials to the required zone and operation through the owning secret-management process; do not grant global account access as a workaround.

bash

Operator terminal; authorized lab context

kubectl --context='lab' -n 'academy-lab' get challenge 'api-tls-challenge' -o jsonpath='{.spec.dnsName}{"\n"}{.spec.type}{"\n"}{.status.presented}{"\n"}{.status.processing}{"\n"}{.status.reason}{"\n"}'
kubectl --context='lab' -n 'cert-manager' logs deployment/cert-manager --since=15m --tail=200
How do I know it worked?

A provider/presentation error is distinguished from an unresolved self-check. Review logs privately.

06

LET’S BUILD

Find delegation and the actual authoritative server

Run on an authorized workstation with dig. Query the exact Challenge DNS name, considering wildcard base names and any delegated challenge zone. A CNAME may move the effective TXT owner; cert-manager does not follow DNS01 CNAMEs unless configured for that strategy. Do not assume the registrar UI is the authoritative provider.

The executable TXT panels below deliberately cover a normal non-delegated DNS zone without a CNAME. If this step reveals a CNAME or a separately delegated challenge subzone, stop this recipe and map its effective owner and authority with the DNS/cert-manager owner; do not run the following fixed-owner TXT commands against the wrong name.

bash

Operator terminal; authorized lab context

dig +trace '_acme-challenge.api.example.com.' TXT
dig +noall +answer '_acme-challenge.api.example.com.' CNAME
dig +noall +answer 'example.com.' SOA
dig +noall +answer 'example.com.' NS
How do I know it worked?

Delegation, SOA/NS and any CNAME explain where the TXT must be visible.

07

LET’S BUILD

Compare authoritative and recursive answers

Set dns_server to one actual authoritative nameserver address from the previous step. Nonrecursive TXT queries should show the expected challenge value at the effective owner. Recursive answers may lag due to positive or negative caching. Do not print the provider API token; the ACME TXT is a validation value, not that token. Multiple TXT values can legitimately coexist for parallel authorizations.

bash

Operator terminal; authorized lab context

dig @'192.0.2.53' +norecurse +time=3 +tries=1 '_acme-challenge.api.example.com.' TXT
dig +time=3 +tries=1 '_acme-challenge.api.example.com.' TXT
dig @'192.0.2.53' +tcp +norecurse +time=3 +tries=1 '_acme-challenge.api.example.com.' TXT
How do I know it worked?

Record authoritative/recursive status and matching TXT; a timeout differs from an absent value.

08

LET’S BUILD

Investigate a split-view self-check

If public authoritative TXT is correct but self-check remains pending, inspect cluster resolver behavior, egress to DNS and SOA visibility. cert-manager uses recursive resolvers for zone discovery and authoritative checks unless flags alter that behavior. Review existing controller arguments without changing them. Recursive-only flags and custom resolvers affect every issuance on that controller; change only through its owner with a rollback plan.

bash

Operator terminal; authorized lab context

kubectl --context='lab' -n 'cert-manager' get deployment cert-manager -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{"\n"}{.args}{"\n"}{end}'
kubectl --context='lab' -n 'cert-manager' get networkpolicy
kubectl --context='lab' -n 'academy-lab' describe challenge 'api-tls-challenge'
How do I know it worked?

Self-check failure is linked to a demonstrated DNS path/configuration issue, or remains explicitly unproven.

09

LET’S BUILD

Correct once and allow controlled reconciliation

Repair the documented cause in the issuer/provider/source configuration and let reconciliation progress. Do not repeatedly delete TLS Secrets, Orders or ACME account keys. CA rate limits and invalid authorization reuse are not repaired by a restart. If an authorized manual retry is needed, use the supported cmctl renewal operation only after reviewing certificate scope and the existing CA response; prefer staging for a separate new test certificate.

bash

Operator terminal; authorized lab context

# Optional: only after the cause is corrected and the owner authorizes renewal:
cmctl renew --context='lab' --namespace='academy-lab' 'api-tls'
kubectl --context='lab' -n 'academy-lab' describe certificate 'api-tls'
kubectl --context='lab' -n 'academy-lab' get certificaterequest,order,challenge
How do I know it worked?

The linked request progresses to valid/Ready without repeated blind retries; failures retain their CA reason.

10

LET’S BUILD

Verify the certificate actually served to clients

A Ready Certificate does not prove the ingress has reloaded it or that you reached the intended endpoint. Use SNI and hostname verification from an authorized external route, then inspect expiry and SAN. Private CA deployments need their approved trust chain instead of disabling verification. The command exposes no private key.

bash

Operator terminal; authorized lab context

set -o pipefail
timeout 15s openssl s_client -connect 'api.example.com:443' -servername 'api.example.com' -verify_hostname 'api.example.com' -verify_return_error </dev/null | openssl x509 -noout -dates -serial -ext subjectAltName
How do I know it worked?

Trust/name verification passes and the served SAN/expiry match the newly issued certificate.

Explore all tutorials ↗