+1 416.471.0356       info@pasha.solutions

Updating Cloudflare DDNS on Ubiquiti UDM-Pro

I've been somewhat pulling my hair out (ok, that's a lie - I have none) figuring out a way to update a Cloudflare A name using the UDM-Pro. There's a long list of reasons you'd want to do this, but for my purposes in this instance I want to setup a VPN endpoint. Of course, static IP addresses aren't something that are common for small business users, and especially not so for home users. Setting manual DNS entries will work for all of a few days and users need something easy to remember that will update whenever the public IP address of the UDM-Pro gets updated (which could be days, weeks, or even months apart). 

Ubiquiti's firmware allows DDNS updates natively within it, but the providers are quite limited, and despite Cloudflare being arguably the most requested one in the forums, they've yet to add it. I suspect this is because it's not as simple as a quick URL call with some variables like DynDNS used to be. There's some tricky ways to do this using DNSoMatic, but I'm going to be setting this up for a long list of clients, and I also really don't want to rely on yet another middleware service.  

Previously I did this on my Synology NAS which I posted about here, but I wanted something more permanent. This solution graciously utilizes the work of a few people I'd like to credit, specifically boostchicken and timothymiller. To give you some context, the UDM-Pro runs Debian as a core OS, then it basically runs the Unifi-OS within a container. That means we can run other containers alongside the Unifi-OS container and do whatever the hell we want in there. Granted, it'll chew into the system resources the Unifi-OS uses from the hardware, but this is super minor so we're not all that worried here. Let's get going.


  1. First you'll want to SSH into your UDM-Pro. I suggest using PuTTy.

  2. We'll install the UDM-boot script from here : https://github.com/boostchicken/udm-utilities/blob/master/on-boot-script/README.md. This more or less allows us to run a bunch of things on startup (so, if the UDM-Pro reboots, does a firmware upgrade, or whatever, our customizations will stick). As we're already SSH'd in... 
    1. Drop into the Unifi-OS Shell

      unifi-os shell
    2. Download the boot scripts to the UDM-Pro
      curl -L https://udm-boot.boostchicken.dev -o udm-boot_1.0.5_all.deb
      dpkg -i udm-boot_1.0.5_all.deb
      Make sure to exit out of the Unifi-OS shell, which we did above with "exit".

  3. Excellent. Let's move on and add in the Cloudflare script 
    1. Make a directory to store the Cloudflare scripts
      mkdir -p /mnt/data/cloudflare-ddns​
    2. Create a config.json file. Just toss it in with VI...  vi config.json, then insert this (command : I), and then save by hitting ESC a few times, then typing :wq! - I've supplied my config.json file below, but I've fudged some of the variable values.
        "cloudflare": [
            "authentication": {
                "api_token": "Qjlkjs9sWKzQhE983ks0k30s0ab2e9s8ZxATX0tAAaz", 
                "api_key": {
                    "api_key": "83661alks93kd09ks8kpsk0dgb75c087wP",
                    "account_email": "This email address is being protected from spambots. You need JavaScript enabled to view it."
            "zone_id": "142d77681af781e09lacddc888dcbdf9fb8d61",
            "subdomains": [
            "proxied": false,
            "ttl": 120
    3. Of course, edit up the values as you see fit. Here's what you'll want to replace: 
      API TOKEN - Create one with edit privileges on the zone you're looking to edit. You'll likely need to create a new API Key.
      API KEY - Get from your Cloudflare dashboard under API. It'll be the global key.
      ACCOUNT EMAIL - The full email address of your CloudFlare account
      ZONE ID - Go to the zone in question, get the ID from Overview on the right side panel
      SUBDOMAINS - Enter the subdomain name. If you want, you can add multiples if you separate them with a comma. For example "test1", "test2", "test3" - and ensure the last entry does NOT have a comma at the end.

    4. Change your directory, and go to the boot directory
      cd /mnt/data/on_boot.d​
    5. Create a 30-cloudflare-ddns.sh file. Just toss it in with VI...  vi 30-cloudflare-ddns.sh, then insert this (command : I), and then save by hitting ESC a few times, then typing :wq!
      # Starts a cloudflare ddns container that is deleted after it is stopped.
      # All configs stored in /mnt/data/cloudflare-ddns
      if podman container exists "$CONTAINER"; then
        podman start "$CONTAINER"
        podman run -i -d --rm \
          --net=host \
          --name "$CONTAINER" \
          --security-opt=no-new-privileges \
          -v /mnt/data/cloudflare-ddns/config.json:/config.json \
    6. CHMOD the file accordingly 
      chmod 744 30-cloudflare-ddns.sh​
    7. Run the damn file from the command line..


  4. To check to ensure everything is running smoothly, you can check your various podman instances.
    1. This will show any of the containers running:

      # podman ps
      CONTAINER ID  IMAGE                                            COMMAND               CREATED         STATUS             PORTS  NAMES
      c09d3eea6b9d  docker.io/timothyjmiller/cloudflare-ddns:latest  python -u /cloudf...  40 minutes ago  Up 40 minutes ago         cloudflare-ddns
      3643198165d5  localhost/unifi-os:latest                        /sbin/init            2 months ago    Up 22 hours ago           unifi-os


    2. The script runs via CRON job every 5 minutes, so after you've gone and poured yourself a coffee for the job well done, check to see what's going on: 
      # podman logs cloudflare-ddns
      ⚙️ Individually disable IPv4 or IPv6 with new config.json options. Read more about it here: https://github.com/timothymiller/cloudflare-ddns/blob/master/README.md
      🕰️ Updating IPv4 (A) & IPv6 (AAAA) records every 5 minutes
      🧩 IPv6 not detected
      📡 Updating record {'type': 'A', 'name': 'testsubdomain', 'content': '123.456.789.10', 'proxied': False, 'ttl': 300}

And that's about that. It's pretty straightforward stuff, but if you're not familiar with using tools such as an SSH client, vi, or just generally working in a *nix shell, this is likely going to feel pretty intimidating. If that's the case, I would welcome you to reach out and I'm sure I can give you a hand.

ALL : Login