How to set up Dynamic DNS on FreeIPA for your Kubernetes Cluster

Kubernetes freeipa dns DevOps

I have a FreeIPA server that serves DNS on my home network. I wanted to automatically configure it with my Kubernetes ingresses using ExternalDNS. There doesn’t seem to be much documentation for this specific setup, so I thought to put together this guide!


This guide will assume that you have the following set up already:

  • A Kubernetes cluster running on your network
  • A FreeIPA server (let’s say serving DNS for a certain zone you want as the domain suffixes (call it
  • An app (or apps) on the Kubernetes cluster exposed on an Ingress (we’ll assume it’s

In addition, I used the following guides to assemble this guide:

1. Generate a TSIG key and register it

We will need to generate a TSIG key first.

Choose a name for your key. I called mine k8s but we’ll call it keyname. Then on your FreeIPA server, execute

$ dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST keyname

and you will get 2 files in your working directory that are probably called something like Kkeyname.+165+44840.key and Kkeyname.+165+44840.private. Open up the .private one:

$ cat Kkeyname.+165+44840.private
Private-key-format: v1.3
Algorithm: 165 (HMAC_SHA512)
Key: zeOLcYcv/95yZX1KSLDreZyMtAsy5Ci5xwC9gW7XAgtOnOTIJpyr03CNDA8sUxfrkhb6Hjs90d3zRGm2g0XDaQ==
Bits: AAA=
Created: 20210418040622
Publish: 20210418040622
Activate: 20210418040622

and copy the part after Key:.

Finally, add the following to your /etc/named.conf, but substitute the key for your key:

key "keyname" {
       algorithm hmac-sha512;
       secret "zeOLcYcv/95yZX1KSLDreZyMtAsy5Ci5xwC9gW7XAgtOnOTIJpyr03CNDA8sUxfrkhb6Hjs90d3zRGm2g0XDaQ==";

Repeat this for every FreeIPA server you have, and we can move onto the next step.

2. Enable DDNS on your FreeIPA server

This step can be done via UI or CLI, but I did it via UI.

First, navigate to your DNS zone’s settings page.

How the top of your UI should look

Scroll down to where it says “Dynamic update” and set that to True. Additionally, add the following line1 to “BIND update policy,” replacing keyname with your key and with your zone:

grant keyname subdomain ANY;

Now, your UI should look something like this:

How your UI should look after making these changes

Save your changes, and anyone with that secret key can add anything to that subdomain.

3. Install ExternalDNS on your Kubernetes cluster

ExternalDNS is an addon for Kubernetes that has functionality to provide DNS updates over RFC2136. I installed the bitnami/external-dns Helm chart using the following Helmfile:

  - name: bitnami
  - name: freeipa-dns-sync
    namespace: external-dns
    chart: bitnami/external-dns
    installed: true
      - provider: rfc2136
        logFormat: json
          - # only handle DDNS for * domains
          host: # replace with your host
          zone: # replace with your zone
          tsigKeyname: keyname # replace with your keyname
          tsigSecretAlg: hmac-sha512
          secretName: freeipa-rfc2136

After deploying this with helmfile apply, I then installed the following secret:

apiVersion: v1
kind: Secret
  name: freeipa-rfc2136
  namespace: external-dns
type: Opaque
  # replace with your secret
  rfc2136_tsig_secret: zeOLcYcv/95yZX1KSLDreZyMtAsy5Ci5xwC9gW7XAgtOnOTIJpyr03CNDA8sUxfrkhb6Hjs90d3zRGm2g0XDaQ==

And that’s it! You should soon see DNS records show up in FreeIPA automatically.

FreeIPA DNS, but with automatically updated DNS settings

For debugging, you may want to check external DNS’s logs using kubectl logs [podname].

  1. Note that this is a deviation from this guide, where it says to write grant keyname name ANY;. name only allows you to change, while subdomain allows you to change every domain like *, as described here.