I run some home infra and services including this blog. With just a standard internet connection, there's one major hurdle which is your assigned IP address. Most ISPs assign your home modem an IP with an expiry time, i.e. you have a given IP address with a deadline and when the time is up, you will get a new, and likely different one. Having a dedicated static never-changing IP address is a thing of luxury and often you pay extra when hosting applications on a cloud provider.

A means of getting around this is Dynamic DNS which is a heartbeat service that updates your domain's name server with your updated IP address. This allows DNS requests for blog.dalanmiller.com to be directed to the correct and current IP address instead of the one allocated prior to your current one.

To achieve this, I wanted it to be extremely reliable and easy as plugging in my router versus having it run on some Raspberry Pi or my Docker host. Thus, I've set up a small cron job on my EdgeRouter X to curl to the Cloudflare API to update the A record to my home IP address.

First, you need to figure out the zone id  and DNS Record ID that you need to update. This is available by looking at the DNS settings for the domain you wish to update and scrolling down the page until you find API > Zone ID.

In the DNS configuration within Cloudflare you should set your desired domain name to simply point to 1.1.1.1 for now. We want to update a prexisting record over and over again and therefore it needs to exist, and thus have an ID in Cloudflare for you to specify which one to update.

You can now run

curl -X GET "https://api.cloudflare.com/client/v4/zones/<your_zone_id_from_above>/dns_records"
  -H "X-Auth-Email: <your_email@mail.com>" \
  -H "X-Auth-Key: <your_api_key>

This will provide you a list of all your DNS records for that zone. You'll want to grab the one correpsonding to the A record (and maybe also AAAA record) that you want to continuously update.

Once you have this, you can then create the script that you want to run. This requires SSH'ing into your EdgeRouter and using vi to create a file at the path /config/scripts/ like the following:

vi /config/scripts/update_your-domain-com.sh

You can use the following bash script in order to update the record. Note, you will likely need to change the interface name from pppoe0 to the name of your WAN interface. If I recall correctly, this is commonly one of your eth interfaces but will depend on your network.

# This command extracts my current WAN IP address and assigns the string to $ip
ip=$(/opt/vyatta/bin/vyatta-show-interfaces pppoe pppoe0 | grep "inet " | awk '{print $2}')

# This HTTP request updates the record to the observed ip address
curl -X PUT "https://api.cloudflare.com/client/v4/zones/<zone_id>/dns_records/<record_id>" \
     -H "X-Auth-Email: <your_email@mail.com" \
     -H "X-Auth-Key: <your_api_key>" \
     -H "Content-Type: application/json" \
     --data "{\"type\":\"A\",\"name\":\"domain.com\",\"content\":\"$ip\",\"ttl\":1,\"proxied\":true}"

Now, we need to make sure the script is executable by setting the permissions correctly:

chmod 0755 /config/scripts/update_your-domain-com.sh

You can test the script works by running:

sh /config/scripts/update_your-domain-com.sh

You should see a successful JSON response that includes success: true some where.

Now you have a working script in place, the final piece is to indicate to EdgeOS that you want to have this thing run on a schedule. You can either add the following via configure while SSH'd into your router or via the web interface. You'll want to add the following:


system {
  ...
  task-scheduler {
     task cloudflare {
       executable {
         path /config/scripts/update_domain-com.sh
       }
       interval 1m
     }
  }
  ...
}

There will bee many other things under system but the key part is adding the task-scheduler section. And, congrats! you now have a working cron job updating Cloudlfare to point to your current IP.

I haven't yet found a way to observe prior successful script runs within EdgeOS, but will later spin up my own version of healthchecks.io as a way to determine if the job is running smoothly.