-
-
Save heygambo/6a6180d62469002297b2ec63406b7d37 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# Cloudflare as Dynamic DNS | |
# From: https://letswp.io/cloudflare-as-dynamic-dns-raspberry-pi/ | |
# Based on: https://gist.github.com/benkulbertis/fff10759c2391b6618dd/ | |
# Original non-RPi article: https://phillymesh.net/2016/02/23/setting-up-dynamic-dns-for-your-registered-domain-through-cloudflare/ | |
# Fixed and documented version by Christian Gambardella (https://gambo.io) | |
# 1. Create a cloudflare account | |
# 2. Create a zone and a record with any ip address. | |
# It will be updated by the script. | |
# Just put 127.0.0.1 or so. | |
# 3. Create a token with those permissions: | |
# zone / zone / read | |
# zone / DNS / edit | |
# limit to all zones from your account or all zones. specific zones are not enough. | |
# 4. Update this script to include your zone name, record name and auth token. | |
# 5. Put it somewhere | |
# 6. Install a cronjob using `crontab -e` | |
# 7. Add line to update every 10 minutes: `*/10 * * * * /home/pi/cron/lwp-cloudflare-dyndns.sh` | |
# Update these with real values | |
auth_token="<auth-token-here>" | |
zone_name="domain.com" | |
record_name="home.domain.com" | |
# Don't touch these | |
ip=$(curl -s http://ipv4.icanhazip.com) | |
ip_file="ip.txt" | |
id_file="cloudflare.ids" | |
log_file="cloudflare.log" | |
# Keep files in the same folder when run from cron | |
current="$(pwd)" | |
cd "$(dirname "$(readlink -f "$0")")" | |
log() { | |
if [ "$1" ]; then | |
echo -e "[$(date)] - $1" >> $log_file | |
fi | |
} | |
log "Check Initiated" | |
if [ -f $ip_file ]; then | |
old_ip=$(cat $ip_file) | |
if [ $ip == $old_ip ]; then | |
log "IP has not changed." | |
exit 0 | |
fi | |
fi | |
if [ -f $id_file ] && [ $(wc -l $id_file | cut -d " " -f 1) == 2 ]; then | |
zone_identifier=$(head -1 $id_file) | |
record_identifier=$(tail -1 $id_file) | |
else | |
zone_identifier=$( curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" -H "Authorization: Bearer $auth_token" -H "Content-Type: application/json" | grep -Po '"id": *\K"[^"]*"' | head -1 | tr -d \" ) | |
record_identifier=$( curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?name=$record_name" -H "Authorization: Bearer $auth_token" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' ) | |
echo "$zone_identifier" > $id_file | |
echo "$record_identifier" >> $id_file | |
fi | |
echo "record: $record_identifier" | |
echo "zone: $zone_identifier" | |
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "Authorization: Bearer $auth_token" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\"}") | |
if [[ $update == *"\"success\":false"* ]]; then | |
message="API UPDATE FAILED. DUMPING RESULTS:\n$update" | |
log "$message" | |
echo -e "$message" | |
exit 1 | |
else | |
message="IP changed to: $ip" | |
echo "$ip" > $ip_file | |
log "$message" | |
echo "$message" | |
fi |
Hey, the script works like a charm for me, I just have a small problem. I have MX entries in Cloudflare that have the same name as the root record so sometimes it grabs the wrong ID. Would it be possible to edit the grep part of the curl request in a way that it also makes sure that it is a type A Record? I tried to wrap my head around the regex but couldn't figure it out since I have never one this before...
Hey there; thank you for the gist! I managed to get it to work but noticed that it would turn off the 'proxied' part on the setting exposing my servers' ip. To fix that I replaced the api call with this:
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "Authorization: Bearer $auth_token" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\",\"ttl\":\"1\",\"proxied\":\"true\"}")
With ttl set to 1 (auto)
Cool stuff! glad it works for you. I copied it from the other script. I've just adjusted it a bit.
I'm using it to host riot on my raspberry pi.
Dear sir,
How can i update for multi domain... More domain..
Thank you
I did a multidomain, multizone mashup of the script using jq, more info in the readme of the repo. Updates A and AAA records based on a list of domains you provide, domains not listed are ignored.
https://github.com/Chafalleiro/Server-scripts/blob/Server-scripts/DYNDNS_for_Cloudflare.sh
🎉
Thx for sharing 🎉
can anyone help with a line 27 syntax error?
File "lwp-cloudflare-dyndns.sh", line 27
ip=$(curl -s http://ipv4.icanhazip.com)
^
SyntaxError: invalid syntax
I've now switched to using this docker container:
version: "3"
services:
cloudflare-ddns:
image: oznu/cloudflare-ddns:latest
restart: unless-stopped
environment:
- API_KEY=<cloudflare-api-key>
- ZONE=example.com
- SUBDOMAIN=subdomain
- PROXIED=true
worked great for me - thanks!
Hey awesome! The Docker container still works well for me 😀
I've copied and pasted this script and have 2 crontabs running