Hi,
My domain is: cliffrat.com & cliffrat.co.uk
I ran the same command for both domains, the following is for cliffrat.co.uk:-
certbot
certonly
--expand
--keep-until-expiring
--preferred-challenges dns
--non-interactive
--agree-tos
-m myemailaddress
--manual
--manual-auth-hook ./authenticate.sh
--manual-cleanup-hook ./cleanup.sh
-d *.cliffrat.co.uk
-d cliffrat.co.uk
authenticate.sh is as follows:-
#!/bin/bash
set -x
API_URL="https://api.hosting.ionos.com/dns/v1"
API_KEY_HEADER="X-API-Key:mykey"
Strip only the top domain to get the zone id
ZONE_NAME=$(expr match "$CERTBOT_DOMAIN" '..(...*)')
When already the TLD then use it
if [ -z "$ZONE_NAME" ]; then
ZONE_NAME="$CERTBOT_DOMAIN"
fi
Get the Ionos zone id
ZONE_RESPONSE=$(curl -s -X GET "$API_URL/zones"
-H "$API_KEY_HEADER"
-H "Accept: application/json")
ZONE_ID=$(echo $ZONE_RESPONSE
| python -c "import sys,json;response=json.load(sys.stdin);print(next((x for x in response if x['name']=='$ZONE_NAME'))['id'])")
Create TXT record
CREATE_DOMAIN="_acme-challenge.$CERTBOT_DOMAIN"
RECORD_CREATE_RESPONSE=$(curl -s -X POST "$API_URL/zones/$ZONE_ID/records"
-H "$API_KEY_HEADER"
-H "Content-Type: application/json"
--data '[{"name": "'"$CREATE_DOMAIN"'", "type": "TXT", "content": "'"$CERTBOT_VALIDATION"'", "ttl": 3600, "prio": 100, "disabled": false}]')
Save info for cleanup
echo $ZONE_ID > /tmp/CERTBOT_$CERTBOT_DOMAIN
Sleep to make sure the change has time to propagate over to DNS
sleep 25
cleanup.sh is as follows:-
#!/bin/bash
set -x
API_URL="https://api.hosting.ionos.com/dns/v1"
API_KEY_HEADER="X-API-Key:mykey"
if [ -f /tmp/CERTBOT_$CERTBOT_DOMAIN ]; then
ZONE_ID=$(cat /tmp/CERTBOT_$CERTBOT_DOMAIN)
rm -f /tmp/CERTBOT_$CERTBOT_DOMAIN
CREATE_DOMAIN="_acme-challenge.$CERTBOT_DOMAIN"
# request the created records
RECORD_GET_RESPONSE=$(curl -s -X GET "$API_URL/zones/$ZONE_ID?recordName=$CREATE_DOMAIN&recordType=TXT" \
-H "$API_KEY_HEADER" \
-H "Accept: application/json")
RECORD_IDS=$(echo $RECORD_GET_RESPONSE \
| python -c "import sys,json;records=json.load(sys.stdin)['records'];print('\n'.join([x['id'] for x in records]))")
fi
Remove the challenge TXT record from the zone
if [ -n "$ZONE_ID" -a -n "$RECORD_IDS" ]; then
echo "$RECORD_IDS"
| xargs -n1 -I {} curl -s -X DELETE "$API_URL/zones/$ZONE_ID/records/{}"
-H "$API_KEY_HEADER"
fi
It produced this output: cliffrat.com worked and a certificate was issued. cliffrat.co.uk failed with some challenges have failed. Also console output was as follows:-
Hook '--manual-auth-hook' for cliffrat.co.uk ran with error output:
- API_URL=https://api.hosting.ionos.com/dns/v1
- API_KEY_HEADER=X-API-Key:mykey
++ expr match cliffrat.co.uk '..(...*)' - ZONE_NAME=co.uk
- '[' -z co.uk ']'
++ curl -s -X GET https://api.hosting.ionos.com/dns/v1/zones -H X-API-Key:mykey -H 'Accept: application/json' - ZONE_RESPONSE='[{"name":"cliffrat.com","id":"blahblah","type":"NATIVE"},{"name":"cliffrat.co.uk","id":"blahblah","type":"NATIVE"}]'
++ echo '[{"name":"cliffrat.com","id":"blahblah","type":"NATIVE"},{"name":"cliffrat.co.uk","id":"blahblah","type":"NATIVE"}]'
++ python -c 'import sys,json;response=json.load(sys.stdin);print(next((x for x in response if x['''name''']=='''co.uk'''))['''id'''])'
Traceback (most recent call last):
File "", line 1, in
StopIteration - ZONE_ID=
- CREATE_DOMAIN=_acme-challenge.cliffrat.co.uk
++ curl -s -X POST https://api.hosting.ionos.com/dns/v1/zones//records -H X-API-Key:mykey -H 'Content-Type: application/json' --data '[{"name": "_acme-challenge.cliffrat.co.uk", "type": "TXT", "content": "blaahblah", "ttl": 3600, "prio": 100, "disabled": false}]' - RECORD_CREATE_RESPONSE='[{"code":"UNAUTHORIZED","message":"The customer is not authorized to do this operation."}]'
- echo
- sleep 25
Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
Domain: cliffrat.co.uk
Type: unauthorized
Detail: No TXT record found at _acme-challenge.cliffrat.co.uk
Both domains are with ionos and as far as I can see though my ionos account, both domains are set up exactly the same.
Also my apache vhost conf files are the same for both domains.
My web server is: apache 2.4.58
The operating system my web server runs on is: archlinux - linux 6.6.16-1-lts x86_64
My hosting provider is: ionos
I can login to a root shell on my machine: yes
I'm using a control panel to manage my site: no
The version of my client is: certbot 2.8.0
I am at a loss as to why it works for one domain and not the other, so any advice or suggestions, no matter how obvious, would be welcome.
Thanks