Configuring a ClusterIssuer for IONOS Domains

Table of Contents

I recently purchased a single domain from ionos.com and needed to configure an additional ClusterIssuer in my Kubernetes cluster alongside my existing Cloudflare ClusterIssuer, since IONOS uses a different API endpoint. It took me a while to find suitable documentation for this, as most guides focus on IONOS Cloud rather than IONOS DNS. So this Blogpost will only focus on the cert-manager part.

Install cert-manager via helm

Add the helm repository

helm repo add jetstack https://charts.jetstack.io --force-update

Install cert-manager

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.18.2 \
  --set crds.enabled=true

What is a Cluster Issuer?

After installing cert-manager, the next step is to create a ClusterIssuer. A ClusterIssuer in Kubernetes is a cluster-wide resource managed by cert-manager that defines how TLS certificates are requested and issued. It includes the configuration for the certificate authority or ACME provider (such as Let’s Encrypt) and specifies the challenge type (e.g., DNS-01 or HTTP-01).

An ACME challenge is the process used by certificate authorities to verify that you control the requested domain before issuing an SSL/TLS certificate. For DNS-01 challenges, this is typically done by creating a specific TXT record in your domain’s DNS zone—a task cert-manager can handle automatically using the IONOS DNS API.

Create an IONOS API Token

To allow cert-manager to create these DNS records, we need an API token from IONOS.

  1. Log in to your IONOS account.
  2. Navigate to Domain & SSL → Open API Portal.
  3. Create a new API token. (I will delete mine after publishing this post)
Repo

Copy your public prefix and secret. We will use it in the next step when creating the Kubernetes Secret for cert-manager.

Create the secret and ClusterIssuer

First, we need to create a new file secret.yaml with the following content.

apiVersion: v1
stringData:
  IONOS_PUBLIC_PREFIX: 7a3e4d1e81c44eae8bd177f945047aba # paste your public prefix 
  IONOS_SECRET: IfXEjhXLfzzGihvFAJ8aTwGTj6Pu2TgY4Po7Mj8YaBHJxHohpv7QkXCMArou79h1zRbf7X5-R42RnTPXLJjszg # paste your secret
kind: Secret
metadata:
  name: ionos-secret
  namespace: cert-manager
type: Opaque

Create your secret:

kubectl apply -f secret.yaml

Now, we can create the ClusterIssuer file issuer.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-ionos
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: <[email protected]>
    privateKeySecretRef:
      name: letsencrypt-ionos
    solvers:
      - dns01:
          webhook:
            groupName: acme.fabmade.de
            solverName: ionos
            config:
              apiUrl: https://api.hosting.ionos.com/dns/v1
              publicKeySecretRef:
                key: IONOS_PUBLIC_PREFIX
                name: ionos-secret
              secretKeySecretRef:
                key: IONOS_SECRET
                name: ionos-secret

Now you can create secrets, as in this example

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-certificate
  namespace: example
spec:
  dnsNames:
    - 'your.domain'
  issuerRef:
    name: letsencrypt-ionos
    kind: ClusterIssuer
  secretName: example-secret

Have fun trying it out!