Introduction
Some hosting providers offer small VPS instances behind dynamic NAT without providing a DDNS service. In such cases, we need to set one up ourselves.
This is a beginner-friendly tutorial that utilizes Cloudflare. Before you begin, please ensure your domain is already managed by Cloudflare.
This script only implements DDNS for IPv4. On a side note, I’ve yet to encounter dynamic IPv6 addresses anyway.
Configure a Cloudflare API Token
Find Your Zone ID
Navigate to your domain’s dashboard on Cloudflare. On the right-hand side, scroll down to the API section and find your Zone ID. Make a note of it.

Create an API Token
Go to My Profile -> API Tokens.

Create a new API token with the following permissions:

Once created, make a note of your API Token.
Add an A Record
In your Cloudflare DNS panel, add a new A record. You can set its initial value to a placeholder like 1.1.1.1. The script will update it later.
Update the DNS Record and Configure Cron
The DDNS Script
Create a new script file and name it cf-ddns.sh (or any other name you prefer).
#!/bin/bash
# --- CONFIGURATION ---
# The Zone ID for your domain
ZONE_ID="your_zone_id_here"
# Your Cloudflare API Token
API_TOKEN="your_api_token_here"
# The full DNS record you want to update (e.g., home.example.com)
RECORD_NAME="home.example.com"
# --- END CONFIGURATION ---
# Get current public IP
IP=$(curl -s https://ipv4.icanhazip.com)
# Get the Record ID for the DNS record
RECORD_ID=$(curl -s -X GET \
"https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=A&name=$RECORD_NAME" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" | jq -r '.result[0].id')
# Update the DNS record with the new IP
RESPONSE=$(curl -s -X PATCH \
"https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$RECORD_NAME\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":false}")
# Log the response
echo "$(date): $RESPONSE"
Note: The script uses
jqto parse JSON. If you don’t have it installed, run:apt install jq -y.
Make the script executable: chmod +x /root/cf-ddns.sh
Run the script once to test it: ./cf-ddns.sh. If it’s successful, you should see a response containing "success":true.
Add a Cron Job
To run the script automatically, edit your crontab file:
crontab -e
Add the following line to run the script every five minutes and log the output:
*/5 * * * * /root/cf-ddns.sh >> /var/log/cf-ddns.log 2>&1
This example uses a 5-minute interval, but you can change it to every 2 minutes (*/2 * * * *) or another value if you wish.
After the script runs, you’ll see that the A record in your Cloudflare dashboard has been updated to your server’s current IP address.