Automate Dynamic IP Updates for Your Domain with Cloudflare and Bash Script

In a world where static IP addresses are often an added expense, dynamic IP addresses can make managing domains a challenge. If your ISP assigns you a dynamic IP address, keeping your domain updated can be a hassle. This tutorial will walk you through creating a simple yet effective Bash script that uses Cloudflare’s API to update your domain’s DNS record whenever your IP changes. With this script, you can ensure that your domain always points to your current dynamic IP address, even without a static IP.

In this tutorial, you will learn:

  • How to obtain a Cloudflare API token for managing DNS
  • How to find your Zone ID and DNS Record ID
  • How to create a Bash script to update a DNS record with your dynamic IP
  • How to enhance the script to update only when the IP address changes
Automate Dynamic IP Updates for Your Domain with Cloudflare and Bash Script
Automate Dynamic IP Updates for Your Domain with Cloudflare and Bash Script
Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Any Linux-based system
Software Bash, curl, jq
Other Cloudflare account with a domain
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

Step-by-Step Guide to Map Your Domain to a Dynamic IP

Follow the steps below to create a Bash script that automatically updates your Cloudflare DNS record whenever your IP changes. This script is ideal for home servers, remote desktops, or any situation where a dynamic IP address needs to be consistently reflected in DNS.

  1. Obtain Your Cloudflare API Token: To interact with Cloudflare’s API, you need an API token with permissions to edit DNS records.
    1. Log in to Cloudflare: Visit the Cloudflare dashboard and log in with your account credentials.
    2. Navigate to API Tokens: Go to My Profile and select API Tokens.
    3. Create a New Token: Click on Create Token and choose the Edit zone DNS template.
    4. Customize the Token: Specify the domain you want the token to manage and click Create Token.
    5. Copy the Token: Copy the generated API token for use in your script.

    Copy the generated token. This will be used in your script to authenticate with Cloudflare.

  2. Find Your Zone ID and DNS Record ID: Next, you need the Zone ID of your domain and the ID of the DNS record you want to update.
    $ curl -X GET "https://api.cloudflare.com/client/v4/zones?name=example.com" \
         -H "Authorization: Bearer YOUR_CLOUDFLARE_API_TOKEN" \
         -H "Content-Type: application/json"
    

    This command will return the Zone ID for example.com. Replace example.com with your actual domain name. Note the id field, which is your Zone ID.

    Find Your Zone ID and DNS Record ID
    Find Your Zone ID and DNS Record ID

    To get the DNS_RECORD_ID, use:

    $ curl -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records?name=example.com" \
         -H "Authorization: Bearer YOUR_CLOUDFLARE_API_TOKEN" \
         -H "Content-Type: application/json"
    

    Look for the id field under the desired DNS record. This is your DNS_RECORD_ID.

    This command will get you DNS_RECORD_ID
    This command will get you DNS_RECORD_ID


  3. Create a Base Bash Script to Update the DNS Record: With the necessary IDs and token, you can create a simple Bash script to update the DNS record with your current IP.
    #!/bin/bash
    
    CLOUDFLARE_API_TOKEN="your_api_token_here"
    ZONE_ID="your_zone_id_here"
    DNS_RECORD_ID="your_record_id_here"
    DNS_RECORD_NAME="example.com"
    DNS_RECORD_TYPE="A"
    
    IP=$(curl -s http://ipv4.icanhazip.com)
    
    curl -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \
         -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
         -H "Content-Type: application/json" \
         --data '{
           "type": "'"$DNS_RECORD_TYPE"'",
           "name": "'"$DNS_RECORD_NAME"'",
           "content": "'"$IP"'",
           "ttl": 120,
           "proxied": false
         }'

    This script updates the DNS record with your current public IP. Replace the placeholders with your actual values.

    Bash Script to Update the DNS Record
    Bash Script to Update the DNS Record
  4. Enhance the Script to Update Only When Necessary: To avoid unnecessary updates, enhance the script to check if the IP address has changed before updating. Also update the full paths to any command within the script so it can run with cron.
    #!/bin/bash
    
    CLOUDFLARE_API_TOKEN="your_api_token_here"
    ZONE_ID="your_zone_id_here"
    DNS_RECORD_ID="your_record_id_here"
    DNS_RECORD_NAME="example.com"
    DNS_RECORD_TYPE="A"
    
    # Define the full paths to commands to be able run this script with cron
    CURL="/usr/bin/curl"
    JQ="/usr/bin/jq"
    
    # Get the current public IP address
    IP=$($CURL -s http://ipv4.icanhazip.com)
    
    # Cloudflare API endpoint to get the current DNS record
    GET_API_ENDPOINT="https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID"
    
    # Get the current DNS record's IP address from Cloudflare
    current_ip=$($CURL -s -X GET "$GET_API_ENDPOINT" \
         -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
         -H "Content-Type: application/json" | $JQ -r '.result.content')
    
    # Check if the IP addresses are different
    if [[ "$IP" == "$current_ip" ]]; then
      echo "No update needed. IP address has not changed: $IP"
    else
      echo "IP address has changed from $current_ip to $IP. Updating record..."
    
      # Cloudflare API endpoint to update the DNS record
      UPDATE_API_ENDPOINT="https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID"
    
      # Update the DNS record
      response=$($CURL -s -X PUT "$UPDATE_API_ENDPOINT" \
           -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
           -H "Content-Type: application/json" \
           --data '{
             "type": "'"$DNS_RECORD_TYPE"'",
             "name": "'"$DNS_RECORD_NAME"'",
             "content": "'"$IP"'",
             "ttl": 120,
             "proxied": false
           }')
    
      # Check if the update was successful
      if [[ $response == *"\"success\":true"* ]]; then
        echo "DNS record updated successfully to IP: $IP"
      else
        echo "Failed to update DNS record. Response: $response"
      fi
    fi

    This version of the script checks if the current IP is different from the IP in the DNS record. It updates the DNS record only if the IP has changed.

    Enhanced Script to Update DNS record Only When Necessary
    Enhanced Script to Update DNS record Only When Necessary
  5. Schedule the Script Using Cron: To keep your DNS record up to date automatically, schedule the script to run at regular intervals using cron.
    $ crontab -e
    # Add the following line to run the script every 5 minutes:
    */5 * * * * /path/to/update_dns.sh
    

    This will run the script every 5 minutes, ensuring that any change in your dynamic IP is promptly reflected in your DNS records.

Conclusion

By following these steps, you have created a reliable solution for keeping your domain pointed to your dynamic IP address. This script automates the process, eliminating the need for manual updates whenever your IP changes. With Cloudflare’s API and a little bash scripting, you can ensure that your domain is always reachable, no matter how often your IP changes. This setup is perfect for home servers, self-hosted services, or any scenario where a dynamic IP would otherwise cause headaches.



Comments and Discussions
Linux Forum