PiStacks Home Setup: Dynamic DNS

From our previous post in our [Home Setup] series, we deployed Traefik Reverse Proxy on Docker Swarm.

As I have a Dynamic Public IP Address, we need some way to route connections on our DNS name (*.pistack.co.za in my case) to the Public IP where our stacks are hosted.

I host my domain on Cloudflare, and they have an API to update your DNS records. So we will use a docker container to update our Public address as soon as it changed.

I found a great docker image: oznu/cloudflare-ddns that will achieve that task for us.

At the bottom of this post, I will have the instructions available if you want to deploy this on Kubernetes.

Create a Cloudflare Account

Once you have created a account, create a "new site" and select the "free" plan:


Once you select your domain, you should be seeing something like this:


Select "DNS" and add a entry:


I will be creating a A Record with the hostname ddns and just give it the target of as it will be changed later. And also make sure to change the "Proxy status" to "DNS only"

Then create another record, this time a CNAME Record with the hostname * with the target of ddns.yourdomain.com and make sure the target is set to your domain.


This will allow us to hook up services to DNS names on the fly without having to change DNS names.

So you can create services such as Wordpress and Grafana with the hostnames wordpress.mydomain.com and grafana.mydomain.com, they will be configured on Traefik and once you make a HTTP request` the DNS will resolve the query to the Public IP address and once it hits Traefik it will know where to route the connection to.

Create a Cloudflare API Key

To create a API Key, select your profile at the top right corner, select "My Profile", then select "API Tokens" and at the bottom you can access your API Keys:


Deploy the Docker Container

As our current setup is based on Docker Swarm, which you can follow this post on how to provision a swarm.

We will be creating a docker compose file with our service definition and deploy the service to our swarm.

Our docker-compose.yml:

version: "3.4"  
    image: oznu/cloudflare-ddns:armhf
      - [email protected]
      - API_KEY=your-api-key
      - ZONE=yourdomain.com
      - SUBDOMAIN=ddns
      - PROXIED=false
      - RRTYPE=A
      - DELETE_ON_STOP=false

Just make sure to populate your values into the environment fields.

Then deploy the stack:

$ docker stack deploy -c docker-compose.yml cloudflare

Once the service is running you can tail the logs to see if the DNS entry was updated, in my case:

$ docker service logs -f cloudflare_ddns
Zone: x.x (x)  
cloudflare_ddns.1.nrwyokg7fw66@rpi-01    | DNS Record: ddns.x.x (x)  
cloudflare_ddns.1.nrwyokg7fw66@rpi-01    | [cont-init.d] 30-cloudflare-setup: exited 0.  
cloudflare_ddns.1.nrwyokg7fw66@rpi-01    | [cont-init.d] 50-ddns: executing...  
cloudflare_ddns.1.nrwyokg7fw66@rpi-01    | Updating CloudFlare DNS record ddns.x.x from to 155.x.x.x ...  
cloudflare_ddns.1.nrwyokg7fw66@rpi-01    | CloudFlare DNS record ddns.x.x (155.x.x.x) updated successfully.  

Now whenever your Public IP changes, your docker service will take care of your DNS changes.

Optional: Deploy on Kubernetes

If you want to deploy the Cloudflare DDNS Client on Kubernetes:

apiVersion: v1  
kind: ConfigMap  
  name: cloudflare-ddns-env
  API_KEY: your-api-key
  DELETE_ON_STOP: "false"
  EMAIL: [email protected]
  PROXIED: "false"
  ZONE: yourdomain.com
kind: Deployment  
apiVersion: apps/v1  
  name: cloudflare-ddns
  namespace: default
    app: cloudflare-ddns
    category: tools
  replicas: 1
      app: cloudflare-ddns
      category: tools
        app: cloudflare-ddns
        category: tools
      - name: cloudflare-ddns
        image: oznu/cloudflare-ddns:armhf
        - configMapRef:
            name: cloudflare-ddns-env
            cpu: 100m
            memory: 50Mi
            cpu: 100m
            memory: 50Mi

Then deploy:

$ kubectl apply -f deployment.yml