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
- Computes a SHA-256 hash of the
.crtfile managed by Caddy - Compares it to the last known hash stored in
state.json(alongsideconfig.toml) - If unchanged: exits silently
- If changed: generates the TLSA hash (
3 1 1— DANE-EE, SPKI, SHA-256) via openssl pipeline - Queries INWX for an existing TLSA record and updates it, or creates a new one if absent
- 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+
opensslavailable inPATH- An INWX account with DNS API access
Metadata
Release files for dnssec-inwx-updater 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| dnssec_inwx_updater-1.0.1.tar.gz | 16.2 kB | With provenance | Details for dnssec_inwx_updater-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| dnssec_inwx_updater-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for dnssec_inwx_updater-1.0.1-py3-none-any.whl |
Total release size: 24.7 kB
Release files / dnssec_inwx_updater-1.0.1.tar.gz
| Download URL | dnssec_inwx_updater-1.0.1.tar.gz |
|---|---|
| Size | 16.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
78405cd66390f7f6c5cfbfb49532b3be6d49f4ac5b81a2a3bbfc4e822d29838c
|
|
BLAKE2b-256 checksum How to use checksums |
a310ab95a7ff351db3f1d4bbe235f12f5ee4461e02602ac0908e27a53217305f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 8, 2026.
Transparency logRelease files / dnssec_inwx_updater-1.0.1-py3-none-any.whl
| Download URL | dnssec_inwx_updater-1.0.1-py3-none-any.whl |
|---|---|
| Size | 8.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3735d06d697f326f7f49ad795e977c8ca7553429c793f1a0c5e8e23b3b8d74c0
|
|
BLAKE2b-256 checksum How to use checksums |
55ee904249e51bef2a40753ab69d82b401c69b710314f4edc2635d8c8f27776a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 8, 2026.
Transparency logSecurity for dnssec-inwx-updater 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for dnssec_inwx_updater-1.0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.