Automatically update INWX DANE TLSA DNS records when Caddy 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
pip install dnssec-inwx-updater
Configuration
Generate a template config file with:
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"
# 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 | Description |
|---|---|---|
[inwx] |
username |
INWX account username |
[inwx] |
password |
INWX account password |
[inwx] |
test_mode |
true to use the OT&E sandbox (default: false) |
[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) |
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 on no-op (certificate 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 changed: generates the TLSA hash (
3 1 1— DANE-EE, SPKI, SHA-256) via openssl - Finds the existing TLSA record in INWX and updates it, or creates a new one if absent
- Saves the new hash to
state.json
TLSA Record Format
_25._tcp.mail.example.com. 3600 IN TLSA 3 1 1 <sha256-of-spki>
Requirements
- Python 3.11+
opensslavailable inPATH- An INWX account with API access
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dnssec_inwx_updater-0.1.0.tar.gz.
File metadata
- Download URL: dnssec_inwx_updater-0.1.0.tar.gz
- Upload date:
- Size: 15.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7032f29dd12b0814eaba87a4aef7b729f732567473581862f5e4ddd76ce95849
|
|
| MD5 |
fdc36b840feb0eab88b40627dc5e721b
|
|
| BLAKE2b-256 |
c64449331bb8d49721b30cf89210c3363c103a466b750af674fabeeb558a0c02
|
Provenance
The following attestation bundles were made for dnssec_inwx_updater-0.1.0.tar.gz:
Publisher:
publish.yml on maschmann/dnssec-inwx-updater
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dnssec_inwx_updater-0.1.0.tar.gz -
Subject digest:
7032f29dd12b0814eaba87a4aef7b729f732567473581862f5e4ddd76ce95849 - Sigstore transparency entry: 1473244079
- Sigstore integration time:
-
Permalink:
maschmann/dnssec-inwx-updater@1772df1d4a47d8de63119cb74ac390405715851f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/maschmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1772df1d4a47d8de63119cb74ac390405715851f -
Trigger Event:
push
-
Statement type:
File details
Details for the file dnssec_inwx_updater-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dnssec_inwx_updater-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
009b62a2dd3c72951787029dd46ea3183cfd804d4fa396ce20addd1bae8dd429
|
|
| MD5 |
1039ea9a0c4c47020fb655576bad7bdc
|
|
| BLAKE2b-256 |
aacfacf57e0cf54dad9c92f25e7dce9f66d39218189cad573f5a2e9059171f70
|
Provenance
The following attestation bundles were made for dnssec_inwx_updater-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on maschmann/dnssec-inwx-updater
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dnssec_inwx_updater-0.1.0-py3-none-any.whl -
Subject digest:
009b62a2dd3c72951787029dd46ea3183cfd804d4fa396ce20addd1bae8dd429 - Sigstore transparency entry: 1473244213
- Sigstore integration time:
-
Permalink:
maschmann/dnssec-inwx-updater@1772df1d4a47d8de63119cb74ac390405715851f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/maschmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1772df1d4a47d8de63119cb74ac390405715851f -
Trigger Event:
push
-
Statement type: