*Ma*nage *ma*naged *DNS* services with this tool. Schlundtech and probably soon, also Hetzner Cloud DNS too.
  • Go 55.7%
  • JavaScript 38.6%
  • Shell 3.3%
  • TypeScript 2.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Paul-Dieter Klumpp 5670b60982 Add a DKIM setup script for the mail domains
Generates one key per domain, publishes the public key as the TXT record at
<selector>._domainkey, registers the key in OpenDKIM's key.table and
signing.table, and restarts OpenDKIM.

The one part that is easy to get wrong: the .txt that opendkim-genkey
writes is not a bare record value, it is a whole zone-file entry, already
split into 250-character strings:

  202610._domainkey.example.com<TAB>IN<TAB>TXT<TAB>( "v=DKIM1; k=rsa; "
    "p=MIIB..." )

There is no flag that suppresses the stub, so the value has to be
extracted: awk -F'"' picks out the quoted character-strings, which are
concatenated the way a resolver would. Stripping only the quotes would
publish the zone-file syntax itself as the TXT value.

DRY_RUN defaults to 1: nothing is sent to DNS, neither table is touched
and nothing is restarted. key.table and signing.table entries are guarded
by grep -qxF, so a second run in the same month adds no duplicates.
2026-10-02 00:00:01 +02:00
.opencode/plugin Initialize schlundtech-dns CLI with zone and record management 2026-10-01 21:00:33 +02:00
cmd Read credentials from .env and fold two packages into cmd 2026-10-01 22:16:04 +02:00
internal/api Read credentials from .env and fold two packages into cmd 2026-10-01 22:16:04 +02:00
maister@65459dcf65 Initialize schlundtech-dns CLI with zone and record management 2026-10-01 21:00:33 +02:00
scripts Add a DKIM setup script for the mail domains 2026-10-02 00:00:01 +02:00
tools Initialize schlundtech-dns CLI with zone and record management 2026-10-01 21:00:33 +02:00
.env.example Read credentials from .env and fold two packages into cmd 2026-10-01 22:16:04 +02:00
.gitignore Document the Linux cross-build 2026-10-01 23:59:39 +02:00
.gitmodules Initialize schlundtech-dns CLI with zone and record management 2026-10-01 21:00:33 +02:00
AGENTS.md Read credentials from .env and fold two packages into cmd 2026-10-01 22:16:04 +02:00
go.mod Read credentials from .env and fold two packages into cmd 2026-10-01 22:16:04 +02:00
go.sum Read credentials from .env and fold two packages into cmd 2026-10-01 22:16:04 +02:00
main.go Initialize schlundtech-dns CLI with zone and record management 2026-10-01 21:00:33 +02:00
opencode.json Initialize schlundtech-dns CLI with zone and record management 2026-10-01 21:00:33 +02:00
README.md Document the Linux cross-build 2026-10-01 23:59:39 +02:00

schlundtech-dns

A command line tool for Schlundtech DNS. List your zones, inspect their records, and set them — from the terminal, no web interface.

Build and run

On the machine you develop on:

go build
./schlundtech-dns --help

Or skip the binary entirely:

go run . --help

Use go build, not go build ./.... With more than one package the ... form only compiles and writes nothing.

Build for a Linux server

No toolchain on the target needed — the binary is pure Go and statically linked, so it runs on any Linux without a libc:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w" \
  -o dist/schlundtech-dns-linux-amd64 .

GOARCH=arm64 gives you dist/schlundtech-dns-linux-arm64. Copy the file over and run it:

./schlundtech-dns-linux-amd64 --help

Configure

Copy the example file and fill it in:

cp .env.example .env
chmod 600 .env
$EDITOR .env
SCHLUNDTECH_USER=your-user
SCHLUNDTECH_PASSWORD=your-password
SCHLUNDTECH_CONTEXT=10

Check that it works:

./schlundtech-dns zones

.env is read from the working directory. It is gitignored, and the tool warns if it is readable by other users.

Real environment variables win over .env, so you can redirect a single invocation without editing the file:

SCHLUNDTECH_CONTEXT=1 ./schlundtech-dns zones

SCHLUNDTECH_CONTEXT is the context ID Schlundtech gave you when you applied for gateway access. Every public implementation for Schlundtech uses 10, so that is the value to try first — but yours is authoritative. The demo system uses 1.

SCHLUNDTECH_TOKEN — only if your account has two-factor authentication: the current six-digit code from your authenticator app. It is valid for about 30 seconds, so set it right before you run the command.

SCHLUNDTECH_ENDPOINT — to talk to the demo system instead of your live zones: https://demo.autodns.com/gateway/.

Use

List your zones

schlundtech-dns zones

Look at a zone's records

schlundtech-dns records list example.com
schlundtech-dns records list example.com --type TXT

Set a record

schlundtech-dns records set example.com --name @ --type A --value 203.0.113.10
schlundtech-dns records set example.com --name @ --type TXT --value 'v=spf1 -all'

@ is the zone apex, www would be www.example.com. --ttl defaults to the TTL the record already has.

A name and type can hold several values — pass --value more than once. Setting any value replaces all existing ones for that name and type, so there is nothing to delete first.

Dry run

Every write touches public DNS and propagates within seconds. Preview first:

schlundtech-dns records set example.com --name @ --type A --value 203.0.113.10 --dry-run

Remove a record

Without --value this removes every value at that name and type:

schlundtech-dns records delete example.com --name @ --type TXT --value 'v=spf1 -all' --dry-run
schlundtech-dns records delete example.com --name @ --type TXT --value 'v=spf1 -all'

Pipe-friendly output

Every command takes --output table|json. table is the default.

schlundtech-dns records list example.com --output json | jq '.[].value'

Errors always go to stderr, so piping stdout stays clean.

Record types

There is no hardcoded list — --type takes whatever the gateway understands. TXT, A, AAAA, CNAME, MX and the rest all work the same way.

Two notes:

  • NS and SOA are not worth touching. Changing them breaks zone delegation.
  • MX is managed by Schlundtech alongside their mail routing. Editing it by hand can break mail delivery for the domain.

How it talks to the gateway

The gateway is InterNetX's AutoDNS XML API, reached at gateway.schlundtech.de. Two things are worth knowing if you read the code:

  • The gateway answers HTTP 200 even when a task fails. The error is in the response body, not the status line. The tool parses the body and reads the error code from there; a non-2xx status only ever means a wrong path.
  • A write is a remove and an add in one task. Changing a record sends both halves together, so a rejected change leaves the zone untouched.

The gateway allows three requests per second; the tool spaces its calls out accordingly.

References