/cf-tlsa-acmesh

A simple Go program that lets you automate the updating of TLSA DNS records with the Cloudflare v4 API from acme.sh generated keys, including a rollover (next) key.

Primary LanguageGoMIT LicenseMIT

cf-tlsa-acmesh

This is a simple Go program that lets you automate the updating of TLSA DNS records with the Cloudflare v4 API from acme.sh generated keys, including the rollover (next) key generated by passing --force-new-domain-key to acme.sh. This is useful for configuring DANE when setting up an SMTP server.

I use this together with the Maddy Mail Server to self-host my email with good deliverability.

NOTE: This program is hardcoded to use port 25 and TCP as the protocol for the record name, but this can easily be changed by modifying the port and protocol variable in the source code.

Usage

Installation

Linux x86-64

This requires curl.

Run this command with elevated privileges (for example, with the help of Sudo):

sudo sh -c 'curl -LJ https://github.com/nixigaj/cf-tlsa-acmesh/releases/latest/download/cf-tlsa-acmesh-x86-64 -o /usr/local/bin/cf-tlsa-acmesh && chmod +x /usr/local/bin/cf-tlsa-acmesh'

Linux arm64

This requires curl.

Run this command with elevated privileges (for example, with the help of Sudo):

sudo sh -c 'curl -LJ https://github.com/nixigaj/cf-tlsa-acmesh/releases/latest/download/cf-tlsa-acmesh-arm64 -o /usr/local/bin/cf-tlsa-acmesh && chmod +x /usr/local/bin/cf-tlsa-acmesh'

Other UNIX-like systems

This requires Git and Go.

git clone https://github.com/nixigaj/cf-tlsa-acmesh
cd cf-tlsa-acmesh
go build -ldflags="-s -w" -o cf-tlsa-acmesh

Install the generated executable by copying it to /usr/local/bin/cf-tlsa-acmesh (this requires elevated privileges).

cp ./cf-tlsa-acmesh /usr/local/bin/cf-tlsa-acmesh

Example setup with acme.sh

  1. Go to Cloudflare and obtain your zone ID for the domain. Generate a user API token with the Zone.DNS permissions.

  2. Create a short shell script for the acme.sh --reloadcmd parameter, such as ~/.acme.sh/scripts/reloadcmd-mx1-example-com.sh, and set the necessary environment variables:

    #!/bin/sh
    
    # Set environment variables
    export KEY_FILE=~/.acme.sh/mx1.example.com_ecc/mx1.example.com.key
    export KEY_FILE_NEXT=~/.acme.sh/mx1.example.com_ecc/mx1.example.com.key.next
    export ZONE_ID=<ZONE_ID>
    export API_TOKEN=<API_TOKEN>
    export DOMAIN=mx1.example.com
    
    # Execute the command
    /usr/local/bin/cf-tlsa-acmesh
  3. Issue an acme.sh certificate with the following command:

    env \
    CF_Token=<TOKEN> \
    CF_Account_ID=<ACCOUNT_ID> \
    CF_Zone_ID=<ZONE_ID> \
    ~/.acme.sh/acme.sh \
    --issue \
    --server letsencrypt \
    --force \
    --always-force-new-domain-key \
    --dns dns_cf \
    --reloadcmd '/bin/sh ~/.acme.sh/scripts/reloadcmd-mx1-example-com.sh' \
    -d mx1.example.com

    Ensure that you include --always-force-new-domain-key to generate a rollover (next) key. Confirm that the --reloadcmd parameter points to the correct script.

  4. Run the ~/.acme.sh/scripts/reloadcmd-mx1-example-com.sh script manually once to generate the initial DNS records and verify that everything works. You can run the script multiple times; it only updates DNS records when necessary and is self-healing provided the ZONE_ID, API_TOKEN and DOMAIN environment variables are set correctly.

  5. For testing, use Internet.nl's email test to ensure that DANE and its rollover scheme are set up correctly, as you can see below.

    Screenshot from Internet.nl

License

All files in this repository are licensed under the MIT License.