Dynamic DNS service based on Cloudflare! Access your home network remotely via a custom domain name without a static IP!
Cloudflare DDNS allows you to run your own Dynamic DNS service from the comfort of your own infrastructure. Combined with a Raspberry PI or whatever spare hardware you still have lying around, it helps promote a more decentralized internet at a low cost. During execution, it resolves your current public IPv4 and IPv6 addresses and creates/updates DNS records in Cloudflare to point to your home address. It keeps track of any DNS records that it is managing, giving you some peace of mind and allowing it to run in non-empty Cloudflare zones without having to worry that your public blog gets taken down. Any stale or duplicate records will get safely cleaned up.
Download .NET Core 3.1 or newer. Once installed, run this command:
dotnet tool install --global cloudflare-ddns
Setup your dns records and use the following to start syncing your public ip to cloudflare
cloudflare-ddns
It's advised to run this program at repeated intervals. The following will walk you through setting up a recurring task on Windows and Linux:
On Linux you can leverage crontab to schedule this command at a recurring interval:
-
Create a config file somewhere on your distro.
-
Run the following code in terminal, this will launch your default editor with the crontab config file
crontab -e
- Add the following lines to sync your DNS records every 15 minutes
*/15 * * * * cloudflare-ddns -c /path/to/your/config-file/config.json
This will schedule a cronjob and makes sure your DNS is synced every 15 minutes.
-
Create a config file somewhere on your distro.
-
Open
Task Scheduler
and create a task. -
In General tab check
Run whether user is logged on or not
-
In Triggers tab check
Repeat task every
and select5 min
. -
In Action tab add an action.
- the
program
isC:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- the
arguments
iscloudflare-ddns
- the
start in
is where your config file location in step 1.
- the
-
Click OK and wait last result become
0x0
. if not,check config andcloudflare-ddns
command works ok in powershell.
A helm chart is available in the charts
folder, for more information about the available values, have a look at the README inside the chart. For helm deployments you don't need to provide a config.json
, this will get generated for you. At the moment there is no helm install
available yet, this is on my TO-DO list though. To get started with helm clone the repository or copy over the files in the charts folder.
To authenticate you will need to create a Cloudflare API token, traditional API keys are not supported! To generate a new API token, go to your Cloudflare Profile and create a token capable of Edit DNS. There are 2 ways you can provide this API token:
- Add an environment variable
CLOUDFLARE_API_TOKEN
with the value of your token. - Add an
apiToken
key at the root of your config.json.
The tool can be configured with a config.json
file which by default will get picked up at the cwd. It's also possible to change the path or name to the configuration file via -c
or --config
. A minimal valid config file looks as follows:
{
"records": [
{
"zoneId": "<cloudflare_zone_id>",
"subdomain": "<subdomain_name>",
"proxied": true
},
...
]
}
For a minimal valid configuration, all you need to define are the records which you would like to sync. But there are a few more options available to play with:
{
"apiToken": "<cloudflare_api_token>",
"ipv4": true,
"ipv6": true,
"resolvers": {
"http": {
"ipv4Endpoint": "https://api.ipify.org",
"ipv6Endpoint": "https://api6.ipify.org"
},
"dns": "cloudflare",
"order": [
"http",
"dns"
]
},
"records": [
{
"zoneId": "<cloudflare_zone_id>",
"subdomain": "<subdomain_name>",
"proxied": true
},
{
"zoneId": "<cloudflare_zone_id>",
"subdomain": "<subdomain_name>",
"proxied": false
},
...
]
}
Config:
Key | Type | Default | Description |
---|---|---|---|
apiToken | string | "" |
Prefer using CLOUDFLARE_API_TOKEN environment variable instead!! Cloudflare API token required to talk to the Cloudflare REST API, traditional API keys are not supported! Make sure this token has the correct permissions for each zone that it needs to create a record. Have a look at the Authentication section! |
ipv4 | bool | true |
Determines if public ipv4 should get resolved. |
ipv6 | bool | true |
Determines if public ipv6 should get resolved. |
resolvers.http.ipv4Endpoint | string | "https://api.ipify.org" |
HTTP REST endpoint for HTTP resolver to determine public ipv4 address. |
resolvers.http.ipv6Endpoint | string | "https://api6.ipify.org" |
HTTP REST endpoint for HTTP resolver to determine public ipv6 address. |
resolvers.dns | string | "cloudflare" |
DNS nameserver to use to resolve public ipv4 or/and ipv6 addresses. Supported servers are cloudflare and google . |
resolvers.order | list | ["http", "dns"] |
Determines the order in which resolvers will be used. By default, it will first try to resolve an IP via HTTP and fallback to DNS. It's possible to change the order and even leave out a specific resolver if you for example only want to resolve over HTTP. An empty list is not supported! |
resources | object | {} |
|
records | list | [] |
List of subdomains to sync in a given Cloudflare zone eg. |
Record:
Key | Type | Default | Description |
---|---|---|---|
zoneId | string | "" |
The ID of the zone where the DNS record will be configured. From your dashboard click into the zone. Under the review tab, scroll down and the zone ID is listed on the right. |
subdomain | string | "" |
The subdomain you want to update with an A or AAAA record. IMPORTANT: Only write the subdomain name, do not include the base this is inferred from the zone. (eg foo or an empty string to update the base domain) |
proxied | bool | false |
Determines whether requests get proxied through Cloudflare. (This usually disables SSH). |
You can use --help
to get an overview of accepted arguments:
cloudflare-ddns: 0.3.0
Cloudflare DDNS
Usage: cloudflare-ddns [options]
Options
-c, --config Path to the config.json file, defaults to the
current working directory.
-l, --log-level=VALUE Set the log level (verbose, info, warning, error),
defaults to info
-v, --version Show current version.
-?, -h, --help Show help information
-c
or--config
allows configuring the path to the config.json file. By default, the tool will look in the current directory for this file.-l
or--log-level
allows changing the verbosity of the tool. By default, it set to info.
Yes, you most definitely can. The specification is fairly simple, a successful response should return a 200 status code with the IP address as plain text. Any other status code will get interpreted as an error and thus ignored. There is no example of a resolver at the moment, but one for azure functions is coming soon π.
You can save yourself some trouble when hosting multiple domains pointing to the same IP address (in the case of Traefik) by defining one A & AAAA record 'ddns.example.com' pointing to the IP of the server that will be updated by this DDNS script. For each subdomain, create a CNAME record pointing to 'ddns.example.com'. Now you don't have to manually modify the script config every time you add a new subdomain to your site!
When running in verbose mode you will get a richer logging experience. And thus will see lines telling you if it can't resolve an IPv4 or IPv6 address.
If you are running in an environment that only uses IPv4 (for example docker or a default k8s setup). Then you won't be able to resolve your public IPv6 address and that's why you will see these error messages. If you for certain know that you can't resolve IPv6 in your environment or don't need your public IPV6 to be synced, then you can turn this off in your config.json
file:
{
...
"ipv6": false,
...
}
Copyright 2020 Nick Van Dyck
MIT