Files
DIY-DynDNS-Powershell/readme.md
T

83 lines
3.7 KiB
Markdown
Raw Normal View History

2026-04-25 18:00:56 +02:00
### Prerequisites
- Use Cloudflare DNS
- [Powershell installed](obsidian://open?vault=Glamdring%202&file=PowerShell%20on%20Debian)
### 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](https://linuxsimply.com/linux-basics/text-editors/default/).
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](https://vitux.com/how-to-setup-a-cron-job-in-debian/).