Howto: ACME DNS-Authenticator shell script using acmesh project

klaboor

Cadet
Joined
Jan 23, 2023
Messages
4
Greetings.

You discovered new 'shell' ACME DNS authenticator method asking yourself how to use it.

Short theory before we begin.
ACME authentication is one of the ACME protocol function required to PROVE that you are authorized for requested domain. In this case this is done by placing random TXT DNS record on your DNS server.

Since you are here I'm sure you heard about acmesh project. If not, please visit this link

We will use acmesh, part of it to be specific because acmesh already covers many providers, but it does the whole issuing certificate process. We don't want that. We want also install certificate into TrueNAS, not just issue it.

This video will help you set everything you need except ACME DNS authentication with shell script and we will do that part right now.
TrueNAS SCALE - Adding LetsEncrypt Certificates

You don't need to be root, but keep doing everything under same user!
If you already use acmesh and you want to switch over this method, stop all acmesh related cron jobs or whatever jobs you have currently in place and skip to step 5.

1. Create some dataset dedicated to this script somewhere on your pool
/mnt/tank/acmeScript

2. Go 'System Settings' -> 'Shell' or use PuTTY or similar to get into shell.

3. Navigate to your new folder (dataset)
cd /mnt/tank/acmeScript

4. Clone acmesh project localy with git
git clone https://github.com/acmesh-official/acme.sh.git

5. Create empty script file (select name your choice)
touch acmeShellAuth.sh

6. Now you need to paste code into file. Open file in editor
nano acmeShellAuth.sh

7. Copy code below and paste it in file(hit SHIFT + Insert in UI Shell ro paste code)
Note.
This script will load main acme.sh script and related DNS provider script so we can use custom functions for DNS TXT record creation/removal ONLY.
It also creates logfile called acmeShellAuth.log next to your script file so you can check what is going on.


Code:
#!/bin/bash


### VARIABLES
# Logfile
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
LOGFILE="${SCRIPT_DIR}/acmeShellAuth.log"


# Source acmesh scripts
export ACME_FOLDER="/mnt/pool/acme.sh" # Change this path to reflect yourf environment
export ACME_DNSAPI="${ACME_FOLDER}/dnsapi"
export PROVIDER="dns_provider" # Find provider script in 'dnsapi' folder
source "${ACME_FOLDER}/acme.sh" > /dev/null 2>&1
source "${ACME_DNSAPI}/${PROVIDER}.sh" > /dev/null 2>&1




# Dns API authentication. See details for your provider https://github.com/acmesh-official/acme.sh/wiki/dnsapi
export username="example@gmail.com"
export password="somePass"


### FUNCTIONS
_log_output() {
        echo `date "+[%a %b %d %H:%M:%S %Z %Y]"`" $1" >> ${LOGFILE}
}




### MAIN
_log_output "INFO Script started."


# File/folder validation
if [ ! -d "${ACME_FOLDER}" ]; then
        _log_output "ERROR Invalid acme folder: ${ACME_FOLDER}"
        return 1
fi
if [ ! -f "${LOGFILE}" ]; then
        touch "${LOGFILE}"
        chmod 500 "${LOGFILE}"
fi


# Main
if [ "${1}" == "set" ]; then
        ${PROVIDER}_add "${3}" "${4}" >> ${LOGFILE} 2>/dev/null
elif [ "${1}" == "unset" ]; then
        ${PROVIDER}_rm "${3}" "${4}" >> ${LOGFILE} 2>/dev/null
fi


_log_output "INFO Script finished."


8. Now you need to change few lines to reflect your environment and DNS provider
a. Modify acme.sh path​

before
export ACME_FOLDER="/mnt/pool/acme.sh"

after
export ACME_FOLDER="/mnt/tank/acmeScript/acme.sh"

b. Select your DNS provider. Navigate here dnsapi or here dnsapi2 and find your provider.
Each provider has it's own issue command. You need that --dns parameter value.
For example PowerDNS have dns_pdns, WEDOS have dns_wedos and so on.
You need to change it here

before
export PROVIDER="dns_provider"

after
export PROVIDER="dns_wedos"

c. Apply your login credentials, token, api password, whatever is valid for your provider.
My is WEDOS so I will demonstrate accordingly

before
export username="example@gmail.com"
export password="somePass"

after
export WEDOS_Username="klaboor@gmail.com"
export WEDOS_Wapipass="start123"

9. Check again you modified things correctly and save your script file. Hit CTRL+x
Save modified buffer? Hit 'y' for Yes and confirm with ENTER.

10. Change script file permissions because it has password inside.
Only you will be able to read, write and execute it
chmod 700 acmeShellAuth.sh

11. In UI navigate to 'Credentials' -> 'Certificates'
Click 'Add' in ACME DNS-Authenticators section
Choose 'Name' you like
'Authenticator' select shell
'Authenticator script' will be /mnt/tank/acmeScript/acmeShellAuth.sh
'Running user' root or admin or whatever user you are using
'Timeout' and 'Propagation delay' are set to 60 (when fields are empty) by default but it was not enough time in my case so I set both to 600
Click 'Save'

12. From now you can continue with steps described in video.

13. Once you have your new certificate in place there is one last step I didn't knew it has be done.
In UI navigate 'System Settings' -> 'General'
Click 'Settings' in GUI section and change 'GUI SSL Certificate' from truenas_default to the one you already installed.
Check 'Web Interface HTTP -> HTTPS Redirect' option and click 'Save'
Confirm web service restart and you should be set.

And thats it. Hope this little howto is clear and helpful.
Of course there is room for improvements and feedback is highly appreciated.
Enjoy!
 

seggerman

Dabbler
Joined
Jun 8, 2011
Messages
34
@klaboor,

I've been trying your script (thanks for putting this together) and it always fails. If I do it manually via the CL it works fine. So I know that the certificate gets issued. If I try it via your script using the Shell DNS authenticator it always fails with:
Here are the challenges that were not fulfilled: Challenge Type: dns-01 Error information: - Type: urn:ietf:params:acme:error:unauthorized - Details: Incorrect TXT record "orr2rqV9xW9AU3GSYgR63UWmElGkp1YkXeYEGv6PYSs" found at
I think it runs into a time out (I've upped the time to 600s). Running from the CL it completes quickly. One thing that I noticed is that on the CL I needed to add "--server letsencrypt" to have LE create the certificate (and not ZEROSSL). Could this be the case? I've tried setting the environment variable DEFAULT_CA to letsencrypt but it still fails.

Any insight? Potentially how to debug the calls to see where it fails?

Thanks
Alexander
 

klaboor

Cadet
Joined
Jan 23, 2023
Messages
4
This script is about to utilize acme.sh functions to ONLY add and remove DNS TXT records. Rest is done by truenas built in procedure. You use --server parameter when you are using acme.sh for entire process. It’s hard to advise without seeing what you accomplished, but from what you posted it seems you are mixing stuff a little bit. Let’s see what you have in script you defined as shell DNS Authenticator, but remove any username password before posting.
 

troyh

Cadet
Joined
Feb 16, 2023
Messages
3
Thank you @klaboor, your script and detailed instructions work perfectly!

For anyone that sees this post and are using a local bind9 server for DNS. The only changes I needed from above are:
  • comment out export username and password as they are not used with the dns_update provider
  • export PROVIDER="dns_update"
  • export NSUPDATE_SERVER="<YOUR_BIND9_NAMESERVER_IP_OR_FQDN>"
  • export NSUPDATE_SERVER="/mnt/tank/acmeScript/nsupdate.key"
  • create the /mnt/tank/acmeScript/nsupdate.key file with the update key from your bind9 configuration (/etc/bind/named.conf.local or similar). Something like:
    Code:
    key "update" {
        algorithm hmac-sha512;
        secret "<YOUR_SECRET_KEY>";
    };
Troy
 
Last edited:

rjtaylor

Cadet
Joined
Apr 1, 2023
Messages
1
Thank you @klaboor for this lovely bit of documentation (and the script)!

If anyone is using Gandi DNS, the only modifications to @klaboor's script you need are:
  1. Comment out the "export username" and "export password" lines.
  2. Add a line for your Gandi API key that looks like this:
export GANDI_LIVEDNS_KEY="keyinsidethesequotes"
 

DonnyJohnny

Cadet
Joined
Mar 27, 2022
Messages
6
Error: [EFAULT] Certificate request for final order failed: Authorization for identifier Identifier(typ=IdentifierType(dns), value='aliasDomainForValidationOnly.com') failed. Here are the challenges that were not fulfilled: Challenge Type: dns-01 Error information: - Type: urn:ietf:params:acme:error:unauthorized - Details: No TXT record found at _acme-challenge.aliasDomainForValidationOnly.com

This is the above error when creating the cert.

Is there a way to use acme.sh in the following way
acme.sh --issue \
-d example.com --challenge-alias aliasDomainForValidationOnly.com --dns dns_dynu
 

danb35

Hall of Famer
Joined
Aug 16, 2011
Messages
15,504

DonnyJohnny

Cadet
Joined
Mar 27, 2022
Messages
6
The way to handle this is probably to just run acme.sh directly, and then use either its built-in deploy script, or mine, to deploy the cert to TrueNAS:
that's what i am doing now.
Thanks for the wonderful script.

I am just thinking if there is any way for this auto certification thing to be more integrated into the system and make it more neat.
 

DonnyJohnny

Cadet
Joined
Mar 27, 2022
Messages
6
The way to handle this is probably to just run acme.sh directly, and then use either its built-in deploy script, or mine, to deploy the cert to TrueNAS:
By the way, my first renewal of cert coming soon. I would like to take this opportunity to ask a question on the cron job.

Currently my cron task command as per below (edfault)
/root/.acme.sh/acme.sh --cron

does acme.sh knows that it need to load your script?
--reloadcmd "/path/to/deploy_freenas.py"

or i need to add this in the cron command
/root/.acme.sh/acme.sh --cron --reloadcmd "/path/to/deploy_freenas.py"

please advise.

Thank you.
 

danb35

Hall of Famer
Joined
Aug 16, 2011
Messages
15,504
does acme.sh knows that it need to load your script?
Yes. It saves all the relevant parameters (DNS API credentials, pre- and post-hooks, etc.) with the cert files.
 

macnugget

Dabbler
Joined
Sep 10, 2019
Messages
15
Just an additional note, on a clean install of TrueNAS scale I encountered this error when trying to create the ACME certificate:

Please configure an email address for any local administrator user which will be used with the ACME server

The solution was to set an email address for the "root" local user. This was surprising to me, because I had created a local user account which the authenticator script was set to use and that account did have an email address set.
 
Top