Here's a quick Github Action a prompt blurted to periodically backup a Cloudflare DNS settings for all my domains and commit them into the repository. Zero maintenance required once set up:
name: Cloudflare DNS Backup
on:
workflow_dispatch:
schedule:
- cron: "40 0 * * 0"
jobs:
backup:
runs-on: ubuntu-22.04
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- run: |
# Create backup directory
mkdir -p dns-backups
# Get list of zones (domains)
zones=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | jq -r '.result[].id')
# Loop through zones and backup DNS records
for zone in $zones; do
# Get zone name
zone_name=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | jq -r '.result.name')
echo "Backing up DNS records for $zone_name"
# Get DNS records and save to file
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone/dns_records" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | jq > "dns-backups/$zone_name.json"
done
- uses: stefanzweifel/git-auto-commit-action@v5
After setting up, Cloudflare DNS backups will be created in folder
dns-backups/domain.tld.jsom
. The setup itself however is a bit of a magic
so I provided a lot of detailed steps to make sure it is possible to
replicate this in the future.
Instructions#
- Obtain Cloudflare API token
- Add this token to your Github repository as a secret named
CLOUDFLARE_API_TOKEN
- Enable Github actions write permissions, as this creates automatic commits
- The backup will run manually every Sunday early in the morning, adjust
schedule
in.github/workflow/main.yml
if needed
Cloudflare API token#
Here's how to create a Cloudflare API token with minimal permissions for read-only DNS access:
- Log in to your Cloudflare dashboard at https://dash.cloudflare.com/
- Click on your profile icon in the top-right corner and select "My Profile"
- In the left sidebar, click on "API Tokens"
- Click the "Create Token" button
- Select "Create Custom Token"
- Set a descriptive name like "DNS Backup Read-Only"
- Under "Permissions" section:
- Select "Zone" from the first dropdown
- Select "DNS" from the second dropdown
- Select "Read" from the third dropdown
- Under "Zone Resources" section:
- Select "Include" from the first dropdown
- Select "All zones" from the second dropdown
- (Alternatively, you can select "Specific zone" if you want to limit to certain domains)
- Set an expiration date if desired (optional, for added security)
- Click "Continue to summary"
- Review the permissions and click "Create Token"
- Copy the generated token immediately (it will only be shown once)
This token has the absolute minimum permissions needed - it can only read DNS records and cannot make any changes to your configuration. It follows the principle of least privilege, which is a security best practice.
Adding Github Secrets#
Github Secrets allow you to store sensitive information like API tokens securely. Follow these steps to add your Cloudflare API token as a secret.
- Go to your Github repository in your browser Click on the "Settings" tab in the top navigation bar (near the right side)
- In the left sidebar, scroll down to the "Security" section Click on "Secrets and variables" Select "Actions" from the dropdown menu
- Click the "New repository secret" button Enter the secret name exactly as referenced in your workflow:
- Enter CLOUDFLARE_API_TOKEN in the "Name" field
- Paste your Cloudflare API token in the "Secret" field Click "Add secret" to save
- You should now see CLOUDFLARE_API_TOKEN listed in your repository secrets The value will be hidden and displayed as "●●●●●●●●" The secret is now available to your Github Actions workflows
- Using the Secret in Workflows Your workflow is already configured to use this secret with:
Enabling Github Actions Write Permissions#
For your DNS backup workflow to successfully commit and push changes to your repository, you need to grant it proper write permissions. Follow these steps:
- Navigate to your Github repository Click on the "Settings" tab (near the top right of the repository page)
- In the left sidebar, click on "Actions" under "Code and automation" Scroll down to the "Workflow permissions" section
- Select the "Read and write permissions" option
- Click "Save" to apply these settings
This is sufficient for running directly in Github.
Local development#
Follow all the steps from above. Then additionally install nektos/act
on
your machine, for me on Mac M3 Pro Homebrew version worked:
brew install act
Obtain fine-grained Personal Access Token.
cp .secrets.example .secrets
In .secrets
file update both CLOUDFLARE_API_TOKEN
and GITHUB_TOKEN
.
Put your just obtained fine-grained token into this variable. Tweak
anything else needed in your main.yml
. Then run locally:
act workflow_dispatch --no-skip-checkout
If it is your first time running act
, preferably choose Medium Docker
image (500 MB). Should work with Large (~75GB) and was not tested with
Micro.
Creating a Fine-Grained Personal Access Token#
This guide will walk you through creating a Github fine-grained personal access token (PAT) with write permissions for a specific repository.
- Log in to your Github account Click on your profile picture in the top-right corner Select "Settings" from the dropdown menu Scroll down to the bottom of the left sidebar and click on "Developer settings"
- In the left sidebar, click on "Personal access tokens" Select "Fine-grained tokens" Click the "Generate new token" button
- Token name: Enter a descriptive name (e.g., "DNS Backup Workflow") Description: Add an optional description of what this token will be used for Expiration: Select when the token should expire (recommended: choose a reasonable timeframe like 90 days) Resource owner: Select your Github username (or organization if applicable)
- Choose "Only select repositories" Click the repository dropdown Select the specific repository you want to grant access to
- Scroll down to the "Repository permissions" section Find "Contents" in the list Change the access level from "No access" to "Read and write" Leave all other permissions as "No access" to follow the principle of least privilege
- Scroll to the bottom of the page Click "Generate token" IMPORTANT: Copy the generated token immediately and store it securely (this is your only chance to see the full token)
Note that GITHUB_TOKEN
is automatically injected for Actions running via
Github. Filling in GITHUB_TOKEN
secret is only needed when action is
being run via act
. Enjoy!
Links#
- https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/
- https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#fine-grained-personal-access-tokens
- https://github.com/stefanzweifel/git-auto-commit-action#usage
- https://nektosact.com/usage/runners.html#runners