Metadata-Version: 2.4
Name: octodns-hetzner
Version: 2.0.0
Summary:  Hetzner DNS provider for octoDNS
Home-page: https://github.com/octodns/octodns-hetzner
Author: Ross McFarland
Author-email: rwmcfa1@gmail.com
License: MIT
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: octodns>=1.5.0
Requires-Dist: requests>=2.27.0
Requires-Dist: hcloud>=2.3.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: pytest-network; extra == "dev"
Requires-Dist: requests_mock; extra == "dev"
Requires-Dist: black<25.0.0,>=24.3.0; extra == "dev"
Requires-Dist: build>=0.7.0; extra == "dev"
Requires-Dist: changelet; extra == "dev"
Requires-Dist: isort>=5.11.5; extra == "dev"
Requires-Dist: proviso; extra == "dev"
Requires-Dist: pyflakes>=2.2.0; extra == "dev"
Requires-Dist: readme_renderer[md]>=26.0; extra == "dev"
Requires-Dist: twine>=3.4.2; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pytest-network; extra == "test"
Requires-Dist: requests_mock; extra == "test"
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

## Hetzner DNS provider for octoDNS

An [octoDNS](https://github.com/octodns/octodns/) provider that targets [Hetzner DNS](https://www.hetzner.com/dns-console).

### Installation

#### Command line

```
pip install octodns-hetzner
```

#### requirements.txt/setup.py

Pin specific versions or SHAs in your project to control upgrades. Refer to
PyPI for current releases. Minimum requirements align with `setup.py`, e.g.:

```
octodns>=1.5.0
octodns-hetzner>=1.0.0
```

### Configuration

```yaml
providers:
  hetzner:
    class: octodns_hetzner.HetznerProvider
    # Your Hetzner API token (required)
    token: env/HETZNER_TOKEN
    # Choose backend during transition to Cloud Zones API
    # - dnsapi (default): uses Hetzner DNS Console API (current behavior)
    # - hcloud: uses Hetzner Cloud API (Zones). Requires a Cloud API token
    backend: dnsapi
```

### Backends

- `dnsapi` (default): uses Hetzner DNS Console API with DNS tokens. Backward compatible with existing setups.
- `hcloud`: uses Hetzner Cloud API Zones via the official `hcloud` client. Requires a Hetzner Cloud API token. The `hcloud` client library is installed as a dependency of this package.

Both backends will co-exist until at least May 2026. The default remains `dnsapi`; opt into `hcloud` when ready.

Note: The `hcloud` backend is new and may evolve. Apply (writes) are implemented via RRSet semantics in the provider, with a thin adapter using the official `hcloud` client. When zone/rrset TTLs are unavailable from the API, a conservative fallback of `3600` seconds is used.

### Zone-by-Zone Migration

You can configure multiple provider instances with different backends to migrate zones gradually:

```yaml
providers:
  hetzner-dns:
    class: octodns_hetzner.HetznerProvider
    token: env/HETZNER_DNS_TOKEN
    backend: dnsapi

  hetzner-cloud:
    class: octodns_hetzner.HetznerProvider
    token: env/HETZNER_CLOUD_TOKEN
    backend: hcloud

zones:
  # Legacy zone still using DNS Console API
  legacy.example.com.:
    sources:
      - hetzner-dns
    targets:
      - hetzner-dns

  # Zone migrated to Cloud Zones API
  migrated.example.com.:
    sources:
      - hetzner-cloud
    targets:
      - hetzner-cloud
```

**Migration Steps**:

1. **Prepare**: Ensure you have a Hetzner Cloud API token available for `hcloud`.
2. **Configure**: Add a second provider instance with `backend: hcloud` and the Cloud API token
3. **Test**: Run `octodns-sync --dry-run` to validate the new provider can read zones
4. **Migrate**: Update zone configuration to use the new provider
5. **Verify**: Confirm DNS records are identical using `octodns-compare`
6. **Repeat**: Migrate remaining zones one at a time

**Token Requirements**:
- `dnsapi` backend: Requires DNS Console API token (from DNS Console)
- `hcloud` backend: Requires Hetzner Cloud API token (from Cloud Console)
- Tokens are **not interchangeable** between backends

### Support Information

#### Records

HetznerProvider supports A, AAAA, CAA, CNAME, DS, MX, NS, PTR, SRV, TLSA, and TXT

#### TXT Records and DKIM

Long TXT records (such as DKIM keys exceeding 255 characters) are automatically
chunked into RFC-compliant format when using the `hcloud` backend. For DKIM keys,
configure them as a single TXT value in your zone file:

```yaml
dkim._domainkey:
  type: TXT
  value: "v=DKIM1\\;k=rsa\\;p=MIIBIjANBgkqh...very-long-key..."
```

The provider will automatically split values exceeding 255 characters into
properly quoted chunks (e.g., `"chunk1" "chunk2"`). Do not manually split long
values into multiple `values:` entries unless you specifically need multiple
distinct TXT records (such as for site verification).

#### Root NS Records

HetznerProvider supports full root NS record management.

#### Dynamic

HetznerProvider does not support dynamic records.

### Development

See the [/script/](/script/) directory for some tools to help with the development process. They generally follow the [Script to rule them all](https://github.com/github/scripts-to-rule-them-all) pattern. Most useful is `./script/bootstrap` which will create a venv and install both the runtime and development related requirements. It will also hook up a pre-commit hook that covers most of what's run by CI.
