2026-04-25 18:00:56 +02:00
2026-04-25 17:58:58 +02:00
2026-04-25 18:00:56 +02:00

Prerequisites

Step 1 - Get a Token

Get a Cloudflare API token with the necessary permissions. Log in to your CloudFlare account, go to Manage Account and to Account API Tokens. Click that big, blue Create Token button and select the Edit zone DNS template.

Select the relevant Zone Resources, I just gave it permissions to edit all my zones: !Pasted image 20250415131506.png

Once you've configured it all, continue to summary, click Create Token and remember to save it. It will only be shown once, so if you forget to save it you'll have to create a new token.

Step 2 - The Script

Create the PowerShell script file on whatever server you want to run this. Using your web server would be a good choice.

nano /etc/ipfixer.ps1

Create the file whereever you want, I'm not your mom.

Paste in the script, remember to add the token you created in step 1:

#Dealing with my Cloudflare domains and my dynamic IP
$ProgressPreference = "SilentlyContinue"
$timeStamp = (get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss")
$cfToken = "MkayyyYourTokenGoesHere"
$myIp = curl "api.ipify.org" #Curl is easier for this one
$cfAPIBaseURI = "https://api.cloudflare.com/client/v4/"
#Get an auth token
$cfHeaders = @{
    "Authorization" = "Bearer $cfToken"
} 

#Pull the DNS zones
$zones = ((Invoke-WebRequest -URI "$($cfAPIBaseURI)zones" -Method GET -Headers $cfHeaders -UseBasicParsing).content | ConvertFrom-JSON).Result

#Get the DNS records for the zones, except the TailScale records
$zones | Foreach-Object{
    $zoneId = $_.id
    $dnsRecords = ((Invoke-WebRequest -URI "$($cfAPIBaseURI)zones/$($_.id)/dns_records" -Method GET -Headers $cfHeaders -UseBasicParsing).content | ConvertFrom-JSON).Result | Where-Object{($_.type -eq "A") -and ($_.content -notMatch "^100")} | Select-Object id, name, type, content

    #Update the DNS record to use the correct IP
    $dnsRecords | where-Object{$_.content -ne $myIp} | Foreach-object{
        $oldIp = $_.content
        $recordBody = @{
            comment = "$TimeStamp | Updated automatically from $oldIp to $myIp"
            content = "$myIp"
        } | ConvertTo-JSON
        $ipFix = Invoke-WebRequest -URI "$($cfAPIBaseURI)zones/$($zoneId)/dns_records/$($_.id)" -Method PATCH -Body $recordBody -Headers $cfHeaders
        If($ipFix.statuscode -match "20."){
            Write-output "Successfully changed the A-record $($_.name) from $oldIp to $myIp."
        }
        If($ipFix.statuscode -notMatch "20."){
            Write-error "Failed to change the A-record $($_.name) from $oldIp to $myIp."
        }
    }
}

A few things to note in the script above:

  • All TailScale IPs (or other IPs starting with 100) are ignored, as is everything but A-records.
  • If a record is updated, a comment is added to it on Cloudflare: !Pasted image 20250415132520.png

Step 3 - Automation (cron)

The entire point was to automate everything, so let's set up a cron job (scheduled task)

crontab -e

This uses your default text editor. If it's something insane like Vim, you might want to change it.

Just like Regex, cron is pretty simple once you've learned it. Every line added to the file consists of 6 space-separated properties:

  1. The minute
  2. The hour
  3. The day of the month
  4. The month of the year
  5. The day of the week
  6. The command to run

This means that to run the command pwsh /etc/ipfixer.ps1 every hour, on the hour, you need to add this line:

0 * * * * pwsh /etc/ipfixer.ps1

Feel free to get creative with the schedule if you like, good info here.

S
Description
Automatically updating the Cloudflare DNS records for your self-hosted domain - with Powershell
Readme GPL-3.0 47 KiB
Languages
PowerShell 100%