cfddns: rebuild on private fork with management web UI
- Swap image from favonia/cloudflare-ddns:latest to
git.alexzaw.dev/alexz/cloudflare-ddns:latest (private fork with
cmd/manager binary that wraps the original ddns updater)
- Expose web UI on internal port 8080, traefik-routable
- Add CFDDNS_WEB_USER/CFDDNS_WEB_PASSWORD basic-auth form fields
- Repurpose existing DOMAINS/PROXIED/UPDATE_CRON/TZ as first-run seed
for the YAML config that the UI manages thereafter
- Mount ${APP_DATA_DIR}/data:/config for persistent cfddns.yaml
- Healthcheck on /healthz via 127.0.0.1 (alpine wget)
- Bump tipi_version 7 -> 8 to trigger app update
This commit is contained in:
@@ -3,63 +3,84 @@
|
|||||||
"name": "Cloudflare DDNS",
|
"name": "Cloudflare DDNS",
|
||||||
"id": "cfddns",
|
"id": "cfddns",
|
||||||
"available": true,
|
"available": true,
|
||||||
"exposable": false,
|
"port": 8533,
|
||||||
|
"exposable": true,
|
||||||
"dynamic_config": true,
|
"dynamic_config": true,
|
||||||
"no_gui": true,
|
"no_gui": false,
|
||||||
"tipi_version": 7,
|
"tipi_version": 8,
|
||||||
"version": "latest",
|
"version": "v1-ui1",
|
||||||
"categories": [
|
"categories": [
|
||||||
"network",
|
"network",
|
||||||
"utilities"
|
"utilities"
|
||||||
],
|
],
|
||||||
"description": "Automatically update Cloudflare DNS records with your current public IP. Supports multiple domains, IPv4/IPv6, and proxy toggle.",
|
"description": "Automatically updates Cloudflare DNS records with your current public IP. Manage domains, proxied state, schedule, API token, and view live status & logs from a built-in web UI. Fork of favonia/cloudflare-ddns with an added management binary.",
|
||||||
"short_desc": "Dynamic DNS updater for Cloudflare",
|
"short_desc": "Dynamic DNS for Cloudflare, with web UI",
|
||||||
"author": "favonia",
|
"author": "alexz (fork of favonia/cloudflare-ddns)",
|
||||||
"source": "https://github.com/favonia/cloudflare-ddns",
|
"source": "https://git.alexzaw.dev/alexz/cloudflare-ddns",
|
||||||
|
"website": "https://github.com/favonia/cloudflare-ddns",
|
||||||
"form_fields": [
|
"form_fields": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "Web UI Username",
|
||||||
|
"env_variable": "CFDDNS_WEB_USER",
|
||||||
|
"required": true,
|
||||||
|
"default": "admin",
|
||||||
|
"min": 3,
|
||||||
|
"max": 50,
|
||||||
|
"hint": "Username for HTTP basic auth on the management UI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "password",
|
||||||
|
"label": "Web UI Password",
|
||||||
|
"env_variable": "CFDDNS_WEB_PASSWORD",
|
||||||
|
"required": true,
|
||||||
|
"min": 8,
|
||||||
|
"hint": "Password for HTTP basic auth on the management UI"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "password",
|
"type": "password",
|
||||||
"label": "Cloudflare API Token",
|
"label": "Cloudflare API Token",
|
||||||
"env_variable": "CLOUDFLARE_API_TOKEN",
|
"env_variable": "CLOUDFLARE_API_TOKEN",
|
||||||
"required": true,
|
"required": true,
|
||||||
"hint": "API token with DNS edit permissions"
|
"hint": "API token with Zone:DNS:Edit permissions. After first start the UI manages this."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"label": "Domains (comma-separated)",
|
"label": "Initial Domains (comma-separated)",
|
||||||
"env_variable": "DOMAINS",
|
"env_variable": "DOMAINS",
|
||||||
"required": true,
|
"required": false,
|
||||||
"hint": "e.g. home.example.com,vpn.example.com"
|
"hint": "First-run seed only — managed by the web UI afterward. e.g. home.example.com,vpn.example.com"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"label": "Proxied (Orange Cloud)",
|
"label": "Initial Proxied (Orange Cloud)",
|
||||||
"env_variable": "PROXIED",
|
"env_variable": "PROXIED",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": false
|
"default": false,
|
||||||
|
"hint": "First-run seed only — proxy state is managed per-domain by the UI afterward"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"label": "Update Schedule",
|
"label": "Initial Update Schedule",
|
||||||
"env_variable": "UPDATE_CRON",
|
"env_variable": "UPDATE_CRON",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "@every 5m",
|
"default": "@every 5m",
|
||||||
"hint": "Cron expression or @every Xm"
|
"hint": "First-run seed only — managed by the UI afterward. Cron expression or @every Xm."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"label": "Timezone",
|
"label": "Initial Timezone",
|
||||||
"env_variable": "TZ",
|
"env_variable": "TZ",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "UTC"
|
"default": "UTC",
|
||||||
|
"hint": "First-run seed only — managed by the UI afterward"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"supported_architectures": [
|
"supported_architectures": [
|
||||||
"arm64",
|
|
||||||
"amd64"
|
"amd64"
|
||||||
],
|
],
|
||||||
"created_at": 1736974800000,
|
"created_at": 1736974800000,
|
||||||
"updated_at": 1736974800000,
|
"updated_at": 1747555200000,
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"min_tipi_version": "4.5.0"
|
"min_tipi_version": "4.5.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,30 +4,34 @@
|
|||||||
"services": [
|
"services": [
|
||||||
{
|
{
|
||||||
"name": "cfddns",
|
"name": "cfddns",
|
||||||
"image": "favonia/cloudflare-ddns:latest",
|
"image": "git.alexzaw.dev/alexz/cloudflare-ddns:latest",
|
||||||
"isMain": true,
|
"isMain": true,
|
||||||
|
"internalPort": 8080,
|
||||||
"environment": [
|
"environment": [
|
||||||
|
{ "key": "CFDDNS_LISTEN", "value": ":8080" },
|
||||||
|
{ "key": "CFDDNS_CONFIG_FILE", "value": "/config/cfddns.yaml" },
|
||||||
|
{ "key": "CFDDNS_WEB_USER", "value": "${CFDDNS_WEB_USER}" },
|
||||||
|
{ "key": "CFDDNS_WEB_PASSWORD", "value": "${CFDDNS_WEB_PASSWORD}" },
|
||||||
|
{ "key": "CLOUDFLARE_API_TOKEN", "value": "${CLOUDFLARE_API_TOKEN}" },
|
||||||
|
{ "key": "DOMAINS", "value": "${DOMAINS:-}" },
|
||||||
|
{ "key": "PROXIED", "value": "${PROXIED:-false}" },
|
||||||
|
{ "key": "UPDATE_CRON", "value": "${UPDATE_CRON:-@every 5m}" },
|
||||||
|
{ "key": "TZ", "value": "${TZ:-UTC}" }
|
||||||
|
],
|
||||||
|
"volumes": [
|
||||||
{
|
{
|
||||||
"key": "CLOUDFLARE_API_TOKEN",
|
"hostPath": "${APP_DATA_DIR}/data",
|
||||||
"value": "${CLOUDFLARE_API_TOKEN}"
|
"containerPath": "/config",
|
||||||
},
|
"readOnly": false
|
||||||
{
|
}
|
||||||
"key": "DOMAINS",
|
],
|
||||||
"value": "${DOMAINS}"
|
"healthCheck": {
|
||||||
},
|
"test": "wget --spider -q http://127.0.0.1:8080/healthz || exit 1",
|
||||||
{
|
"interval": "30s",
|
||||||
"key": "PROXIED",
|
"timeout": "5s",
|
||||||
"value": "${PROXIED:-false}"
|
"retries": 3,
|
||||||
},
|
"startPeriod": "10s"
|
||||||
{
|
|
||||||
"key": "UPDATE_CRON",
|
|
||||||
"value": "${UPDATE_CRON:-@every 5m}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "TZ",
|
|
||||||
"value": "${TZ:-UTC}"
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,26 @@
|
|||||||
services:
|
services:
|
||||||
cfddns:
|
cfddns:
|
||||||
image: 'favonia/cloudflare-ddns:latest'
|
image: 'git.alexzaw.dev/alexz/cloudflare-ddns:latest'
|
||||||
environment:
|
environment:
|
||||||
|
- 'CFDDNS_LISTEN=:8080'
|
||||||
|
- 'CFDDNS_CONFIG_FILE=/config/cfddns.yaml'
|
||||||
|
- 'CFDDNS_WEB_USER=${CFDDNS_WEB_USER}'
|
||||||
|
- 'CFDDNS_WEB_PASSWORD=${CFDDNS_WEB_PASSWORD}'
|
||||||
- 'CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}'
|
- 'CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}'
|
||||||
- 'DOMAINS=${DOMAINS}'
|
- 'DOMAINS=${DOMAINS:-}'
|
||||||
- 'PROXIED=${PROXIED:-false}'
|
- 'PROXIED=${PROXIED:-false}'
|
||||||
- 'UPDATE_CRON=${UPDATE_CRON:-@every 5m}'
|
- 'UPDATE_CRON=${UPDATE_CRON:-@every 5m}'
|
||||||
- 'TZ=${TZ:-UTC}'
|
- 'TZ=${TZ:-UTC}'
|
||||||
|
volumes:
|
||||||
|
- '${APP_DATA_DIR}/data:/config'
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD-SHELL', 'wget --spider -q http://127.0.0.1:8080/healthz || exit 1']
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
x-runtipi:
|
x-runtipi:
|
||||||
is_main: true
|
is_main: true
|
||||||
|
internal_port: 8080
|
||||||
x-runtipi:
|
x-runtipi:
|
||||||
schema_version: 2
|
schema_version: 2
|
||||||
|
|||||||
39
apps/cfddns/metadata/description.md
Normal file
39
apps/cfddns/metadata/description.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Cloudflare DDNS
|
||||||
|
|
||||||
|
Keeps your Cloudflare DNS A/AAAA records in sync with the public IP address of this server, with a web management UI for managing the domain list and settings.
|
||||||
|
|
||||||
|
This is a private fork of [favonia/cloudflare-ddns](https://github.com/favonia/cloudflare-ddns) with an added `manager` binary that wraps the upstream updater. The manager:
|
||||||
|
|
||||||
|
- Loads configuration from `cfddns.yaml` in the app data dir.
|
||||||
|
- Exposes a web UI (HTTP basic auth) for adding, editing, and removing domain entries, toggling proxy state per domain, editing the Cloudflare API token, and viewing live status and logs.
|
||||||
|
- Supervises the upstream `ddns` binary as a child process and restarts it cleanly when the configuration changes.
|
||||||
|
|
||||||
|
## First install
|
||||||
|
|
||||||
|
On first start the manager seeds `cfddns.yaml` from the `DOMAINS`, `PROXIED`, `UPDATE_CRON`, `TZ`, and `CLOUDFLARE_API_TOKEN` env vars (set via the install form). After that the YAML file is the source of truth and the env vars are ignored.
|
||||||
|
|
||||||
|
If both `DOMAINS` and `CLOUDFLARE_API_TOKEN` are empty at first start, the manager will not launch the updater — it logs a warning and waits for you to configure domains via the web UI.
|
||||||
|
|
||||||
|
## Web UI
|
||||||
|
|
||||||
|
Open the app from the Runtipi dashboard. Log in with the username/password you set during install (`CFDDNS_WEB_USER` / `CFDDNS_WEB_PASSWORD`).
|
||||||
|
|
||||||
|
The UI shows:
|
||||||
|
|
||||||
|
- Current public IPv4/IPv6 (scraped from updater output)
|
||||||
|
- Last update time and status
|
||||||
|
- Updater process state and PID
|
||||||
|
- Domain table with add / edit / delete actions
|
||||||
|
- Per-domain proxied checkbox
|
||||||
|
- Cron schedule, timezone, and API token editor
|
||||||
|
- Live tail of the updater log
|
||||||
|
- "Refresh now" button that triggers an immediate update
|
||||||
|
|
||||||
|
## Storage
|
||||||
|
|
||||||
|
Configuration: `${APP_DATA_DIR}/data/cfddns.yaml` (mode 0600 — contains your API token).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
- Fork: https://git.alexzaw.dev/alexz/cloudflare-ddns
|
||||||
|
- Upstream: https://github.com/favonia/cloudflare-ddns
|
||||||
Reference in New Issue
Block a user