Skip to content

A pure Unix shell script that implements automatic updating of DNS TLSA records using the Cloudflare v4 API from acme.sh generated keys, including the rollover (next) key.

License

Notifications You must be signed in to change notification settings

fazelukario/cloudflare-tlsa-acmesh.sh

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cloudflare-tlsa-acmesh.sh

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.

Usage

Installation

Using CURL

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'

Using GIT

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

Dependencies

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 --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
  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 \
    --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.

  4. 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 the CF_ZONE_ID, CF_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.