Skip to content

Instantly share code, notes, and snippets.

@grenade
Last active February 7, 2024 07:21
Show Gist options
  • Save grenade/012c993e16aef34297653b71199aef33 to your computer and use it in GitHub Desktop.
Save grenade/012c993e16aef34297653b71199aef33 to your computer and use it in GitHub Desktop.
diy dynamic dns - sync cloudflare domain name with dynamic ip address every 60 seconds
[Unit]
Description=dns ip sync
Wants=network-online.target
After=network-online.target
AssertPathExists=/etc/dns-ip-sync.json
[Service]
Type=simple
ExecStartPre=curl \
--silent \
--location \
--output /usr/local/bin/dns-ip-sync.sh \
--url https://gist.githubusercontent.com/grenade/012c993e16aef34297653b71199aef33/raw/dns-ip-sync.sh?$(uuidgen)
ExecStartPre=chmod +x /usr/local/bin/dns-ip-sync.sh
ExecStart=/usr/local/bin/dns-ip-sync.sh
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
#!/bin/bash
dns_resolver=1.1.1.1
public_ip_url=https://checkip.amazonaws.com
ip_address_pattern="^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$"
cloudflare_dns_zone_id=$(jq -r .cloudflare.dns.zone.id /etc/dns-ip-sync.json)
cloudflare_dns_zone_name=$(jq -r .cloudflare.dns.zone.name /etc/dns-ip-sync.json)
cloudflare_dns_record_id=$(jq -r .cloudflare.dns.record.id /etc/dns-ip-sync.json)
cloudflare_dns_record_name=$(jq -r .cloudflare.dns.record.name /etc/dns-ip-sync.json)
cloudflare_api_token=$(jq -r .cloudflare.api.token /etc/dns-ip-sync.json)
observed_public_ip=$(curl -s -X GET ${public_ip_url})
if [[ ! ${observed_public_ip} =~ ${ip_address_pattern} ]]; then
echo "failed to observe public ip address at: ${public_ip_url}"
unset observed_public_ip
exit 1
else
echo "public ip address observed as: ${observed_public_ip}, at: ${public_ip_url}"
if host ${cloudflare_dns_record_name} ${dns_resolver} | grep 'has address' | grep ${observed_public_ip}; then
echo "${cloudflare_dns_record_name} resolves to ${observed_public_ip}"
exit
else
if [ -z ${cloudflare_dns_zone_id+x} ]; then
cloudflare_dns_zone_id=$(curl \
--silent \
--request GET \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${cloudflare_api_token}" \
--url "https://api.cloudflare.com/client/v4/zones?name=${cloudflare_dns_zone_name}&status=active" \
| jq -r '.result[0].id')
fi
if [ -z ${cloudflare_dns_zone_id+x} ]; then
echo "failed to obtain cloudflare dns zone id for zone: ${cloudflare_dns_zone_name}"
exit 1
fi
if [ -z ${cloudflare_dns_record_id+x} ]; then
cloudflare_dns_record_id=$(curl \
--silent \
--request GET \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${cloudflare_api_token}" \
--url "https://api.cloudflare.com/client/v4/zones/${cloudflare_dns_zone_id}/dns_records?type=A&name=${cloudflare_dns_record_name}" \
| jq -r '.result[0].id')
fi
if [ -z ${cloudflare_dns_record_id+x} ]; then
echo "failed to obtain cloudflare dns record id for record: ${cloudflare_dns_record_name}, in zone: ${cloudflare_dns_zone_name} (${cloudflare_dns_zone_id})"
exit 1
fi
if curl \
--silent \
--request PUT \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${cloudflare_api_token}" \
--data "{\"type\":\"A\",\"name\":\"${cloudflare_dns_record_name}\",\"content\":\"${observed_public_ip}\",\"ttl\":1,\"proxied\":false}" \
--url "https://api.cloudflare.com/client/v4/zones/${cloudflare_dns_zone_id}/dns_records/${cloudflare_dns_record_id}"; then
echo "${cloudflare_dns_record_name} A record set to ${observed_public_ip} in zone: ${cloudflare_dns_zone_name} (${cloudflare_dns_zone_id}), record: ${cloudflare_dns_record_name} (${cloudflare_dns_record_id})"
fi
fi
fi
@grenade
Copy link
Author

grenade commented May 20, 2022

install

  • prerequisites

    # fedora
    sudo dnf install curl jq
    
    # ubuntu
    sudo apt install curl jq
  • download systemd unit file

    sudo curl -sL \
      -o /etc/systemd/system/dns-ip-sync.service \
      https://gist.githubusercontent.com/grenade/012c993e16aef34297653b71199aef33/raw/dns-ip-sync.service
  • insert secrets and configuration

    # set cloudflare_api_token
    cloudflare_api_token=secret
    sudo sed -i "s/f6c29d04b0ae425293f855831d12ff12/${cloudflare_api_token}/" /etc/systemd/system/dns-ip-sync.service
    
    # set cloudflare_dns_record
    cloudflare_dns_record=office.bananas.com
    sudo sed -i "s/home.example.com/${cloudflare_dns_record}/" /etc/systemd/system/dns-ip-sync.service
    
    # set cloudflare_dns_zone
    cloudflare_dns_zone=bananas.com
    sudo sed -i "s/example.com/${cloudflare_dns_zone}/" /etc/systemd/system/dns-ip-sync.service
  • enable and start service

    sudo systemctl enable --now dns-ip-sync.service
  • tail service logs

    journalctl -u dns-ip-sync.service -f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment