Skip to content

Instantly share code, notes, and snippets.

@federicociro
Last active December 27, 2022 22:04
Show Gist options
  • Save federicociro/f5058f12cafa5757306f81549e5f584c to your computer and use it in GitHub Desktop.
Save federicociro/f5058f12cafa5757306f81549e5f584c to your computer and use it in GitHub Desktop.
Bash script to update DNS records in Cloudflare if local IP changed
[Unit]
Description=Cloudflare always up to date DNS daemon.
Documentation=https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
[Service]
Type=simple
ExecStart=/usr/local/bin/cloudflare-ddns.sh
StandardOutput=file:/var/log/cloudflare-ddns.log
[Install]
WantedBy=default.target
[Unit]
Description=Check DNS records every 5 minutes
RefuseManualStart=no # Allow manual starts
RefuseManualStop=no # Allow manual stops
[Timer]
#Execute job if it missed a run due to machine being off
Persistent=true
#Run 120 seconds after boot for the first time
OnBootSec=120
#Run every 5 minute thereafter
OnUnitActiveSec=300
#File describing job to execute
Unit=cloudflare-ddns.service
[Install]
WantedBy=timers.target
#!/bin/sh
# Source: https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details
#Set values below
USER="domain.tld"
GLOBAL_KEY="global_key"
ZONE_ID="zone_id"
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Content-Type:application/json" \
-H "X-Auth-Key:$GLOBAL_KEY" \
-H "X-Auth-Email:$USER" \
-H "Content-Type: application/json"
#!/bin/bash
# Use set -eu at the beginning of the script to exit immediately if any command in the script returns a non-zero exit code, or if any uninitialized variables are used. This can help prevent errors from being overlooked.
set -eu
AUTH_EMAIL="example@domain.tld"
AUTH_KEY="cloudflare_auth_key"
# Domain 1
# Domain name
A_RECORD_NAME1="domain1.com"
# Zone Id unique for each domain
ZONE_ID1="zoneid1"
# Get this through a script: cloudflare-get-record-id.sh
# Source: https://api.cloudflare.com/#getting-started-requests
A_RECORD_ID1="recordid1"
# Domain 2
# Domain name
A_RECORD_NAME2="domain2.com"
# Zone Id unique for each domain
ZONE_ID2="zoneid2"
A_RECORD_ID2="recordid2"
# Retrieve the last recorded public IP address
touch /tmp/ip-record
IP_RECORD="/tmp/ip-record"
RECORDED_IP=`cat $IP_RECORD`
# Log date
NOW=$(date -u +"%Y-%m-%d %H:%M:%S %Z")
# Fetch the current public IP address
PUBLIC_IP=$(dig +short myip.opendns.com @resolver1.opendns.com) || exit 1
# Alternative
#PUBLIC_IP=$(curl --silent https://api.ipify.org) || exit 1
#If the public ip has not changed, nothing needs to be done, exit.
if [ "$PUBLIC_IP" = "$RECORDED_IP" ]; then
echo $NOW " | Actual Public IP is: $PUBLIC_IP | Public IP is still OK."
exit 0
fi
# Otherwise, your Internet provider changed your public IP again.
# Record the new public IP address locally
echo $PUBLIC_IP > $IP_RECORD
# Record the new public IP address on Cloudflare using API v4
echo $NOW "Posting new Public IP to Cloudflare DNS.."
echo ""
echo "Changing DNS for domain1"
RECORD1=$(cat <<EOF
{ "type": "A",
"name": "$A_RECORD_NAME1",
"content": "$PUBLIC_IP",
"ttl": 180,
"proxied": true }
EOF
)
# NOT WORKING YET - ONLY GLOBAL KEY - Check API for authentication with tokens: https://api.cloudflare.com/#getting-started-requests
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID1/dns_records/$A_RECORD_ID1" \
-X PUT \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $AUTH_EMAIL" \
-H "X-Auth-Key: $AUTH_KEY" \
-d "$RECORD1"
echo ""
echo "Changing DNS for domain2"
RECORD2=$(cat <<EOF
{ "type": "A",
"name": "$A_RECORD_NAME2",
"content": "$PUBLIC_IP",
"ttl": 180,
"proxied": true }
EOF
)
# Update the record to Cloudflare
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID2/dns_records/$A_RECORD_ID2" \
-X PUT \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $AUTH_EMAIL" \
-H "X-Auth-Key: $AUTH_KEY" \
-d "$RECORD2"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment