Skip to main content

Automatically update INWX DANE TLSA DNS records when Caddy Letsencrypt certificates change

Project description

dnssec-inwx-updater

Automatically update INWX DANE TLSA DNS records when Caddy renews a Let's Encrypt certificate.

When Caddy renews a certificate and its public key changes, this tool detects the change and updates the _25._tcp.<domain> TLSA record in your INWX DNS zone — keeping DANE validation working for SMTP without manual intervention.

Installation

From PyPI:

pip install dnssec-inwx-updater

From a wheel (without PyPI access):

pip install dnssec_inwx_updater-*.whl

From source:

git clone <repo>
cd dnssec-inwx-updater
make dev        # creates .venv and installs dev dependencies
make build      # builds wheel into dist/

Configuration

Generate a template config file:

dnssec-inwx-updater --create-config --config /etc/dnssec-inwx-updater/config.toml

This writes a commented template to the given path (parent directories are created automatically) and exits. If the file already exists the command aborts with an error.

Then edit the file and fill in your details:

[inwx]
username = "your-inwx-username"
password = "your-inwx-password"
# shared_secret = ""  # TOTP shared secret — only needed if 2FA is enabled on your account
# language = "de"     # API response language: "de" for inwx.de, "en" for inwx.com (default: de)
# test_mode = false   # Uncomment to use the INWX OT&E sandbox for testing

[cert]
# Directory where Caddy stores certificates
cert_directory = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory"
# The domain whose certificate to watch — resolves to {cert_directory}/{domain}/{domain}.crt
domain = "mail.example.com"

[dns]
# The INWX zone (registered domain) that contains the record
zone = "example.com"
# The record name — INWX appends the zone automatically
record_name = "_25._tcp.mail"
# TTL in seconds
ttl = 3600

Config fields

Section Key Required Default Description
[inwx] username INWX login name (shown top-right in the control panel)
[inwx] password INWX account password
[inwx] shared_secret "" TOTP base32 seed from QR code — only if 2FA is enabled
[inwx] language "de" API response language: "de" (inwx.de) or "en" (inwx.com)
[inwx] test_mode false Use the INWX OT&E sandbox instead of production
[cert] cert_directory Root directory where Caddy stores certificates
[cert] domain Domain to watch — cert resolved as {cert_directory}/{domain}/{domain}.crt
[dns] zone INWX DNS zone (registered domain, e.g. example.com)
[dns] record_name Record name within the zone (e.g. _25._tcp.mail)
[dns] ttl TTL in seconds (e.g. 3600)

Note: The INWX username is your login handle, not your customer number. It is displayed in the top-right corner of the INWX control panel after logging in.

Usage

Run manually:

dnssec-inwx-updater --config /etc/dnssec-inwx-updater/config.toml

Run as a cron job (every 5 minutes):

*/5 * * * * /usr/local/bin/dnssec-inwx-updater --config /etc/dnssec-inwx-updater/config.toml >> /var/log/dnssec-inwx-updater.log 2>&1

The tool is silent when the certificate is unchanged. On a change it logs what it did. On error it logs to stderr and exits non-zero — cron will capture this.

How It Works

  1. Computes a SHA-256 hash of the .crt file managed by Caddy
  2. Compares it to the last known hash stored in state.json (alongside config.toml)
  3. If unchanged: exits silently
  4. If changed: generates the TLSA hash (3 1 1 — DANE-EE, SPKI, SHA-256) via openssl pipeline
  5. Queries INWX for an existing TLSA record and updates it, or creates a new one if absent
  6. Saves the new hash to state.json — only on success, so failures retry on the next run

TLSA Record Format

_25._tcp.mail.example.com. 3600 IN TLSA 3 1 1 <sha256-of-spki>

Parameters: 3 = DANE-EE (end-entity), 1 = SPKI selector, 1 = SHA-256 hash.

Requirements

  • Python 3.11+
  • openssl available in PATH
  • An INWX account with DNS API access

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dnssec_inwx_updater-1.0.1.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dnssec_inwx_updater-1.0.1-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file dnssec_inwx_updater-1.0.1.tar.gz.

File metadata

  • Download URL: dnssec_inwx_updater-1.0.1.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dnssec_inwx_updater-1.0.1.tar.gz
Algorithm Hash digest
SHA256 78405cd66390f7f6c5cfbfb49532b3be6d49f4ac5b81a2a3bbfc4e822d29838c
MD5 08b7bdc27293c3da677078410600c8eb
BLAKE2b-256 a310ab95a7ff351db3f1d4bbe235f12f5ee4461e02602ac0908e27a53217305f

See more details on using hashes here.

Provenance

The following attestation bundles were made for dnssec_inwx_updater-1.0.1.tar.gz:

Publisher: publish.yml on maschmann/dnssec-inwx-updater

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dnssec_inwx_updater-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for dnssec_inwx_updater-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3735d06d697f326f7f49ad795e977c8ca7553429c793f1a0c5e8e23b3b8d74c0
MD5 ecba526682ad03851cd3e16e7c2bd666
BLAKE2b-256 55ee904249e51bef2a40753ab69d82b401c69b710314f4edc2635d8c8f27776a

See more details on using hashes here.

Provenance

The following attestation bundles were made for dnssec_inwx_updater-1.0.1-py3-none-any.whl:

Publisher: publish.yml on maschmann/dnssec-inwx-updater

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page