negrii/cloudflare-ddns

By negrii

β€’Updated 7 months ago

Cloudflare Dynamic DNS updater

Image
Networking
0

800

negrii/cloudflare-ddns repository overview

⁠🌐 Cloudflare DDNS Docker

Dynamic DNS (DDNS) updater for Cloudflare, packaged as a multi-architecture Docker image, optimized for Raspberry Pi 3, 4, and 5 as well as Linux x86_64 systems.

This project is designed to automatically keep a Cloudflare DNS (A) record updated with your public IP address, making it ideal for game servers, homelabs, and connections without a static IP.


⁠✨ Features

  • βœ… Uses the official Cloudflare API (PATCH /dns_records)

  • βœ… Multi-arch Docker:

    • linux/amd64 (PC / VPS)
    • linux/arm/v7 (Raspberry Pi 3)
    • linux/arm64 (Raspberry Pi 4 and 5)
  • βœ… Automatic semantic versioning (Semantic Release)

  • βœ… Automatic publishing to:

    • Docker Hub
    • GitHub Container Registry (GHCR)
  • βœ… Logs with date and time (Europe/Madrid)

  • βœ… Non-root user (improved security)

  • βœ… No calls to Cloudflare if the IP has not changed

  • βœ… Very lightweight (Alpine Linux)

  • βœ… Optional persistent state using Docker volumes (avoids false IP updates on restart)


By default, the container stores its internal state (last known IP address and DNS Record ID) inside /data.

To avoid false IP change detections after container restarts, it is strongly recommended to mount a persistent volume.

The following files are stored in /data:

  • last_ip β†’ last public IP detected
  • dns_record_id β†’ Cloudflare DNS Record ID (cached after first run)

If no volume is mounted, the container will still work correctly, but this state will be lost when the container restarts.


β πŸ“¦ Available Images

⁠Docker Hub
docker pull negrii/cloudflare-ddns:latest
⁠GitHub Container Registry
docker pull ghcr.io/negri234279/cloudflare-ddns:latest

Also available by version:

v1.0.0
v1.0.1
v1.1.0

β πŸš€ Quick start with Docker Compose

⁠1️⃣ Create .env
CF_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx
CF_ZONE_ID=yyyyyyyyyyyyyyyyyyyyyyyy
CF_DOMAIN=foo.bar.es
CF_RECORD_TYPE=A
CF_TTL=1
CF_PROXIED=false
CF_INTERVAL=300
TZ=Europe/Madrid

πŸ’‘ CF_TTL=1 TTL automΓ‘tico en Cloudflare.


⁠2️⃣ Run container
docker run -d \
  --name cloudflare-ddns \
  --env-file .env.dev.local \
  --restart unless-stopped \
  -v cloudflare-ddns-data:/data \
  negrii/cloudflare-ddns:latest

πŸ’Ύ The cloudflare-ddns-data volume ensures state persistence across container restarts.

Without it, the container may detect a false IP change on startup.


⁠3️⃣ docker-compose.yml
services:
  cloudflare-ddns:
    image: negrii/cloudflare-ddns:latest
    container_name: cloudflare-ddns
    env_file:
      - .env
    restart: unless-stopped
    volumes:
      - cloudflare-ddns-data:/data
  
volumes:
  cloudflare-ddns-data:

πŸ’Ύ The cloudflare-ddns-data volume ensures state persistence across container restarts.

Without it, the container may detect a false IP change on startup.


⁠4️⃣ Start service
docker compose up -d

View logs:

docker logs -f cloudflare-ddns

⁠5️⃣ πŸ—‘οΈ Remove container and volume (full reset)
docker rm -f cloudflare-ddns
docker volume rm cloudflare-ddns-data

⚠️ This will remove all persisted state.


β πŸ“ Example of logs

2025-03-12 02:20:43 πŸš€ Cloudflare DDNS running on armv7l (TZ=Europe/Madrid)
2025-03-12 02:20:43 ⏱️ Interval: 300s
2025-03-12 02:20:43 βœ… Persistence enabled: /data is a mounted volume
2025-03-12 02:25:43 ℹ️ IP unchanged (203.0.113.45)

β πŸ”‘ How to obtain Cloudflare data

β πŸ”Έ API Token

Create an API Token with permissions:

  • Zone β†’ DNS β†’ Edit

β πŸ”Έ Zone ID

Cloudflare Dashboard β†’ your domain bar.es β†’ Overview β†’ Zone ID


β πŸ”Έ DNS Record ID

It is not necessary to manually obtain the DNS Record ID.

The container will automatically retrieve the DNS Record ID from Cloudflare using the domain and zone information provided on first run, and store it internally.


⁠🧠 Environment variables

VariableDescription
CF_API_TOKENCloudflare token
CF_ZONE_IDZone ID
CF_DOMAINDomain or subdomain
CF_RECORD_TYPEDNS record type (default A)
CF_TTLTTL (default 1 = automatic)
CF_PROXIEDtrue / false (default false)
CF_INTERVALInterval in seconds (default 300)
TZTime zone (default Europe/Madrid)
STATE_DIRState directory (default /data)

β πŸ—οΈ Development

docker compose -f 'docker-compose.dev.yml' up -d --build

β πŸ”„ CI/CD

This project uses GitHub Actions for:

  • Automatic versioning with semantic-release
  • Creation of GitHub Releases
  • Multi-arch builds with Docker Buildx
  • Automatic push to Docker Hub and GHCR

Each push to main generates a new version if the commits require it.


β πŸ” Security

  • Container run as non-root user
  • Cloudflare token never stored in the image
  • Exclusive use of HTTPS and official API

β πŸ‘€ Author

Negrii πŸ”— https://github.com/Negri234279⁠


β πŸ“„ License

MIT License


⁠⭐ Contributions

Pull requests and suggestions are welcome πŸ™Œ

If you find this project useful, leave a ⭐ on GitHub

Tag summary

Content type

Image

Digest

sha256:885ac9ffe…

Size

7.3 MB

Last updated

7 months ago

docker pull negrii/cloudflare-ddns:v1.6.1