Skip to content

Instantly share code, notes, and snippets.

@benscabbia
Created March 3, 2017 21:23
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save benscabbia/a6b158974219f96ecb1e87b97890c5fe to your computer and use it in GitHub Desktop.
Save benscabbia/a6b158974219f96ecb1e87b97890c5fe to your computer and use it in GitHub Desktop.
Cloudflare + Dynamic DNS (ddclient) = Super Awesome
# This guide will show you how to configure ddclient to dynamically update your DNS at Cloudflare.
# This cookbook makes use of a number of online guides - all of which I will reference at the end.
# Cloudflare requires ddclient to be version 3.8.2 or you will get a 'cloudflare protocol didn't exist'.
# Unfortunately, the package manager at this time makes use of 3.8.1
# My suggestion is to follow the semi-autonomous process, by downloading the out of date package
# and then manually update a few files. If you prefer, you can go down the fully manual route manual route.
# Installation - Manual (Not Tested: https://www.cloudflare.com/technical-resources/#ddclient)
# Installation - Semi-Autonomous (Recommended, follow below)
sudo apt-get update
sudo apt-get install ddclient libjson-any-perl
# The version should be 3.8.1, which does not support Cloudflare. Check version number by running the command below.
# Look for ...ddclient version 3.8.1
ddclient -h
# We manually upgrade the binary along with the configuration file. Check latest version: https://sourceforge.net/projects/ddclient/
# Download file:
wget http://downloads.sourceforge.net/project/ddclient/ddclient/ddclient-3.8.3.tar.bz2
# Extract
tar -jxvf ddclient-3.8.3.tar.bz2
# Copy the file from extracted directory and overwrite binary
sudo cp -f ddclient-3.8.3/ddclient /usr/sbin/ddclient
# From version 3.8.2 config file must be nested in a directory called ddclient, this is the final edit to our install:
# Move ddclient.conf in a directory called ddclient:
sudo mkdir /etc/ddclient
sudo mv /etc/ddclient.conf /etc/ddclient
# Awesome, we're almost there. Now just a little configuration. Navigate to directory and edit the config file:
cd /etc/ddclient.conf
sudo nano ddclient.conf
# Copy the configuration like below. The config assumes you have the domain 'gudthing.co.uk'
# Replace text in login, password, zone, and domain
protocol=cloudflare
use=web
server=www.cloudflare.com
ssl=yes
login=YOUR-EMAIL-ADDRESS@cloudflare.com
password=YOUR-GLOBAL-API-KEY-https://www.cloudflare.com/a/account/my-account
zone=gudthing.co.uk
gudthing.co.uk
# Once done, press CTRL + O to write the changes, and hit ENTER to confirm your want to overwrite file and then exit CTRL + X
# Good news, you are technically good to go! Test your setup by:
ddclient -daemon=0 -debug -verbose -noquiet
# Check the log and see if there are any messages. Most likely issues will be with config file, so update appropriately
# Now our DNS details will get updated everytime we run the command above. Pretty cool, but we can do better.
# Let's make it run every 5 minutes = 12 times an hour. We will do this via daemon, which will need another configuration file.
# Set the values to below:
sudo nano /etc/default/ddclient
run_ipup="false"
run_daemon="true"
daemon_interval=5000
# Make sure you set run_ipup to false, of it will cause problems.
# CTRL + O and then ENTER and lastly CTRL + X
# Configuration ready, now lets run the daemon:
sudo service ddclient start
sudo service ddclient status
# Optional - Create a cron job to force daily requirement
# So far we have setup ddclient to run every 5 minutes. Every 5 mins it will check our WAN address and if it has changed
# it will talk to Cloudflare and update our DNS. The issue is that if our DNS doesn't change for a few days, then cloudflare
# will not hear from our server which may cause timeout issues/drops in connection or fail to update when duty calls.
# With a cron job, we force a daily / weekly exchange:
cd etc/cron.daily
# create a file called ddclient with the following configuration
sudo nano /etc/cron.daily/ddclient
#!/bin/sh
/usr/sbin/ddclient -force
# Write, save and close file: CTRL + O, ENTER & CTRL + X
# The file we've just created is just a text file, lets make it executable:
sudo chmod +x /etc/cron.daily/ddclient
# You're done! Now you can have all the benefits from Cloudflare + [free] DDNS!
# API Key: https://www.cloudflare.com/a/account/my-account
# Binary: https://sourceforge.net/projects/ddclient/
# Resources:
# https://www.cloudflare.com/technical-resources/#ddclient
# https://jenssegers.com/84/dynamic-dns-for-cloudflare-with-ddclient
# https://samhobbs.co.uk/2015/01/dynamic-dns-ddclient-raspberry-pi-and-ubuntu
@willquill
Copy link

Thanks for making this! I noticed a few errors:

Line 33 should read: cd /etc/ddclient
Line 72 should read: cd /etc/cron.daily

@tpcr
Copy link

tpcr commented Mar 6, 2023

So how do you set the Proxy flag at Cloudflare?

@DiamondGamesInc
Copy link

I'm getting an error, and I can't seem to figure out why. Any idea?

rusty@DGI-tunnel:/run$ sudo service ddclient status
● ddclient.service - Update dynamic domain name service entries
Loaded: loaded (/lib/systemd/system/ddclient.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-06-23 21:28:11 UTC; 3min 23s ago
Docs: man:ddclient(8)
Process: 5682 ExecStart=/usr/sbin/ddclient -daemon $daemon_interval -syslog -pid /run/ddclient.pid (code=exited, status=0/SUCCESS)
Main PID: 5683 (ddclient - slee)
Tasks: 1 (limit: 38541)
Memory: 19.8M
CPU: 68ms
CGroup: /system.slice/ddclient.service
└─5683 "ddclient - sleeping for 100 seconds"

Jun 23 21:28:11 DGI-tunnel systemd[1]: Starting Update dynamic domain name service entries...
Jun 23 21:28:11 DGI-tunnel systemd[1]: ddclient.service: Can't open PID file /run/ddclient.pid (yet?) after start: Operation not permitted
Jun 23 21:28:11 DGI-tunnel systemd[1]: Started Update dynamic domain name service entries.

@willquill
Copy link

@DiamondGamesInc When Cloudflare makes changes to the API, ddclient is slow to adopt them. I was using ddclient in my plex-docker repository, but I replaced it with cloudflare-ddns here and I recommend you do the same if you exclusively use it with Cloudflare.

In that PR I linked, I add this to my README for cloudflare-ddns:

I use Cloudflare, but if you use something else for DDNS, you can swap it out for the ddclient Docker container. I used ddclient for a long time, but they were slow to adopt changes to the Cloudflare API, and I kept running into problems.

@DiamondGamesInc
Copy link

I use ProxMox and have a VM with Ubuntu 20.04 setup strictly to use for this. I tried to setup a tunnel via Cloudflared but it's so darn complex. I went through the steps many times, but each time It just fails to work. The tunnel was setup through their new "Zero Trust" system. I can't seem to get it to work as the A Record without a SubDomain. I've been pulling my hair out for this. The google searches, reddit posts, etc. mostly refer to the old way before they moved cloudflared to Zero Trust. It's been tough for me. Do you have any experience with it? I need the A name as the domain pointed to our private GitLab server. The problem is I'm going away for vacation next week and need to make sure the DNS gets updated while I'm gone if the IP changes.

@willquill
Copy link

@DiamondGamesInc I do not have experience with Cloudflare tunnels or Cloudflared. I do have experience with using cloudflare-ddns in Docker for DDNS.

If all you need is DDNS right now, then check out this section of my README: https://github.com/willquill/plex-docker#prepare-cloudflare-ddns

If you use Docker (highly recommend because it's easy) then use this config.json as your template: https://github.com/willquill/plex-docker/blob/main/config.json

And this is what you would put in your docker-compose.yaml file (also have a .env file in the same directory as docker-compose.yaml that maps those two environment variables to the correct PUID and PGID for your user, usually 1000 but can vary). Or just hardcode the values.:

  cloudflare-ddns:
    image: timothyjmiller/cloudflare-ddns:latest
    container_name: cloudflare-ddns
    security_opt:
      - no-new-privileges:true
    network_mode: 'host'
    environment:
      - PUID=$DOCKERUSERNAME
      - PGID=$DOCKERUSERGROUP
    volumes:
      - ./config/cloudflare-ddns/config.json:/config.json
    restart: unless-stopped

@helsan74
Copy link

helsan74 commented Mar 4, 2024

Thanks.
Is there a way to also update multiple subdomains?

@willquill
Copy link

Is there a way to also update multiple subdomains?

Configure it to update only a single subdomain - say it's "ddns.domain.com". Then create CNAME records that point to "ddns".

Example:

  • Cloudflare only updates ddns.domain.com
  • You have CNAMEs called "foo" and "bar" that point to ddns.domain.com.
  • Now if anyone goes to foo.domain.com or bar.domain.com, they'll go to the same IP associated with ddns.domain.com, which is dynamically updated via cloudflare-ddns.

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