Skip to content

jmrplens/Cloudflare-DNS-Updater

Repository files navigation

FOSSA Status codecov Unit and Coverage test

1. Dynamic DNS - Cloudflare

Bash script to update IPv4 and IPv6 records in Cloudflare. Update with WAN or LAN IP.

1.1. Real life example

Result Settings
Screenshot of Termius (9-6-23, 01-13-49)
domains:
    - name: jmrp.dev
      ip_type: external
      ipv4: true
      ipv6: true
      proxied: true
      ttl: auto
    - name: git.jmrp.dev
      ip_type: external
      ipv4: true
      ipv6: true
      proxied: true
      ttl: auto
    - name: jenkins.jmrp.dev
      ip_type: external
      ipv4: true
      ipv6: true
      proxied: true
      ttl: auto

settings:
    cloudflare:
        - zone_id: #########
        - zone_api_token: ########
    misc:
        - create_if_no_exist: false

notifications:
    telegram:
        enabled: false
        bot_token: token
        chat_id: id

1.2. About

  • Bash Script for most Linux, Unix distributions and MacOS.
  • Choose any source IP address to update external or internal (WAN/LAN) for ech domain.
  • For multiply lan interfaces like Wifi, Docker Networks and Bridges the script will automatically detects the primary Interface by priority.
  • Cloudflare's options proxy and TTL configurable via the config file for each domain.
  • Optional Telegram Notifications

1.3. Requirements

  • curl
  • Cloudflare api-token with ZONE-DNS-EDIT Permissions
  • DNS Record must be pre created in web interface (WIP: Create record if no exist)

Creating Cloudflare API Token

To create a CloudFlare API token for your DNS zone go to cloudflare-api-token-url and follow these steps:

  1. Click Create Token
  2. Select Create Custom Token
  3. Provide the token a name, for example, example.com-dns-zone-readonly
  4. Grant the token the following permissions:
    • Zone - DNS - Edit
  5. Set the zone resources to:
    • Include - Specific Zone - example.com
  6. Complete the wizard and use the generated token at the CLOUDFLARE_API_TOKEN variable for the container

1.4. Installation

You can place the script at any location manually.

MacOS: Don't use the /usr/local/bin/ for the script location. Create a separate folder under your user path /Users/${USER}

The automatic install examples below will place the script at /usr/local/bin/

wget https://raw.githubusercontent.com/jmrplens/DyDNS_Cloudflare_IPv4-6/main/cloudflare-dns.sh
sudo chmod +x cloudflare-dns.sh
sudo mv cloudflare-dns.sh /usr/local/bin/cloudflare-dns

1.5. Configuration file

You can use default config file cloudflare-dns.yaml or pass your own config file as parameter to script.

wget https://raw.githubusercontent.com/jmrplens/DyDNS_Cloudflare_IPv4-6/main/cloudflare-dns.yaml

Place the config file in the directory as the update-cloudflare-dns for above example at /usr/local/bin/

sudo mv cloudflare-dns.yaml /usr/local/bin/cloudflare-dns.yaml

Edit it with your favorite editor and set the necessary parameters.

1.6. Configuration Parameters

domains:
  - name: example.com
    ip_type: external
    ipv4: true
    ipv6: true
    proxied: true
    ttl: auto

settings:
  cloudflare:
    - zone_id: #########
    - zone_api_token: ########
  misc:
    - create_if_no_exist: false

notifications:
  telegram:
    enabled: false
    bot_token: token
    chat_id: id

Multiple domains is supported:

domains:
  - name: example.com
    ip_type: external
    ipv4: true
    ipv6: true
    proxied: true
    ttl: auto
  - name: example2.com # Only name = using default settings
  - name: example3.com
    ip_type: external
    ipv4: true
    ipv6: true
    proxied: false
    ttl: auto
  - name: ..........
.........

Domains

Option Example Description
name example.com Domain name. Required
ip_type external Which IP should be used for the record: internal/external. Optional (default: external)
ipv4 true Update IPv4 DNS Record: true/false. Optional (default: true)
ipv6 true Update IPv6 DNS Record: true/false. Optional (default: true)
proxied true Use Cloudflare proxy on dns record: true/false. Optional (default: true)
ttl 3600 120-7200 in seconds or auto. Optional (default: auto)

Cloudflare

Option Example Description
zone_api_token token Cloudflare API Token KEEP IT PRIVATE!!!!
zone_id id Cloudflare's Zone ID
Cloudflare misc
Option Example Description
create_if_no_exist false Not yet implemented

Notifications

Telegram
Option Example Description
enabled true Use Telegram notifications: true/false.
bot_token token Telegram's Bot API Token
chat_id id Chat ID of the bot

1.7. Running The Script

When placed in /usr/local/bin/

cloudflare-dns dyndns-update

With your config file (need to be placed in same folder)

cloudflare-dns dyndns-update your_config.yaml

1.8. Automation With Crontab

You can run the script via crontab

crontab -e

Examples

Example Code
Run every minute
* * * * * /usr/local/bin/cloudflare-dns dyndns-update
Run every minute with your specific config file
* * * * * /usr/local/bin/cloudflare-dns dyndns-update myconfig.yaml
Run every every 2 minutes
*/2 * * * * /usr/local/bin/cloudflare-dns dyndns-update
Run at boot
@reboot /usr/local/bin/cloudflare-dns dyndns-update
Run 1 minute after boot
@reboot sleep 60 && /usr/local/bin/cloudflare-dns dyndns-update

1.9. Logs

This Script will create a log file with only the last run information Log file will be located at the script's location.

Example:

/usr/local/bin/cloudflare-dns.log

2. Information for Developers

2.1. Units Test y Code Coverage

The bats framework is used to perform the unit tests. In addition, if you want to obtain the Code Coverage you use bashcov.

To run them locally:

  1. Clone this repository and update the submodules:

    git clone https://github.com/jmrplens/DynDNS_Cloudflare_IPv4-6.git
    cd DynDNS_Cloudflare_IPv4-6
    git submodule update --init --recursive
  2. Execute the tests:

    • Without code coverage:

      # Path: ../DynDNS_Cloudflare_IPv4-6/
      ./unit_test.sh
    • With code coverage:

      1. With Ruby 3 or higher, install the dependencies:

        # Path: ../DynDNS_Cloudflare_IPv4-6/
        gem install bundler
        export BUNDLE_GEMFILE=test/Gemfile
        bundle install
      2. Execute tests with code coverage:

        # Path: ../DynDNS_Cloudflare_IPv4-6/
        bashcov ./unit_test.sh

2.2. Github CI (actions)

Here we describe how the Github CI workflows for unit testing and code coverage work.


2.2.1. Workflow


%%{
  init: {
    "fontFamily": "monospace",
    "flowchart": {
      "htmlLabels": true
    },
    "sequence": {}
  }
}%%

flowchart LR
subgraph WC[Main Workflow]
    A(<b>Unit Test and Coverage</b>\n <i><small><a href='https://github.com/jmrplens/DynDNS_Cloudflare_IPv4-6/blob/main/.github/workflows/test_cov_main.yaml'>test_cov_main.yaml</a></small></i>)
    A --> B[Matrix strategy\n\n<table><tr><td align='left'><b>OS&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbspRUBY</b></td><td>&nbsp3.0&nbsp</td><td style='background-color:'>&nbsp3.1&nbsp</td><td>&nbsp3.2&nbsp</td><td>&nbsp3.3&nbsp</td></tr><tr style='color:brown'><td>Ubuntu 22.04&nbsp&nbsp&nbsp&nbsp&nbsp</td><td>&#x2022</td><td>&#x2022</td><td>&#x2022</td><td>&#x2022</td></tr><tr style='color:darkviolet'><td align='left'>Debian 12&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp</td><td>&#x2022</td><td>&#x2022</td><td>&#x2022</td><td>&#x2022</td></tr><tr style='color:darkorange'><td align='left'>Mac OS 14&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp</td><td>&#x2022</td><td>&#x2022</td><td>&#x2022</td><td>&#x2022</td></tr></table>\n]
    B ==>C[Call a worker for each combination]
    linkStyle 1 stroke-width:2px,stroke:red;

end

C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU
C -->WU

subgraph WU[Reusable Workflow]
    D[<b>Worker to run the tests and coverage</b>\n<i><small><a href='https://github.com/jmrplens/DynDNS_Cloudflare_IPv4-6/blob/main/.github/workflows/test_cov_worker.yaml'>test_cov_worker.yaml</a></small></i>]
    D --> E[Checkout repository with submodules]
    E --> F[Build/Install Ruby and the needed Gems\n<i><small><a href='https://github.com/jmrplens/DynDNS_Cloudflare_IPv4-6/blob/main/test/Gemfile'>test/Gemfile</a></small></i>]
    F --> G[Run unit test with coverage\n<small><code>bashcov ./unit-test.sh</code></small>]
    G --> H[Upload coverage reports to:\n<a href='https://app.codecov.io/github/jmrplens/DynDNS_Cloudflare_IPv4-6'>Codecov</a> and <a href='https://app.codacy.com/gh/jmrplens/DynDNS_Cloudflare_IPv4-6/dashboard'>Codacy</a>]
end
Loading

2.2.2. Self-hosted runners

To run the Github CI on Debian, self-hosted runners are used.

For Debian operating systems it is necessary to manually install the Ruby versions that will run the tests. This is required:

  1. Install self-hosted runner.

  2. Install ruby-build. Follow the instructions in Install manually as a standalone program.

  3. Assuming you have used the default work folder name _work , you must install the Ruby versions to be run in the runner into that folder:

    ruby-build X.Y.Z ACTION_RUNNER_PATH/_work/_tool/Ruby/X.Y.Z/x64

    Where X.Y.Z is the Ruby version you want to install (3.0.6, 3.1.4, ...).

    And mark it as completed with:

    touch /root/actions-runner/_work/_tool/Ruby/X.Y.Z/x64.complete

    Where X.Y.Z is the Ruby version you have installed (3.0.6, 3.1.4, ...).

3. More info

3.1. Code Quality

Codacy Badge CodeFactor Shellcheck CircleCI

3.2. Code Coverage

Codacy Badge codecov

3.3. License

FOSSA Status