github timothymiller/cloudflare-ddns v2.3.0
v2.3.0 — Multi-interface support, reliability fixes & docs overhaul

4 hours ago

cloudflare-ddns v2.3.0 — Multi-interface support, reliability fixes & docs overhaul

⚠️ Upgrade notes

  • Invalid settings now stop the container at startup. Values that used to
    be ignored or silently replaced by a default (regexes, PROXIED,
    WAF_LISTS, TTL, timeouts, malformed API tokens) now produce an explicit
    error. Check the startup log after upgrading.
  • Docker Compose file names swapped. docker/docker-compose.yml is now
    environment-variable mode; the legacy config.json example is
    docker/docker-compose.legacy.yml.
  • Helm chart 0.2.1. Notification and heartbeat URLs are stored in the
    Secret, and the pod runs with a restricted security context.

New features

  • Interface-bound providers (#248). cloudflare.trace, cloudflare.doh,
    ipify and url: accept an @<interface> suffix
    (IP4_PROVIDER=cloudflare.trace@ens5) to send detection through a specific
    network interface.
  • Detection groups (#248). DOMAINS_N, IP4_DOMAINS_N, IP6_DOMAINS_N,
    IP4_PROVIDER_N and IP6_PROVIDER_N (N ≥ 2) give groups of domains their
    own providers. See docs/multi-interface.md.

Behavior changes

  • Graceful shutdown on SIGTERM as well as SIGINT. docker stop,
    Kubernetes pod termination and systemd now trigger the same shutdown path
    as Ctrl+C: DELETE_ON_STOP cleanup runs and the exit heartbeat is sent.
    Waits between updates are interruptible, so shutdown is immediate.
  • Failed Cloudflare writes are reported as failures. A failed create,
    update or delete now sends a fail heartbeat and a notification instead of
    being logged and treated as success.
  • Invalid settings are startup errors. An invalid
    MANAGED_RECORDS_COMMENT_REGEX, MANAGED_WAF_LIST_ITEMS_COMMENT_REGEX,
    PROXIED expression, WAF_LISTS entry, TTL, DETECTION_TIMEOUT or
    UPDATE_TIMEOUT now stops the process with an error instead of silently
    falling back to a default (or silently dropping the entry).
  • UPDATE_CRON minimum interval is 30s. Lower @every values are
    clamped to 30s with a warning.
  • Legacy --repeat interval. In legacy config.json mode the polling
    interval is the TTL, but never less than 300s when the TTL is 1 (auto);
    any ttl below 30 now polls every 300s instead of every second.
  • Exit code. One-shot runs (UPDATE_CRON=@once, or legacy mode without
    --repeat) exit with code 1 if the update failed.
  • Uptime Kuma URL (#302). A query string on UPTIMEKUMA (such as the
    ?status=up&msg=OK&ping= that Uptime Kuma shows) is stripped
    automatically, so both the bare push URL and the copied URL work.
  • API token validation (#292). Surrounding quotes on the token are stripped
    with a warning; a token containing whitespace or other invalid characters
    is a clear startup error (the token itself is never printed). In legacy
    mode an empty or placeholder token is a startup error.
    Cloudflare's "Invalid format for Authorization header" error now comes with
    a hint that the value is likely the Global API Key or a token ID.
  • WAF lists are created if missing. A list named in WAF_LISTS that does
    not exist is created, using WAF_LIST_DESCRIPTION as its description
    (requires the Account Filter Lists Edit permission).
  • Telegram messages are sent as plain text (no Markdown parse mode), so
    domain names with _ or * no longer break delivery.
  • Logging. Heartbeat and notification failures are logged with the HTTP
    status; secrets in notification URLs are redacted in logs.

Fixes

  • DNS records are looked up by name server-side. Zones with more than 100
    A/AAAA records could miss the target record and try to recreate it every
    cycle.
  • A failed record listing is treated as a failure rather than "no records",
    which could create duplicates.
  • Legacy mode: failed writes are reported, record names are matched
    case-insensitively, and purgeUnknownRecords on definitive IP absence now
    deletes only the configured subdomains' records instead of every A/AAAA
    record in the zone.
  • cloudflare.doh, ipify and url: providers are pinned to the requested
    address family (previously only cloudflare.trace was), fixing detection
    failures on dual-stack hosts.
  • Multicast, reserved (240/4), benchmarking (198.18/15), 0.0.0.0/8 and
    IPv4-mapped IPv6 addresses are no longer accepted as detected IPs.
  • WAF list items are read with cursor pagination; large lists were truncated.
  • DELETE_ON_STOP reports per-domain failures in the exit heartbeat and
    notification (previously it always claimed success and sent two exit
    heartbeats).
  • Zone IDs are cached instead of looked up on every cycle.

Documentation and deployment

  • README restructured: quick start with exact token permissions, how-it-works
    section, configuration by topic, one canonical environment variable
    reference, deployment, security notes and troubleshooting.
  • Legacy config.json mode documented separately in
    docs/legacy-config.md, including a migration
    table to environment variables.
  • Corrected documentation: the IPv4 default provider is cloudflare.trace
    (#294); Pushover URL is pushover://shoutrrr:api-token@user-key;
    scheduling supports @every/@once only (not cron expressions).
  • docker/docker-compose.yml is now environment-variable mode; the legacy
    file is docker/docker-compose.legacy.yml. Obsolete version: and
    PUID/PGID removed.
  • systemd unit: absolute ExecStart, optional
    EnvironmentFile=/etc/cloudflare-ddns/env for environment-variable mode,
    and sandboxing (DynamicUser, ProtectSystem=strict, ...).
  • Helm chart 0.2.1 (appVersion 2.3.0): notification and heartbeat URLs moved
    into the Secret, existingSecret can carry them, new deleteOnFailure,
    rejectCloudflareIps, wafListDescription, wafListItemComment and
    managedWafListItemsCommentRegex values, restricted security context and
    Recreate strategy.
  • k8s/cloudflare-ddns.yml rewritten for environment-variable mode (legacy
    manifest kept as k8s/cloudflare-ddns.legacy.yml).
  • Legacy config.json now supports recordComment (#289).
  • Release notes consolidated into this changelog.

Docker images

timothyjmiller/cloudflare-ddns:2.3.0
timothyjmiller/cloudflare-ddns:2.3
timothyjmiller/cloudflare-ddns:2
timothyjmiller/cloudflare-ddns:latest

Helm chart: oci://ghcr.io/timothymiller/cloudflare-ddns version 0.2.1.

Full changelog: v2.2.0...v2.3.0

Don't miss a new cloudflare-ddns release

NewReleases is sending notifications on new releases.