GitShow/mholt/caddy-dynamicdns
mholt

caddy-dynamicdns

Caddy app that keeps your DNS records (A/AAAA) pointed at itself.

by mholt
Star on GitHubFork

Go

366 stars38 forks16 contributorsActive · 2w agoSince 2020Apache-2.0

Meet the team

See all 16 on GitHub →
mholt
mholt12 contributions
francislavoie
francislavoie10 contributions
dependabot[bot]Bot
dependabot[bot]7 contributions
jm355
jm3553 contributions
caiych
caiych2 contributions
otaconix
otaconix2 contributions
cobyge
cobyge1 contribution
eliasvasylenko
eliasvasylenko1 contribution

Languages

View on GitHub →
Go100%

Commit activity

Last 12 weeks · 2 commits

Full graph →

Community health

2 of 6 standards met

Community profile →
42
✓README✓License○Contributing○Code of Conduct○Issue Template○PR Template

Recent PRs & issues

Active · 6 in progress · Last activity 2w ago
See all on GitHub →
PurplestViper
Support global dns option(#92)OpenPR

The global options are set by the tls app, but the field is empty and the field is not exported. Get field data by reflection. #92

PurplestViper · 2w ago
PurplestViper
caddyfile.go: refactor splitProviderSegment() and unmarshalModuleTokens()OpenPR

The and functions are refactored into extended versions of the and functions(https://github.com/caddyserver/caddy/pull/7931). After Caddy merges and publishes, the template code can be deleted.

PurplestViper · 2w ago
mietzen
Add delete_orphans option for automatic DNS record cleanupOpenPR

Disclaimer: I use Claude Code to implement parts of this PR, especially the json state functionality This PR adds functionality to remove orphaned DNS records. Why? This is very useful when using the option and service discovery modules like, in my case, caddy-docker-proxy. Currently we would need to either clean up the DNS records by hand or leave them registered. I propose to solve this by keeping track of our managed domains in a state file () and calling to remove orphaned records. To do so, we need to add the option: This is fully backwards compatible, so without nothing will be touched. I found no other way then to use a state file, since: Tracking all DNS records in zone would delete manually created records of that zone -> Dangerous! Saving the state In-memory only -> Doesn't survive restarts and may leave orphans again Claude suggested to using it makes sense and I couldn't find any other method already present in caddy to save the state. Is this correct? I tested this with my own provider and the provider. Both work flawlessly. I tried to encapsulate the change and to always fail gracefully. I also added test for the storing the state and the deletion functionality. We got some limitations: Removing an entire zone from config prevents orphan cleanup for that zone Changing won't clean up records of the disabled type Multiple Caddy instances sharing storage may cause state conflicts That I added to the . I'm open for feedback! Edit:** One thing to add, I could only test IPv4 since my ISP is not offering IPv6 -.-

mietzen · 2w ago

Recent fixes

View closed PRs →
asio
Support multiple DNS providers (fix #47)MergedPR

This allows updating domains across multiple DNS providers — or multiple accounts of the same provider (e.g. different API credentials per zone) — from a single app. Repeating the whole global option doesn't work (Caddy keeps only the last occurrence), so the app itself now holds a list of providers. Config The directive can now be repeated, with each provider's domains nested inside its block. Caddyfile config (global options): Equivalent JSON config: All other options (, , , /, , , ) remain global and apply to all providers, so no existing option changes semantics. The public IP is looked up once per check and shared across providers. (Per-provider variants of e.g. could be follow-ups if there's demand.) Implementation notes Caddyfile parsing:* the parser takes the provider directive's segment via , splits out sub-blocks, and hands the remaining tokens to the DNS provider module through a rebuilt dispenser — so provider modules parse exactly the tokens they'd parse today. is the only name reserved inside a provider block; it seemed safe to claim since providers receive zones at runtime via libdns rather than via config, any collision would be a loud parse error rather than silent misbehavior, and JSON config bypasses the Caddyfile entirely. Backward compatibility: top-level / are folded into a one-entry list at provision time, and a legacy Caddyfile still adapts to identical JSON as before (covered by regression tests). Mixing top-level with per-provider is rejected with a clear error. Seeding: looking up current IPs from existing DNS records is now tracked per domain name instead of once globally, so every provider's domains get seeded — and as a side effect, domains added by a config reload now get seeded too (previously they were skipped if any earlier config had already seeded). Error semantics unchanged: the boot-time retry backoff still triggers only on total IP-source failure; per-provider failures are logged, as before, so one provider's bad credentials can't wedge the check loop. Testing New parser tests using a dummy in-test DNS provider module (which errors on unrecognized subdirectives — proving reserved tokens never leak into the provider module), covering multi-provider configs, before/after module config in the block, and legacy-format regressions. Unit tests for the legacy config normalization and its error cases. Built with xcaddy + caddy-dns/glesys: produces the expected array, and a legacy Caddyfile produces byte-identical JSON to master. Live test:* ran one Caddy instance against 4 real GleSYS accounts (4 zones, different API credentials each). All four seeded from existing records, created A+AAAA records, verified in public DNS, and subsequent cycles correctly no-op'd. On master, only the last-configured provider ever acts.

asio · 2w ago
kthchew
Using multiple providersClosedIssue

Is it possible to use multiple providers to update different domains? I tried this config (simplified) but it seems like only the second block (for DuckDNS) is functional; is not updated at all.

kthchew · 2w ago
laur3n7ius
feat: add IP hookMergedPR

body: Add pluggable IP updaters and ZTE IPv6 firewall module

laur3n7ius · 4w ago
Structured data for AI agents

Repository: mholt/caddy-dynamicdns. Description: Caddy app that keeps your DNS records (A/AAAA) pointed at itself. Stars: 366, Forks: 38. Primary language: Go. Languages: Go (100%). License: Apache-2.0. Open PRs: 6, open issues: 10. Last activity: 2w ago. Community health: 42%. Top contributors: mholt, francislavoie, dependabot[bot], jm355, caiych, otaconix, cobyge, eliasvasylenko, asio, matthewpi and others.

·@ofershap

Replace github.com with gitshow.dev