Clusterward
← Back to the blog
OperationsFlorian Apel

cert-manager with Scaleway DNS: wildcard certificates via DNS-01

Your domain lives at Scaleway, you need *.example.com – and cert-manager knows Cloudflare and Route 53, but not Scaleway. How wildcard certificates via DNS-01 reach the cluster with Scaleway’s own webhook, pitfalls included.

Cover image: cert-manager with Scaleway DNS: wildcard certificates via DNS-01

Monday morning at a SaaS team on Scaleway: the tenth customer this week gets their subdomain, and certificate issuance stalls. The reason is known – Let’s Encrypt counts every certificate against the registered domain – and so is the fix: a wildcard certificate for *.example.com. Except the zone lives in Scaleway Domains & DNS, and Scaleway is not on cert-manager’s list of built-in DNS providers.

The DNS-01 challenge is the ACME method in which you prove control over a domain by publishing a given value as a TXT record under _acme-challenge.<domain>. For cert-manager to drive Scaleway DNS, you need a webhook. Below: the steps, the pitfalls and how Clusterward handles it.

Why do wildcard certificates need DNS-01?

Let’s Encrypt knows three challenge types. HTTP-01 places a file under /.well-known/acme-challenge/ and suits individual hosts; Let’s Encrypt explicitly rules it out for wildcards, and TLS-ALPN-01 as well. That leaves DNS-01: whoever may set TXT records in the zone controls every subdomain beneath it, so this proof suffices for *.example.com.

Why a wildcard pays off with a subdomain per customer is covered in Let’s Encrypt rate limits: why SaaS subdomains need a wildcard certificate. This one is about the how.

Why doesn’t cert-manager know Scaleway?

cert-manager ships DNS-01 solvers for a fixed list: ACME-DNS, Akamai, Azure DNS, Cloudflare, Google Cloud DNS, Route 53, DigitalOcean and RFC2136. Every other provider plugs in through a webhook: a separate service in the cluster that cert-manager calls as an API extension, which sets and removes the TXT records.

For Scaleway, Scaleway maintains the webhook itself: chart scaleway-certmanager-webhook from the repository https://helm.scw.cloud, API group acme.scaleway.com, solver name scaleway. All three reappear in the issuer.

Does the zone really live at Scaleway?

The webhook writes to Scaleway Domains & DNS, so the zone must exist there and be authoritative. A domain registered with Scaleway has one automatically. A domain from another registrar is added as an external domain:

  • Scaleway first asks for a TXT record _scaleway-challenge in the current zone as proof of ownership.
  • Then you switch the nameservers at the registrar to ns0.dom.scw.cloud and ns1.dom.scw.cloud.
  • Scaleway allows 14 days for the whole process, then removes the external domain again.

While the old nameservers still answer, the webhook’s TXT record lands in a zone Let’s Encrypt never asks, and the challenge stays pending forever.

How do I set up the Scaleway webhook?

You need cert-manager running. Then, in this order:

  1. Create an IAM key. In the Scaleway console under IAM, create an application, give it a policy with the permission set DomainsDNSFullAccess on exactly the project that holds the zone, and generate an API key. The key needs nothing more.
  2. Install the webhook and wait. helm repo add scaleway https://helm.scw.cloud/, then helm install scaleway-certmanager-webhook scaleway/scaleway-certmanager-webhook -n cert-manager --wait. The webhook obtains its own serving certificate from cert-manager; only then does kubectl get apiservice v1alpha1.acme.scaleway.com report Available – in our clusters after about a minute.
  3. A Secret in the right namespace. A Secret with the keys SCW_ACCESS_KEY and SCW_SECRET_KEY in the namespace cert-manager – why exactly there follows below.
  4. Create a ClusterIssuer. An ACME issuer with a dns01.webhook solver: groupName: acme.scaleway.com, solverName: scaleway and, under config, the references accessKeySecretRef and secretKeySecretRef pointing at the Secret.
  5. Request the Certificate. dnsNames with *.example.com and example.com – a wildcard covers neither the apex nor more than one level below it.
  6. Distribute the Secret. The issued Secret lives in exactly one namespace. With Reflector and the annotations reflection-allowed and reflection-auto-enabled in the secretTemplate of the Certificate it reaches every namespace, and each Ingress simply references the name.

Which pitfalls show up in practice?

  • Secret in the wrong namespace. The webhook reads the Secret in the challenge’s namespace – for a ClusterIssuer that is cert-manager’s cluster resource namespace, cert-manager by default. The chart’s RBAC role only lets it read Secrets in its own namespace anyway. So install it there; a Secret next to the application stays invisible and the challenge fails with “could not get secret”.
  • Issued too early. Create the Certificate straight after the install and the webhook’s API group may not answer yet. cert-manager retries, but the error sends you debugging. --wait and a look at the APIService avoid that.
  • Zone not authoritative. External domain added, nameservers never switched: the TXT record sits at Scaleway while Let’s Encrypt asks the old servers.
  • Key in the wrong project. The policy applies per project. If the zone sits in another project, the API refuses the write.
  • Production too soon. Let’s Encrypt allows only five failed validations per name and account per hour. Test against the staging environment first, then switch the issuer.

When issuance hangs, kubectl describe challenge in the certificate’s namespace almost always shows the actual reason.

How Clusterward handles it

In Clusterward you register the zone once under DNS with access key and secret key; right after saving, Clusterward checks that the key sees the zone, and only verified zones are offered for wildcards. The “Cluster setup” card installs cert-manager, Reflector and the Scaleway DNS webhook – the latter with a wait until its API group answers; only then does it read “Installed”.

Under Certificates, “Register wildcard” creates a managed wildcard: zone, cluster, Let’s Encrypt or its staging, an email address. Per wildcard, Clusterward creates a Secret with the key in the cert-manager namespace, a ClusterIssuer and a Certificate for the zone plus apex with the Reflector annotations, then issues at once. If something is missing, the certificate page lists each blocker beforehand (admin access to the cluster, the webhook, the zone’s key), links the card that fixes it and keeps “Issue” disabled. Afterwards Clusterward follows issuance until the certificate is ready with its expiry date; a daily check reports when it expires in under 14 days. More under DNS & certificates; how a service uses the wildcard at the ingress is described under Network & ingress.

Conclusion

Wildcard certificates for a Scaleway zone are not an exotic path but six objects in the right order: key, webhook, Secret, issuer, Certificate, Reflector. Most failures happen not in cert-manager but before it – in the Secret’s namespace, in not waiting for the webhook and in nameservers that were never switched.

Wildcard certificates for your Scaleway zone? Tell us how your domains and clusters are split today. We’ll show you how DNS-01 and your customer onboarding fit together. Ask a question →

Sources and further reading

Frequently asked questions

  • Yes, with the webhook Scaleway maintains itself: chart scaleway-certmanager-webhook from helm.scw.cloud. cert-manager has no built-in Scaleway solver. The webhook sets the TXT record of the DNS-01 challenge through the Domains API and is addressed in the issuer with groupName acme.scaleway.com and solverName scaleway.