This project is not affiliated with the company netcup GmbH. Although it is developed by an employee, it is not an official client by netcup GmbH and was developed in my free time. netcup is a registered trademark of netcup GmbH, Karlsruhe, Germany.
A simple dynamic DNS client written in PHP for use with the netcup DNS API.
- Be a netcup customer: https://www.netcup.de β or for international customers: https://www.netcup.eu
- You don't have to be a domain reseller to use the necessary functions for this client β every customer with a domain may use it.
- netcup API key and API password, which can be created within your CCP at https://www.customercontrolpanel.de
- PHP-CLI with CURL extension
- A domain π
- All necessary API functions for DNS actions implemented (REST API)
- Determines correct public IP address, uses fallback API for determining the IP address, in case main API does return invalid / no IP
- Forces correct IP version (IPv4/IPv6) when connecting to IP address lookup services, preventing issues with dual-stack servers
- Automatically retries API requests on errors
- IPv4 and IPv6 Support (can be individually enabled / disabled)
- Possible to manually provide IPv4 / IPv6 address to set as a CLI option
- Update everything you want in one go: Every combination of domains, subdomains, domain root, and domain wildcard is possible
- Creation of DNS record, if it doesn't already exist
- If configured, lowers TTL to 300 seconds for the domain on each run, if necessary
- Caching: After a successful run, the current IP is cached locally. On subsequent runs, the DNS API is skipped entirely if the IP hasn't changed. Use
--forceto bypass the cache. - Jitter: A random delay (1β30 seconds by default) is applied before API calls to spread load when many users run the script via cron at the same time. Configurable via
JITTER_MAXin config. - Hiding output (quiet option)
- PHP-CLI with CURL extension
Download the latest version from the releases or clone the repository:
$ git clone https://github.com/stecklars/dynamic-dns-netcup-api.git
I'm always trying to keep the master branch stable.
Then, allow update.php to be executed by your user:
chmod u+x update.php
- Copy
config.dist.phptoconfig.phpcp config.dist.php config.php
- Fill out
config.phpwith the required values. The options are explained in there.
./update.php
You should probably run this script every few minutes, so that your IP is updated as quickly as possible. Add it to your cronjobs and run it regularly, for example every five minutes.
A Docker image is available for systems without PHP, such as NAS devices. The image is built for linux/amd64, linux/arm64, and linux/arm/v7 (e.g. Raspberry Pi, NAS devices). It includes PHP, cURL, and a built-in scheduler β no additional setup required. You only need to provide your config.php.
Create your config.php first β use config.dist.php as a template. Then follow the instructions for your platform below.
| Variable | Default | Description |
|---|---|---|
| CRON_SCHEDULE | */5 * * * * |
How often to check for IP changes |
| TZ | UTC | Timezone for the schedule and log output |
| Container path | Description |
|---|---|
/app/config.php |
Your configuration file (read-only) |
/app/data |
Persistent IP cache (empty dir, created automatically) |
- Search for
stecklars/dynamic-dns-netcup-apiin your NAS Docker GUI and download the image - Create a container with the volume mounts and environment variables described above
- Set the restart policy to "always" or "unless stopped" so it survives reboots
- Start the container β it runs the script immediately and then on the configured schedule
The image is pulled from Docker Hub automatically β no need to clone the repository:
docker run -d --name dyndns \
-v ./config.php:/app/config.php:ro \
-v dyndns-data:/app/data \
-e CRON_SCHEDULE="*/5 * * * *" \
-e TZ=Europe/Berlin \
--restart unless-stopped \
stecklars/dynamic-dns-netcup-apiIf you have cloned the repository, you can use docker compose instead:
docker compose up -d
To run the script once instead of starting the scheduler (e.g., to test your config):
docker run --rm -v ./config.php:/app/config.php:ro stecklars/dynamic-dns-netcup-api --run-onceOne-shot mode is meant for testing and manual runs β for regular use, use the cron mode (the default) which handles scheduling, caching, and jitter automatically.
Script flags like --force and --quiet can be used in both modes, e.g.:
docker run --rm -v ./config.php:/app/config.php:ro stecklars/dynamic-dns-netcup-api --run-once --forcedocker logs dyndns # show all logs
docker logs -f dyndns # follow logs in real-time
docker logs --tail 20 dyndns # show last 20 linesIn docker compose, use docker compose logs -f.
- "Permission denied" errors on Fedora, RHEL, or openSUSE: These systems use SELinux, which blocks container access to mounted files even if file permissions look correct. Fix this by adding the
:zflag to all volume mounts, e.g.,-v ./config.php:/app/config.php:ro,z -v dyndns-data:/app/data:z. This does not affect NAS systems. - IPv6: Docker's default bridge network does not support IPv6. If you use
USE_IPV6=true, run the container with--network hostor configure Docker's IPv6 support.
Just add these Options after the command like ./update.php --quiet
| short option | long option | function |
|---|---|---|
| -q | --quiet | The script won't output notices or warnings, only errors |
| -c | --config | Manually provide a path to the config file |
| -4 | --ipv4 | Manually provide the IPv4 address to set |
| -6 | --ipv6 | Manually provide the IPv6 address to set |
| -f | --force | Force update, bypassing the IP cache |
| -h | --help | Outputs this help |
| -v | --version | Outputs the current version of the script |
A test suite is included in the tests/ directory that validates the script's functionality using a mock HTTP server.
- Bash
- PHP-CLI (unit tests work without cURL; integration tests require the cURL extension)
- Python 3 (for the mock HTTP server)
./tests/test.sh
The test suite covers CLI options, IP validation, domain parsing, and full end-to-end update flows including caching, jitter, TTL management, error handling, and IPv4/IPv6 support.
If you have ideas on how to improve this script, please don't hesitate to create an issue. Thank you!