{"id":50265327,"url":"https://github.com/langerma/hetzner-dyndns-openwrt","last_synced_at":"2026-05-27T13:38:06.817Z","repository":{"id":326128773,"uuid":"1104104008","full_name":"langerma/hetzner-dyndns-openwrt","owner":"langerma","description":null,"archived":false,"fork":false,"pushed_at":"2025-12-23T18:32:57.000Z","size":10,"stargazers_count":5,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-05-27T13:38:01.276Z","etag":null,"topics":["cloud-api","ddns","dns","dynamic-dns","dyndns","hetzner","hetzner-cloud","openwrt","shell-script"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/langerma.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-25T18:57:44.000Z","updated_at":"2026-04-05T15:42:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/langerma/hetzner-dyndns-openwrt","commit_stats":null,"previous_names":["langerma/hetzner-dyndns-openwrt"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/langerma/hetzner-dyndns-openwrt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/langerma%2Fhetzner-dyndns-openwrt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/langerma%2Fhetzner-dyndns-openwrt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/langerma%2Fhetzner-dyndns-openwrt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/langerma%2Fhetzner-dyndns-openwrt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/langerma","download_url":"https://codeload.github.com/langerma/hetzner-dyndns-openwrt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/langerma%2Fhetzner-dyndns-openwrt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33568857,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloud-api","ddns","dns","dynamic-dns","dyndns","hetzner","hetzner-cloud","openwrt","shell-script"],"created_at":"2026-05-27T13:38:06.070Z","updated_at":"2026-05-27T13:38:06.810Z","avatar_url":"https://github.com/langerma.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hetzner DynDNS Script\n\nA shell script for automatic dynamic DNS updates using the **Hetzner Cloud API**. Perfect for OpenWRT routers and other Linux systems to keep your DNS records synchronized with your current public IP address.\n\n## Features\n\n- ✅ Works with the **new Hetzner Cloud API** (`api.hetzner.cloud`)\n- ✅ Supports both **IPv4 (A records)** and **IPv6 (AAAA records)**\n- ✅ Automatic IP detection via Hetzner's IP service\n- ✅ Only updates DNS when IP address changes (avoids unnecessary API calls)\n- ✅ Support for both Zone ID and Zone Name lookup\n- ✅ Configurable TTL values\n- ✅ Compatible with OpenWRT and standard Linux systems\n- ✅ Comprehensive error handling and logging\n\n## Requirements\n\n- `curl` - for API requests\n- `jq` - for JSON parsing\n- A Hetzner Cloud account with DNS zones\n- A Hetzner Cloud API token with DNS permissions\n\n## Installation\n\n1. Download the script:\n```bash\nwget https://raw.githubusercontent.com/langerma/hetzner-dyndns-openwrt/main/dyndns.sh\nchmod +x dyndns.sh\n```\n\n2. Get your API token:\n   - Log in to [Hetzner Cloud Console](https://console.hetzner.cloud/)\n   - Navigate to your project → Security → API Tokens\n   - Create a new token with **Read \u0026 Write** permissions for **Zones**\n\n3. Migrate your DNS zones (if needed):\n   - Old DNS zones from `dns.hetzner.com` need to be migrated to the Cloud Console\n   - Follow the [migration guide](https://docs.hetzner.com/networking/dns/migration-to-hetzner-console/process/)\n\n## Usage\n\n### Basic Usage\n\n```bash\n# Update a subdomain (creates pr.example.com)\n./dyndns.sh -Z example.com -n pr\n\n# Update with explicit API token\nHETZNER_AUTH_API_TOKEN=\"your-token-here\" ./dyndns.sh -Z example.com -n dyn\n\n# Update IPv6 record\n./dyndns.sh -Z example.com -n dyn -T AAAA\n\n# Update root domain\n./dyndns.sh -Z example.com -n @ -T A\n\n# Use Zone ID instead of name\n./dyndns.sh -z 123456 -n dyn\n```\n\n### Command-Line Options\n\n| Option | Description | Required |\n|--------|-------------|----------|\n| `-Z` | Zone name (e.g., `example.com`) | Yes (or `-z`) |\n| `-z` | Zone ID | Yes (or `-Z`) |\n| `-n` | Record name (subdomain or `@` for root) | Yes |\n| `-T` | Record type: `A` or `AAAA` (default: `A`) | No |\n| `-t` | TTL in seconds (default: `60`) | No |\n| `-h` | Show help | No |\n\n### Environment Variables\n\nYou can set these environment variables instead of command-line options:\n\n```bash\nexport HETZNER_AUTH_API_TOKEN=\"your-token-here\"\nexport HETZNER_ZONE_NAME=\"example.com\"\nexport HETZNER_RECORD_NAME=\"dyn\"\nexport HETZNER_RECORD_TYPE=\"A\"\nexport HETZNER_RECORD_TTL=\"60\"\n\n./dyndns.sh -n dyn\n```\n\n## Automated Updates (Cron)\n\n### Option 1: Inline Environment Variable\n\n```bash\n# Edit crontab\ncrontab -e\n\n# Add line to update every 5 minutes\n*/5 * * * * HETZNER_AUTH_API_TOKEN=\"your-token\" /root/dyndns.sh -Z example.com -n dyn \u003e\u003e /tmp/dyndns.log 2\u003e\u00261\n```\n\n### Option 2: Configuration File (Recommended)\n\nCreate a config file `/root/.hetzner-dyndns.conf`:\n\n```bash\nHETZNER_AUTH_API_TOKEN=\"your-token-here\"\nHETZNER_ZONE_NAME=\"example.com\"\nHETZNER_RECORD_NAME=\"dyn\"\nHETZNER_RECORD_TYPE=\"A\"\nHETZNER_RECORD_TTL=\"60\"\n```\n\nSecure the file:\n```bash\nchmod 600 /root/.hetzner-dyndns.conf\n```\n\nAdd to crontab:\n```bash\n*/5 * * * * . /root/.hetzner-dyndns.conf \u0026\u0026 /root/dyndns.sh -Z ${HETZNER_ZONE_NAME} -n ${HETZNER_RECORD_NAME} \u003e\u003e /tmp/dyndns.log 2\u003e\u00261\n```\n\n### OpenWRT Specific\n\nFor OpenWRT, the logs are automatically sent to syslog. Check logs with:\n```bash\nlogread | grep dyndns\n```\n\n## Security Best Practices\n\n1. **Use dedicated API tokens** - Create separate tokens for each router/device\n2. **Minimal permissions** - Only grant DNS Zones read/write permissions\n3. **Token naming** - Use descriptive names like \"DynDNS-Router1\", \"DynDNS-Router2\"\n4. **Secure storage** - Use `chmod 600` for config files\n5. **Token rotation** - Periodically rotate tokens for enhanced security\n\n## Troubleshooting\n\n### No zones found\n\n**Error:** `No zones found in your Hetzner account`\n\n**Solution:** Your DNS zones need to be migrated to the Hetzner Cloud Console:\n1. Visit [dns.hetzner.com](https://dns.hetzner.com/)\n2. Follow the migration guide\n3. Ensure zones are visible in Cloud Console\n\n### API Token Invalid\n\n**Error:** `API Error (unauthorized): Invalid token`\n\n**Solution:**\n- Verify token is copied correctly (no extra spaces)\n- Ensure token has **Zones** read/write permissions\n- Create a new token if needed\n\n### Record name doubling\n\n**Error:** Creates `subdomain.example.com.example.com`\n\n**Solution:** This has been fixed in v2.0. Update to the latest version.\n\n### Can't determine IP address\n\n**Error:** `Apparently there is a problem in determining the public ip address`\n\n**Solution:**\n- Check internet connectivity\n- Verify `https://ip.hetzner.com` is accessible\n- For IPv6, ensure your system has a public IPv6 address\n\n## Migration from Old Script\n\nIf you're migrating from the old `dns.hetzner.com` API script:\n\n1. **Migrate your DNS zones** to Hetzner Cloud Console\n2. **Create a new API token** in Cloud Console (old tokens won't work)\n3. **Update your script** to this new version\n4. **Update cron jobs** with the new API token\n\nThe script usage remains largely the same, but uses the new API endpoints.\n\n## API Rate Limits\n\nThe Hetzner Cloud API has rate limits. For DynDNS usage:\n- Recommended check interval: **5 minutes**\n- Script only makes API calls when IP changes\n- Avoid checking more frequently than every 2 minutes\n\n## Examples\n\n### Multiple Subdomains\n\n```bash\n# Update multiple subdomains for different services\nHETZNER_AUTH_API_TOKEN=\"token\" ./dyndns.sh -Z example.com -n home\nHETZNER_AUTH_API_TOKEN=\"token\" ./dyndns.sh -Z example.com -n vpn\nHETZNER_AUTH_API_TOKEN=\"token\" ./dyndns.sh -Z example.com -n nas\n```\n\n### Dual Stack (IPv4 + IPv6)\n\n```bash\n# Update both A and AAAA records\n./dyndns.sh -Z example.com -n dyn -T A\n./dyndns.sh -Z example.com -n dyn -T AAAA\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Credits\n\nThis script is based on the excellent work by [FarrowStrange](https://github.com/FarrowStrange) in the [hetzner-api-dyndns](https://github.com/FarrowStrange/hetzner-api-dyndns) repository.\n\nThe original script was designed for the legacy Hetzner DNS API (`dns.hetzner.com`). This version has been completely rewritten to work with the new Hetzner Cloud API (`api.hetzner.cloud`) while maintaining compatibility with OpenWRT routers and similar systems.\n\n## License\n\nThis project is open source and available under the MIT License.\n\n## Changelog\n\n### v2.0 (2025-11-25)\n- Complete rewrite for new Hetzner Cloud API (`api.hetzner.cloud`)\n- Fixed record name doubling issue\n- Improved error handling and logging\n- Added support for environment variables\n- Enhanced security with Bearer token authentication\n\n### v1.3 (Original)\n- Support for old DNS API (`dns.hetzner.com`)\n- Basic IPv4/IPv6 support\n\n## Support\n\n- Hetzner Cloud API Documentation: https://docs.hetzner.cloud/\n- DNS Migration Guide: https://docs.hetzner.com/networking/dns/migration-to-hetzner-console/\n- Issues: Please report issues on GitHub\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flangerma%2Fhetzner-dyndns-openwrt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flangerma%2Fhetzner-dyndns-openwrt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flangerma%2Fhetzner-dyndns-openwrt/lists"}