This is a pure Unix shell script 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.
This project havily inspired by Erik Junsved's cf-tlsa-acmesh, but completely rewritten in pure Unix shell script, adding support for both RSA and EC certificates, and the ability to choose the port and protocol for the TLSA DNS record instead of hardcoding it.
I use this together with the ISPConfig to self-host my email with good deliverability.
This requires curl.
Run this command with elevated privileges (for example, with the help of Sudo):
sudo sh -c 'curl -LJ https://raw.githubusercontent.com/fazelukario/cloudflare-tlsa-acmesh.sh/refs/heads/main/cloudflare_tlsa_acmesh.sh -o /usr/local/bin/cloudflare_tlsa_acmesh.sh && chmod +x /usr/local/bin/cloudflare_tlsa_acmesh.sh'
This requires git.
git clone https://github.com/fazelukario/cloudflare-tlsa-acmesh.sh.git
cd cloudflare-tlsa-acmesh.sh
cp ./cloudflare_tlsa_acmesh.sh /usr/local/bin/cloudflare_tlsa_acmesh.sh # this requires elevated privileges
chmod +x /usr/local/bin/cloudflare_tlsa_acmesh.sh # this also requires elevated privileges
-
Go to Cloudflare and obtain your zone ID for the domain. Generate a user API token with the Zone.DNS permissions.
-
Create a short shell script for the acme.sh
--renew-hook
parameter, such as~/.acme.sh/scripts/update_tlsa_records_renew_hook.sh
, and set the necessary environment variables:#!/bin/sh # Set environment variables export KEY_FILE=~/.acme.sh/mail.example.com/mail.example.com.key export KEY_FILE_NEXT=~/.acme.sh/mail.example.com/mail.example.com.key.next export CF_TOKEN=<API_TOKEN> export CF_ZONE_ID=<ZONE_ID> export DOMAIN=mail.example.com export PROTOCOL="tcp" # optional, default is "tcp" export PORT=25 # optional, default is "25" # Execute the command /usr/local/bin/cloudflare_tlsa_acmesh.sh
-
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 \ --renew-hook '/bin/sh ~/.acme.sh/scripts/update_tlsa_records_renew_hook.sh' \ -d mail.example.com
Ensure that you include
--always-force-new-domain-key
to generate a rollover (next) key. Confirm that the--renew-hook
parameter points to the correct script. -
Run the
~/.acme.sh/scripts/update_tlsa_records_renew_hook.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 theCF_ZONE_ID
,CF_TOKEN
andDOMAIN
environment variables are set correctly. -
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.
All files in this repository are licensed under the MIT License.