# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a Docker-based Dynamic DNS client for Hetzner DNS (and 50+ other providers) using **[qmcgaw/ddns-updater](https://github.com/qdm12/ddns-updater)** - a universal, production-ready DDNS solution with web UI. **Core Components:** - `docker-compose.yml`: Service configuration using qmcgaw/ddns-updater image - `data/config.json`: DDNS configuration (domains, tokens, providers) - `config.json.example`: Configuration template for Hetzner setup ## Development Commands ### Docker Operations **Start the service:** ```bash docker-compose up -d ``` **View logs:** ```bash docker-compose logs -f ``` **Restart service:** ```bash docker-compose restart ``` **Stop service:** ```bash docker-compose down ``` **Check status:** ```bash docker-compose ps ``` ### Configuration Management **Create initial config:** ```bash mkdir -p data cp config.json.example data/config.json # Edit data/config.json with your credentials ``` **Validate config JSON:** ```bash cat data/config.json | jq . ``` **Get Hetzner Zone ID via API:** ```bash curl -H "Auth-API-Token: YOUR_TOKEN" https://dns.hetzner.com/api/v1/zones ``` ### Web UI **Access Web UI:** Open browser to `http://localhost:8000` The Web UI shows: - Current IP status - Last update timestamp - Update history - Errors and warnings - Per-domain status ## Architecture ### Application Flow 1. **Initialization**: Load configuration from `data/config.json` 2. **Main Loop**: - Get current public IP (IPv4/IPv6) - Compare with DNS records for each configured domain - Update DNS if IP has changed - Wait for configured period (default: 5 minutes) - Repeat ### Configuration Structure Configuration is in JSON format at `data/config.json`: ```json { "settings": [ { "provider": "hetzner", "zone_identifier": "zone_id", "domain": "example.com", "host": "@", "ttl": 60, "token": "api_token", "ip_version": "ipv4" } ] } ``` **Key Parameters:** - `provider`: DNS provider name (hetzner, cloudflare, duckdns, etc.) - `zone_identifier`: Hetzner DNS Zone ID - `domain`: Base domain name - `host`: Subdomain or `@` for root - `ttl`: Time-to-live in seconds - `token`: Hetzner API token with DNS edit permissions - `ip_version`: `ipv4`, `ipv6`, or `ipv4 or ipv6` ### Multi-Domain Support Add multiple entries in the `settings` array to manage multiple domains or subdomains. ### Environment Variables Optional variables in `.env`: - `PERIOD`: Update check interval (default: 5m) - `LOG_LEVEL`: Logging verbosity (debug, info, warning, error) ## Versioning Strategy This project uses a simplified versioning scheme: - **0.1**: Large changes (new features, breaking changes) - **0.0.1**: Small changes (bugfixes, minor improvements) - **1.x**: Major releases (only by explicit instruction) **When making changes:** 1. Update `CHANGELOG.md` with the change description 2. Increment version according to change size 3. Work in feature branches, merge to main when ready ## Key Files - `docker-compose.yml`: Service definition using qmcgaw/ddns-updater - `config.json.example`: Template for Hetzner configuration - `data/config.json`: Active configuration (not in git) - `.env.example`: Optional environment variables template - `CHANGELOG.md`: Version history ## Security Notes - API token is sensitive - never commit `data/config.json` or `.env` - Container runs with minimal privileges - Only ports 8000 (web UI) exposed - Use HTTPS reverse proxy for production deployments - API token should have minimal required permissions (DNS read/write only) ## Troubleshooting **View Web UI status:** ```bash # Open http://localhost:8000 in browser ``` **Check container logs:** ```bash docker-compose logs --tail=50 -f ``` **Validate configuration:** ```bash # Check JSON syntax cat data/config.json | jq . ``` **Test API connectivity:** ```bash # List zones curl -H "Auth-API-Token: YOUR_TOKEN" https://dns.hetzner.com/api/v1/zones # List records for a zone curl -H "Auth-API-Token: YOUR_TOKEN" "https://dns.hetzner.com/api/v1/records?zone_id=ZONE_ID" ``` **Debug mode:** Set `LOG_LEVEL=debug` in `.env` and restart container. **Container won't start:** - Check `docker-compose logs` - Verify `data/config.json` exists and is valid JSON - Check port 8000 is not in use ## Provider Migration To switch from Hetzner to another provider: 1. Check [supported providers](https://github.com/qdm12/ddns-updater#providers) 2. Update `provider` field in `data/config.json` 3. Adjust provider-specific fields 4. Restart: `docker-compose restart` No code changes needed - just configuration! ## Upstream Documentation - [DDNS-Updater GitHub](https://github.com/qdm12/ddns-updater) - [Hetzner Configuration Guide](https://github.com/qdm12/ddns-updater/blob/master/docs/hetzner.md) - [All Supported Providers](https://github.com/qdm12/ddns-updater#providers)