ACME dns-authenticator shell script

loicuv

Cadet
Joined
Jan 4, 2023
Messages
3
Hi

After some searching I found that the only supported acme dns authenticators are cloudflare and aws route53. I'm currently using OVH as my DNS provider so I figured I'd try the "shell" type authenticator in the UI.
I installed acme.sh and followed the directives for OVH and ended up putting this in my shell script
/root/.acme.sh/acme.sh --issue -d "my.domain" -d "*.my.domain" --dns dns_ovh --server letsencrypt
Which works well when running it manually (with proper api auth for ovh) and creates the certificates in /root/.acme.sh/my.domain. I then created an acme dns authenticator with the "shell" type pointing to this script, and created it successfully.
I then created a certificate signing request that uses my authenticator, which worked, but when actually creating the ACME certificate, I'm getting a DNS error (which doesn't happen when running my authenticator script manually)
Code:
Error information:
- Type: urn:ietf:params:acme:error:dns
- Details: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.my.domain - check that a DNS record exists for this domain

Authorization for identifier Identifier(typ=IdentifierType(dns), value='my.domain') failed.
Here are the challenges that were not fulfilled:
Challenge Type: dns-01

Error information:
- Type: urn:ietf:params:acme:error:dns
- Details: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.my.domain - check that a DNS record exists for this domain


I didn't find any mention of the "shell" option in the documentation, so I'm not sure if i'm missing something, or if using acme.sh in the script is actually the right way of doing it ?
I found a 2y old post that seem to do every step manually with the freenas api, but I figure that it's a bit old and should somehow be "replaced" with the "shell" option.

Thanks
 

loicuv

Cadet
Joined
Jan 4, 2023
Messages
3
So after digging in the source code that handles the shell option, I found this very useful comment:
The authenticator script is called two times during the certificate generation:

1. The validation record creation which is called in the following way:
Code:
script set domain validation_name validaton_context timeout


2. The validation record deletion which is called in following way:
Code:
script unset domain validation_name validation_context


It is up to script implementation to handle both calls and perform the record creation.

That could perfectly be in the documentation.

Bottom line is, don't need to install acme.sh or anything, you just need to write a shell script that either creates the dns challenge record (with the data passed to the script) or deletes it.
 
Last edited:

DmSm

Cadet
Joined
Dec 3, 2022
Messages
3
So after digging in the source code that handles the shell option, I found this very useful comment:


That could perfectly be in the documentation.

Bottom line is, don't need to install acme.sh or anything, you just need to write a shell script that either creates the dns challenge record (with the data passed to the script) or deletes it.
Did you implement these scripts? Could you please share them?
 

FrostyCat

Explorer
Joined
Jan 4, 2022
Messages
79
Good find, I did move one of my domains from Google to CLoudflare just to be able to authenticate previously, I may just move it back and consolidate once again.
 

klaboor

Cadet
Joined
Jan 23, 2023
Messages
4
Whatever script you define as Authenticator script there are several parameters passed to script. Script is called twice during signing request.
1.
Code:
/mnt/blabla/customAcme.sh "set" "mydomain.eu" "_acme-challenge.mydomain.eu" "some43charactersLongTxtString"

2.
Code:
/mnt/blabla/customAcme.sh "unset" "mydomain.eu" "_acme-challenge.mydomain.eu" "some43charactersLongTxtString"

I agree this should be in documentation. I found it same way as loicuv did, in github commit comments.

Code itself is trivial. As it was mentioned, you need to add DNS TXT record and remove it.
Code:
#!/bin/bash

### FUNCTIONS
add_record(){
    domain=$1
    subdomain=$2
    $txtvalue=$3
    
    # Your DNS provider API code
}

del_record(){
    domain=$1
    subdomain=$2
    $txtvalue=$3
    
    # Your DNS provider API code
}

# Main
if [ "$1" == "set" ]; then
    add_record "${2}" "${3}" "${4}"
fi
if [ "$1" == "unset" ]; then
    del_record "${2}" "${3}" "${4}"
fi

Right now you need to code it itself. Every provider offer different methods so my code wont work for your provider. I took part of the acme.sh code related to my provider and modified it for my case but it was pain because it's all custom functions.
Or you can still use acme.sh issue cert functionality.
Best way would be open feature request for acme.sh to by able add and delete TXT records only since acme.sh already covers over hundreds of providers. I already opened an issue there. Not sure if this is correct way asking for new feature https://github.com/acmesh-official/acme.sh/issues/4472
 

DmSm

Cadet
Joined
Dec 3, 2022
Messages
3
Ah, too complicated. I ended up creating cron job calling a simple worker on Cloudflare to update DNS records.
 
Top