I fought with ddclient, but learned to love curl.
If you’re running a custom home router like me, you’re probably using OPNsense. Like me, you also might be managing your domains and subdomains through cPanel. When my ISP changes my IP address -which doesn’t happen often, but will happen suddenly and without notice- I need my DNS records to update automatically.
I was pleased the other day to find out that cPanel has a Dynamic DNS feature out of the box, so the question was how to announce my WAN IP to the required subdomains in a timely fashion.

My research uncovered that a redditor had some success with OPNsense’s ddclient, which expects traditional DynDNS protocols that append parameters to URLs. cPanel’s feature, however, uses a token-based system that wants nothing appended—just hit the URL and it handles the rest. When you try to use the available dyndns2 or Custom GET protocols, ddclient automatically adds /nic/update?system=dyndns&hostname=...&myip=... to your cPanel URL. cPanel returns a 400 error because it has no idea what to do with that.
I spent an hour trying different protocol combinations before I realized: I’m solving the wrong problem.
In Brief
Simply put, the solution is a custom script registered with OPNsense’s configd system, scheduled through the GUI. By registering it with OPNsense actions, you can easily manage this task just like any other cron job in the interface.
Here are the steps.
Step 1: Generate the cPanel Tokens
In cPanel, go to Domains → Dynamic DNS. Create a token for each subdomain you want to update.
cPanel gives you a URL like:
https://yourdomain.com/cpanelwebcall/randomstringofalphacharacters
That token is everything. When you hit that URL, cPanel automatically detects your source IP and updates the DNS record, no parameters needed.
Step 2: Create the Update Script
SSH into OPNsense. Create the directory structure:
bash
mkdir -p /usr/local/opnsense/scripts/ddns
Open the script file, name it something that makes sense for you. I recommend adding every domain to one script file, so that if you ever add more domains, then there’s only one file to edit.
bash
nano /usr/local/opnsense/scripts/ddns/[dns-update-cpanel].sh
This is your typical script file; include a curl command (it’s best to put the full path to the curl executable) followed by the cPanel URL. Here’s an example of what you should be doing:
sh
#!/bin/sh
/usr/local/bin/curl -s "https://yourdomain.com/cpanelwebcall/randomstringofcharacters" # books.yourdomain.com
"https://yourdomain.com/cpanelwebcall/randomstringofcharacters" # files.yourdomain.com
"https://yourdomain.com/cpanelwebcall/randomstringofcharacters" # clients.yourdomain.com
Make it executable:
bash
chmod +x /usr/local/opnsense/scripts/ddns/[dns-update-cpanel].sh
Test it:
bash
/usr/local/opnsense/scripts/ddns/[dns-update-cpanel].sh
```
You should see:
```
ipv4: [your ip number]
ipv4: [your ip number]
ipv4: [your ip number]
Each line is cPanel confirming the update. If you see this, the script works.
Step 3: Register with Configd
OPNsense uses configd to determine what commands are listed in the Cron interface. Register a new action, again, with whatever name makes sense:
bash
nano /usr/local/opnsense/service/conf/actions.d/[dns-update-cpanel].conf
```
Add this:
```
[restart]
command:/usr/local/opnsense/scripts/ddns/[dns-update-cpanel].sh
parameters:
type:script
message:updating cPanel DDNS
description:Update cPanel Dynamic DNS
Opnsense only has two actions: restart and stop. The [restart] action is all that is required to invoke our script. You can update the message and description to something that will make sense in the interface.
Save and exit.
Restart configd:
bash
service configd restart
Verify it loaded:
bash
configctl actions list | grep dns-update-cpanel
If that returns something, you’re registered.
Test via configctl:
bash
configctl ddns_cpanel restart
You should see the IP confirmations again.
Step 4: Schedule It
Now go to the OPNsense web interface.
Navigate to System → Settings → Cron. Click Add.
Configure:
- Enabled: ✓
- Minutes:
0 - Hours:
5(or whenever you want it to run) - Day of the month:
* - Month:
* - Day of the week:
* - Command: Select “Update cPanel Dynamic DNS” from the dropdown
- Description:
cPanel DDNS Update
Save.
I run mine once daily at 5 AM. My ISP rarely changes my IP, usually when they are working in the neighborhood this seems like time enough to have everything in place before I get to the office. If you need more frequent updates, adjust accordingly, knowing that most businesses have static IPs, and residential IPs don’t change that often.
What You Actually Get
One cron job. All your subdomains. Updated automatically within a working day.
When it runs, each subdomain gets a fresh A record pointing to whatever IP my router currently has. If my IP changes, my services stay accessible. If my IP doesn’t change, cPanel just confirms the existing record and moves on.
The whole thing took maybe 30 minutes to set up, most of that spent generating tokens in cPanel.

Caveats
This approach bypasses OPNsense’s built-in Dynamic DNS plugin entirely. That means:
- No GUI status indicators – The built-in DDNS interface won’t show success/failure
- Manual troubleshooting – If something breaks, you’re debugging via SSH and logs
- Possibly not persistent across reinstalls – Scripts in
/usr/local/opnsense/survive reboots but probably not clean installs
For a production environment, you might want something more robust. For a home setup where you can SSH in if needed, this works fine.
Executive Summary
cPanel’s DDNS system is token-based, thereby leaking no information in the URL. It’s dead simple. OPNsense’s ddclient seems to be on its way out, with talk about a native backend which I was unable to make use of.
You can spend hours trying to force compatibility, or you can spend 30 minutes writing a script that does exactly what you need and nothing more.
I chose the script.
If you’re running OPNsense with cPanel hosting, this works. As a matter of fact, any URL-based DNS service will work.
Did this work for you? I’d love to hear about it.
Brendon Brown is a fractional CTO and digital strategist based in Tulsa, Oklahoma. With 14+ years across IT infrastructure, eCommerce, complex migrations, and process automation, he helps private brands and institutions get enterprise-grade results without the enterprise price tag.
Need help with a technical setup like this? The hardest part isn’t the implementation—it’s knowing which approach will actually work for your specific stack. Thirty minutes. No slides, no pitch deck. Schedule a call →
Or just say hello on LinkedIn.