-
-
Save lyoshenka/6257440 to your computer and use it in GitHub Desktop.
Quick and dirty DDNS using Bash and Cloudflare (API v4 compatible)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Step 1: Fill in EMAIL, TOKEN, DOMAIN and SUBDOMAIN. Your API token is here: https://dash.cloudflare.com/profile/api-tokens | |
# Make sure the token is the Global token, or has these permissions: #zone:read, #dns_record:read, #dns_records:edit | |
# If you want to set the root domain instead of a subdomain, set SUBDOMAIN to "@" | |
# Step 2: Create an A record on Cloudflare with the subdomain you chose | |
# Step 3: Run "./ddns.sh -l" to get the zone_id and rec_id of the record you created. | |
# Fill in ZONE_ID and REC_ID below | |
# This step is optional, but will save you 2 requests every time you run this script | |
# Step 4: Run "./ddns.sh". It should tell you that record was updated or that it didn't need updating. | |
# Step 5: Run it every hour with cron. Use the '-s' flag to silence normal output | |
# 0 * * * * /path/to/ddns.sh -s | |
EMAIL='' | |
TOKEN='' | |
DOMAIN='' | |
SUBDOMAIN='' | |
ZONE_ID='' | |
REC_ID='' | |
set -euo pipefail | |
VERBOSE="true" | |
LOOKUP="false" | |
while getopts ":lsd" opt; do | |
case ${opt} in | |
l ) LOOKUP="true" ;; | |
s ) VERBOSE="false" ;; | |
d ) set -x ;; # for debugging | |
\? ) echo -e "Usage: $(basename "$0") [-l] [-s] [-d]\nRead the script source for detailed instructions" && exit 1 ;; | |
esac | |
done | |
[[ "$SUBDOMAIN" = "@" ]] && FULL_DOMAIN="$DOMAIN" || FULL_DOMAIN="$SUBDOMAIN.$DOMAIN" | |
API_URL="https://api.cloudflare.com/client/v4" | |
CURL="curl -s \ | |
-H Content-Type:application/json \ | |
-H X-Auth-Key:$TOKEN \ | |
-H X-Auth-Email:$EMAIL " | |
if [ -z "$ZONE_ID" ] || $LOOKUP; then | |
ZONE_ID="$($CURL "$API_URL/zones?name=$DOMAIN" | sed -e 's/[{}]/\n/g' | grep '"name":"'"$DOMAIN"'"' | sed -e 's/,/\n/g' | grep '"id":"' | cut -d'"' -f4)" | |
$VERBOSE && echo "ZONE_ID='$ZONE_ID'" | |
fi | |
if [ -z "$REC_ID" ] || $LOOKUP; then | |
#REC_ID="$($CURL "$API_URL/zones/$ZONE_ID/dns_records" | grep -C 5 '"name": "'"$FULL_DOMAIN"'"' | grep '"id": "' | cut -d'"' -f4)" | |
REC_ID="$($CURL "$API_URL/zones/$ZONE_ID/dns_records" | sed -e 's/[{}]/\n/g' | grep '"name":"'"$FULL_DOMAIN"'"' | sed -e 's/,/\n/g' | grep '"id":"' | cut -d'"' -f4)" | |
$VERBOSE && echo "REC_ID='$REC_ID'" | |
fi | |
$LOOKUP && exit 0 | |
set +e | |
for IP_URL in "http://ifconfig.me/ip" "http://ipv4.icanhazip.com"; do | |
IP="$(curl -s "$IP_URL")" | |
[ -n "$IP" ] && break | |
done | |
set -e | |
if [ -z "$IP" ]; then | |
echo "Could not get external IP" | |
exit 1 | |
fi | |
RECORD_IP="$($CURL "$API_URL/zones/$ZONE_ID/dns_records/$REC_ID" | grep -o '"content":"[^"]\+' | cut -d '"' -f4)" | |
if [ "$IP" == "$RECORD_IP" ]; then | |
$VERBOSE && echo "IP Unchanged" | |
exit 0 | |
fi | |
$VERBOSE && echo "Setting IP to $IP" | |
$CURL -X PUT "$API_URL/zones/$ZONE_ID/dns_records/$REC_ID" --data '{"type":"A","name":"'"$SUBDOMAIN"'","content":"'"$IP"'","proxied":false}' 1>/dev/null | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, i'm trying to get it working with monit but unfortunatelly looks like monit doesn't run the script btw when i run it myself everything works.
Do you have any idea ?
Perhaps there is my command on monit