One Domain Issues Correctly; Second Does Not (ACME.sh)

My domain is:
saffiregrills.com

I ran this command:
acme.sh --issue -d saffiregrills.com -w /home/letsencrypt_challenge -k 4096 --force

It produced this output:

saffiregrills.com:Verify error:Invalid response from http://saffiregrills.com/.well-known/acme-challenge/db5cUqtv-cWSFzDTusGLudeoQwTTH8AymRbA0lASCtE [209.126.82.159]:

My web server is (include version):

NGINX

The operating system my web server runs on is (include version):

Debian 11

My hosting provider, if applicable, is:

Contabo

The version of my client is:

ACME.sh v3.0.2

Please note that I've tried running the same ACME.sh command with the --test argument, and everything appears to be working there. However when I remove --test I get the before-mentioned message.

I was able to successfully issue and install a certificate for a test website on the same server using (virtually) the same configuration files.

This is what the ACME.sh log says. Note that the first logged event is when using the --test argument, and the second is without it.

[Thu 18 Nov 2021 12:43:40 PM CST] Running cmd: issue
[Thu 18 Nov 2021 12:43:40 PM CST] _main_domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:40 PM CST] _alt_domains='no'
[Thu 18 Nov 2021 12:43:40 PM CST] Using config home:/root/.acme.sh
[Thu 18 Nov 2021 12:43:40 PM CST] Using ACME_DIRECTORY: https://acme-staging-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_DIRECTORY='https://acme-staging-v02.api.letsencrypt.org/directory'
[Thu 18 Nov 2021 12:43:40 PM CST] DOMAIN_PATH='/root/.acme.sh/saffiregrills.com'
[Thu 18 Nov 2021 12:43:40 PM CST] Le_NextRenewTime='1642356132'
[Thu 18 Nov 2021 12:43:40 PM CST] Using ACME_DIRECTORY: https://acme-staging-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:40 PM CST] _init api for server: https://acme-staging-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:40 PM CST] Retrying GET
[Thu 18 Nov 2021 12:43:40 PM CST] GET
[Thu 18 Nov 2021 12:43:40 PM CST] url='https://acme-staging-v02.api.letsencrypt.org/directory'
[Thu 18 Nov 2021 12:43:40 PM CST] timeout=
[Thu 18 Nov 2021 12:43:40 PM CST] displayError='1'
[Thu 18 Nov 2021 12:43:40 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:43:40 PM CST] ret='0'
[Thu 18 Nov 2021 12:43:40 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_KEY_CHANGE='https://acme-staging-v02.api.letsencrypt.org/acme/key-change'
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_NEW_AUTHZ
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_NEW_ORDER='https://acme-staging-v02.api.letsencrypt.org/acme/new-order'
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_NEW_ACCOUNT='https://acme-staging-v02.api.letsencrypt.org/acme/new-acct'
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_REVOKE_CERT='https://acme-staging-v02.api.letsencrypt.org/acme/revoke-cert'
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_AGREEMENT='https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf'
[Thu 18 Nov 2021 12:43:40 PM CST] ACME_NEW_NONCE='https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce'
[Thu 18 Nov 2021 12:43:40 PM CST] Using CA: https://acme-staging-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:40 PM CST] _on_before_issue
[Thu 18 Nov 2021 12:43:40 PM CST] _chk_main_domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:40 PM CST] _chk_alt_domains
[Thu 18 Nov 2021 12:43:40 PM CST] Le_LocalAddress
[Thu 18 Nov 2021 12:43:40 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:43:40 PM CST] Check for domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:40 PM CST] _currentRoot='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:43:40 PM CST] d
[Thu 18 Nov 2021 12:43:40 PM CST] _saved_account_key_hash is not changed, skip register account.
[Thu 18 Nov 2021 12:43:40 PM CST] Read key length:4096
[Thu 18 Nov 2021 12:43:40 PM CST] _createcsr
[Thu 18 Nov 2021 12:43:40 PM CST] Single domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:40 PM CST] Getting domain auth token for each domain
[Thu 18 Nov 2021 12:43:40 PM CST] d
[Thu 18 Nov 2021 12:43:40 PM CST] url='https://acme-staging-v02.api.letsencrypt.org/acme/new-order'
[Thu 18 Nov 2021 12:43:40 PM CST] payload='{"identifiers": [{"type":"dns","value":"saffiregrills.com"}]}'
[Thu 18 Nov 2021 12:43:40 PM CST] RSA key
[Thu 18 Nov 2021 12:43:40 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:40 PM CST] HEAD
[Thu 18 Nov 2021 12:43:40 PM CST] _post_url='https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce'
[Thu 18 Nov 2021 12:43:40 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L  -I  '
[Thu 18 Nov 2021 12:43:41 PM CST] _ret='0'
[Thu 18 Nov 2021 12:43:41 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:41 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:41 PM CST] POST
[Thu 18 Nov 2021 12:43:41 PM CST] _post_url='https://acme-staging-v02.api.letsencrypt.org/acme/new-order'
[Thu 18 Nov 2021 12:43:41 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:43:41 PM CST] _ret='0'
[Thu 18 Nov 2021 12:43:41 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:41 PM CST] code='201'
[Thu 18 Nov 2021 12:43:41 PM CST] Le_LinkOrder='https://acme-staging-v02.api.letsencrypt.org/acme/order/33016618/1052470758'
[Thu 18 Nov 2021 12:43:41 PM CST] Le_OrderFinalize='https://acme-staging-v02.api.letsencrypt.org/acme/finalize/33016618/1052470758'
[Thu 18 Nov 2021 12:43:41 PM CST] url='https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/970537198'
[Thu 18 Nov 2021 12:43:41 PM CST] payload
[Thu 18 Nov 2021 12:43:41 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:41 PM CST] POST
[Thu 18 Nov 2021 12:43:41 PM CST] _post_url='https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/970537198'
[Thu 18 Nov 2021 12:43:41 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:43:41 PM CST] _ret='0'
[Thu 18 Nov 2021 12:43:41 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:41 PM CST] code='200'
[Thu 18 Nov 2021 12:43:41 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:43:41 PM CST] Getting webroot for domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:41 PM CST] _w='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:43:41 PM CST] _currentRoot='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:43:41 PM CST] entry='"type":"http-01","status":"valid","url":"https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/970537198/4rSs-w","token":"whBndl4RI3mi15ddedSu-YaPOTKzxwj7UfY1G8O_fDA","validationRecord":[{"url":"http://saffiregrills.com/.well-known/acme-challenge/whBndl4RI3mi15ddedSu-YaPOTKzxwj7UfY1G8O_fDA","hostname":"saffiregrills.com","port":"80","addressesResolved":["209.126.82.159"],"addressUsed":"209.126.82.159"'
[Thu 18 Nov 2021 12:43:41 PM CST] token='whBndl4RI3mi15ddedSu-YaPOTKzxwj7UfY1G8O_fDA'
[Thu 18 Nov 2021 12:43:41 PM CST] uri='https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/970537198/4rSs-w'
[Thu 18 Nov 2021 12:43:41 PM CST] keyauthorization='whBndl4RI3mi15ddedSu-YaPOTKzxwj7UfY1G8O_fDA.fcHR9WoxAWKq4bE9Z2wi-QEjbx267x4ivNTiwXeV-yg'
[Thu 18 Nov 2021 12:43:41 PM CST] saffiregrills.com is already verified.
[Thu 18 Nov 2021 12:43:41 PM CST] keyauthorization='verified_ok'
[Thu 18 Nov 2021 12:43:41 PM CST] dvlist='saffiregrills.com#verified_ok#https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/970537198/4rSs-w#http-01#/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:43:41 PM CST] d
[Thu 18 Nov 2021 12:43:41 PM CST] vlist='saffiregrills.com#verified_ok#https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/970537198/4rSs-w#http-01#/home/letsencrypt_challenge,'
[Thu 18 Nov 2021 12:43:41 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:43:41 PM CST] saffiregrills.com is already verified, skip http-01.
[Thu 18 Nov 2021 12:43:41 PM CST] ok, let's start to verify
[Thu 18 Nov 2021 12:43:41 PM CST] saffiregrills.com is already verified, skip http-01.
[Thu 18 Nov 2021 12:43:41 PM CST] pid
[Thu 18 Nov 2021 12:43:41 PM CST] No need to restore nginx, skip.
[Thu 18 Nov 2021 12:43:41 PM CST] _clearupdns
[Thu 18 Nov 2021 12:43:41 PM CST] dns_entries
[Thu 18 Nov 2021 12:43:41 PM CST] skip dns.
[Thu 18 Nov 2021 12:43:41 PM CST] Verify finished, start to sign.
[Thu 18 Nov 2021 12:43:41 PM CST] i='2'
[Thu 18 Nov 2021 12:43:41 PM CST] j='26'
[Thu 18 Nov 2021 12:43:41 PM CST] Lets finalize the order.
[Thu 18 Nov 2021 12:43:41 PM CST] Le_OrderFinalize='https://acme-staging-v02.api.letsencrypt.org/acme/finalize/33016618/1052470758'
[Thu 18 Nov 2021 12:43:41 PM CST] url='https://acme-staging-v02.api.letsencrypt.org/acme/finalize/33016618/1052470758'
[Thu 18 Nov 2021 12:43:41 PM CST] payload='{"csr": "MIIEkDCCAngCAQAwHDEaMBgGA1UE..."}'
[Thu 18 Nov 2021 12:43:41 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:41 PM CST] POST
[Thu 18 Nov 2021 12:43:41 PM CST] _post_url='https://acme-staging-v02.api.letsencrypt.org/acme/finalize/33016618/1052470758'
[Thu 18 Nov 2021 12:43:41 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:43:42 PM CST] _ret='0'
[Thu 18 Nov 2021 12:43:42 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:42 PM CST] code='200'
[Thu 18 Nov 2021 12:43:42 PM CST] Order status is valid.
[Thu 18 Nov 2021 12:43:42 PM CST] Le_LinkCert='https://acme-staging-v02.api.letsencrypt.org/acme/cert/fa49f0687bfe63f6be5fa1acd4876ddcfed6'
[Thu 18 Nov 2021 12:43:42 PM CST] Downloading cert.
[Thu 18 Nov 2021 12:43:42 PM CST] Le_LinkCert='https://acme-staging-v02.api.letsencrypt.org/acme/cert/fa49f0687bfe63f6be5fa1acd4876ddcfed6'
[Thu 18 Nov 2021 12:43:42 PM CST] url='https://acme-staging-v02.api.letsencrypt.org/acme/cert/fa49f0687bfe63f6be5fa1acd4876ddcfed6'
[Thu 18 Nov 2021 12:43:42 PM CST] payload
[Thu 18 Nov 2021 12:43:42 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:42 PM CST] POST
[Thu 18 Nov 2021 12:43:42 PM CST] _post_url='https://acme-staging-v02.api.letsencrypt.org/acme/cert/fa49f0687bfe63f6be5fa1acd4876ddcfed6'
[Thu 18 Nov 2021 12:43:42 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:43:42 PM CST] _ret='0'
[Thu 18 Nov 2021 12:43:42 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:42 PM CST] code='200'
[Thu 18 Nov 2021 12:43:42 PM CST] Found cert chain
[Thu 18 Nov 2021 12:43:42 PM CST] _end_n='36'
[Thu 18 Nov 2021 12:43:42 PM CST] Le_LinkCert='https://acme-staging-v02.api.letsencrypt.org/acme/cert/fa49f0687bfe63f6be5fa1acd4876ddcfed6'
[Thu 18 Nov 2021 12:43:42 PM CST] e[1;32mCert success.e[0m
[Thu 18 Nov 2021 12:43:42 PM CST] Your cert is in: e[1;32m/root/.acme.sh/saffiregrills.com/saffiregrills.com.cere[0m
[Thu 18 Nov 2021 12:43:42 PM CST] Your cert key is in: e[1;32m/root/.acme.sh/saffiregrills.com/saffiregrills.com.keye[0m
[Thu 18 Nov 2021 12:43:42 PM CST] The intermediate CA cert is in: e[1;32m/root/.acme.sh/saffiregrills.com/ca.cere[0m
[Thu 18 Nov 2021 12:43:42 PM CST] And the full chain certs is there: e[1;32m/root/.acme.sh/saffiregrills.com/fullchain.cere[0m
[Thu 18 Nov 2021 12:43:42 PM CST] _on_issue_success
[Thu 18 Nov 2021 12:43:58 PM CST] Running cmd: issue
[Thu 18 Nov 2021 12:43:58 PM CST] _main_domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:58 PM CST] _alt_domains='no'
[Thu 18 Nov 2021 12:43:58 PM CST] Using config home:/root/.acme.sh
[Thu 18 Nov 2021 12:43:58 PM CST] default_acme_server='https://acme-v02.api.letsencrypt.org/directory'
[Thu 18 Nov 2021 12:43:58 PM CST] ACME_DIRECTORY='https://acme-v02.api.letsencrypt.org/directory'
[Thu 18 Nov 2021 12:43:58 PM CST] DOMAIN_PATH='/root/.acme.sh/saffiregrills.com'
[Thu 18 Nov 2021 12:43:58 PM CST] Le_NextRenewTime='1642358622'
[Thu 18 Nov 2021 12:43:58 PM CST] Using ACME_DIRECTORY: https://acme-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:58 PM CST] _init api for server: https://acme-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:58 PM CST] Retrying GET
[Thu 18 Nov 2021 12:43:58 PM CST] GET
[Thu 18 Nov 2021 12:43:58 PM CST] url='https://acme-v02.api.letsencrypt.org/directory'
[Thu 18 Nov 2021 12:43:58 PM CST] timeout=
[Thu 18 Nov 2021 12:43:58 PM CST] displayError='1'
[Thu 18 Nov 2021 12:43:58 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:43:59 PM CST] ret='0'
[Thu 18 Nov 2021 12:43:59 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_KEY_CHANGE='https://acme-v02.api.letsencrypt.org/acme/key-change'
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_NEW_AUTHZ
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_NEW_ORDER='https://acme-v02.api.letsencrypt.org/acme/new-order'
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_NEW_ACCOUNT='https://acme-v02.api.letsencrypt.org/acme/new-acct'
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_REVOKE_CERT='https://acme-v02.api.letsencrypt.org/acme/revoke-cert'
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_AGREEMENT='https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf'
[Thu 18 Nov 2021 12:43:59 PM CST] ACME_NEW_NONCE='https://acme-v02.api.letsencrypt.org/acme/new-nonce'
[Thu 18 Nov 2021 12:43:59 PM CST] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Thu 18 Nov 2021 12:43:59 PM CST] _on_before_issue
[Thu 18 Nov 2021 12:43:59 PM CST] _chk_main_domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:59 PM CST] _chk_alt_domains
[Thu 18 Nov 2021 12:43:59 PM CST] Le_LocalAddress
[Thu 18 Nov 2021 12:43:59 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:43:59 PM CST] Check for domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:59 PM CST] _currentRoot='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:43:59 PM CST] d
[Thu 18 Nov 2021 12:43:59 PM CST] _saved_account_key_hash is not changed, skip register account.
[Thu 18 Nov 2021 12:43:59 PM CST] Read key length:4096
[Thu 18 Nov 2021 12:43:59 PM CST] _createcsr
[Thu 18 Nov 2021 12:43:59 PM CST] Single domain='saffiregrills.com'
[Thu 18 Nov 2021 12:43:59 PM CST] Getting domain auth token for each domain
[Thu 18 Nov 2021 12:43:59 PM CST] d
[Thu 18 Nov 2021 12:43:59 PM CST] url='https://acme-v02.api.letsencrypt.org/acme/new-order'
[Thu 18 Nov 2021 12:43:59 PM CST] payload='{"identifiers": [{"type":"dns","value":"saffiregrills.com"}]}'
[Thu 18 Nov 2021 12:43:59 PM CST] RSA key
[Thu 18 Nov 2021 12:43:59 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:59 PM CST] HEAD
[Thu 18 Nov 2021 12:43:59 PM CST] _post_url='https://acme-v02.api.letsencrypt.org/acme/new-nonce'
[Thu 18 Nov 2021 12:43:59 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L  -I  '
[Thu 18 Nov 2021 12:43:59 PM CST] _ret='0'
[Thu 18 Nov 2021 12:43:59 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:43:59 PM CST] Retrying post
[Thu 18 Nov 2021 12:43:59 PM CST] POST
[Thu 18 Nov 2021 12:43:59 PM CST] _post_url='https://acme-v02.api.letsencrypt.org/acme/new-order'
[Thu 18 Nov 2021 12:43:59 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:44:00 PM CST] _ret='0'
[Thu 18 Nov 2021 12:44:00 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:44:00 PM CST] code='201'
[Thu 18 Nov 2021 12:44:00 PM CST] Le_LinkOrder='https://acme-v02.api.letsencrypt.org/acme/order/269397360/40688649710'
[Thu 18 Nov 2021 12:44:00 PM CST] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/269397360/40688649710'
[Thu 18 Nov 2021 12:44:00 PM CST] url='https://acme-v02.api.letsencrypt.org/acme/authz-v3/50552245760'
[Thu 18 Nov 2021 12:44:00 PM CST] payload
[Thu 18 Nov 2021 12:44:00 PM CST] Retrying post
[Thu 18 Nov 2021 12:44:00 PM CST] POST
[Thu 18 Nov 2021 12:44:00 PM CST] _post_url='https://acme-v02.api.letsencrypt.org/acme/authz-v3/50552245760'
[Thu 18 Nov 2021 12:44:00 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:44:00 PM CST] _ret='0'
[Thu 18 Nov 2021 12:44:00 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:44:00 PM CST] code='200'
[Thu 18 Nov 2021 12:44:00 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:44:00 PM CST] Getting webroot for domain='saffiregrills.com'
[Thu 18 Nov 2021 12:44:00 PM CST] _w='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:44:00 PM CST] _currentRoot='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:44:00 PM CST] entry='"type":"http-01","status":"pending","url":"https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q","token":"wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U"'
[Thu 18 Nov 2021 12:44:00 PM CST] token='wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U'
[Thu 18 Nov 2021 12:44:00 PM CST] uri='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:00 PM CST] keyauthorization='wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U.9JbDAt52tYklhk77W_jKxQigPP_N_FBRVaqW8PqvCKc'
[Thu 18 Nov 2021 12:44:00 PM CST] dvlist='saffiregrills.com#wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U.9JbDAt52tYklhk77W_jKxQigPP_N_FBRVaqW8PqvCKc#https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q#http-01#/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:44:00 PM CST] d
[Thu 18 Nov 2021 12:44:00 PM CST] vlist='saffiregrills.com#wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U.9JbDAt52tYklhk77W_jKxQigPP_N_FBRVaqW8PqvCKc#https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q#http-01#/home/letsencrypt_challenge,'
[Thu 18 Nov 2021 12:44:00 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:44:00 PM CST] ok, let's start to verify
[Thu 18 Nov 2021 12:44:00 PM CST] Verifying: saffiregrills.com
[Thu 18 Nov 2021 12:44:00 PM CST] d='saffiregrills.com'
[Thu 18 Nov 2021 12:44:00 PM CST] keyauthorization='wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U.9JbDAt52tYklhk77W_jKxQigPP_N_FBRVaqW8PqvCKc'
[Thu 18 Nov 2021 12:44:00 PM CST] uri='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:00 PM CST] _currentRoot='/home/letsencrypt_challenge'
[Thu 18 Nov 2021 12:44:00 PM CST] wellknown_path='/home/letsencrypt_challenge/.well-known/acme-challenge'
[Thu 18 Nov 2021 12:44:00 PM CST] writing token:wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U to /home/letsencrypt_challenge/.well-known/acme-challenge/wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U
[Thu 18 Nov 2021 12:44:00 PM CST] Changing owner/group of .well-known to root:server_nginx
[Thu 18 Nov 2021 12:44:00 PM CST] url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:00 PM CST] payload='{}'
[Thu 18 Nov 2021 12:44:00 PM CST] Retrying post
[Thu 18 Nov 2021 12:44:00 PM CST] POST
[Thu 18 Nov 2021 12:44:00 PM CST] _post_url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:00 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:44:00 PM CST] _ret='0'
[Thu 18 Nov 2021 12:44:00 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:44:00 PM CST] code='200'
[Thu 18 Nov 2021 12:44:00 PM CST] trigger validation code: 200
[Thu 18 Nov 2021 12:44:00 PM CST] Pending, The CA is processing your order, please just wait. (1/30)
[Thu 18 Nov 2021 12:44:00 PM CST] sleep 2 secs to verify again
[Thu 18 Nov 2021 12:44:02 PM CST] checking
[Thu 18 Nov 2021 12:44:02 PM CST] url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:02 PM CST] payload
[Thu 18 Nov 2021 12:44:03 PM CST] Retrying post
[Thu 18 Nov 2021 12:44:03 PM CST] POST
[Thu 18 Nov 2021 12:44:03 PM CST] _post_url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:03 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:44:03 PM CST] _ret='0'
[Thu 18 Nov 2021 12:44:03 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:44:03 PM CST] code='200'
[Thu 18 Nov 2021 12:44:03 PM CST] saffiregrills.com:Verify error:Invalid response from http://saffiregrills.com/.well-known/acme-challenge/wohL-9x2oQMsqkk8zHsKE7rkH_629pWc3OaV-lI6M-U [209.126.82.159]: 
[Thu 18 Nov 2021 12:44:03 PM CST] pid
[Thu 18 Nov 2021 12:44:03 PM CST] No need to restore nginx, skip.
[Thu 18 Nov 2021 12:44:03 PM CST] _clearupdns
[Thu 18 Nov 2021 12:44:03 PM CST] dns_entries
[Thu 18 Nov 2021 12:44:03 PM CST] skip dns.
[Thu 18 Nov 2021 12:44:03 PM CST] _on_issue_err
[Thu 18 Nov 2021 12:44:03 PM CST] Please check log file for more details: /root/.acme.sh/acme.sh.log
[Thu 18 Nov 2021 12:44:03 PM CST] url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:03 PM CST] payload='{}'
[Thu 18 Nov 2021 12:44:03 PM CST] Retrying post
[Thu 18 Nov 2021 12:44:03 PM CST] POST
[Thu 18 Nov 2021 12:44:03 PM CST] _post_url='https://acme-v02.api.letsencrypt.org/acme/chall-v3/50552245760/TgkI-Q'
[Thu 18 Nov 2021 12:44:03 PM CST] _CURL='curl --silent --dump-header /root/.acme.sh/http.header  -L '
[Thu 18 Nov 2021 12:44:03 PM CST] _ret='0'
[Thu 18 Nov 2021 12:44:03 PM CST] _hcode='0'
[Thu 18 Nov 2021 12:44:03 PM CST] code='400'

Here is what my website configuration file looks like right now. Note that several sections have been commented out in the meantime until I can get this fixed.

###
# HTTP Redirect Server Block
###
#server {
#	listen 80;
#	listen [::]:80;
#
#	server_name saffiregrills.com www.saffiregrills.com;
#
#	return 301 https://saffiregrills.com$request_uri;
#}

###
# Main/HTTPS Server Block
###
server {
	listen 80 default_server;
	listen [::]:80 default_server;

#	listen 443 ssl http2 default_server;
#	listen [::]:443 ssl http2 default_server;

	root /home/main_dbe46/saffiregrills.com;

	# Add index.php to the list if you are using PHP
	index index.html index.php;

	server_name saffiregrills.com;

	##
	# SSL configuration
	##
	# SSL/TLS Certificates
	ssl_certificate /etc/nginx/ssl/saffiregrills.com/saffiregrills.com.cer;
	ssl_certificate_key /etc/nginx/ssl/saffiregrills.com/saffiregrills.com.key;

	# Huffie-Hellman Group File
	ssl_dhparam /etc/nginx/ssl/saffiregrills.com/dhparams.pem;

	# Let's Encrypt Root for SSL/TLS Certificate Challenge Responses
	include includes/letsencrypt_challenge;

	##
	# Sitewide Location Rules
	##
	location / {
		# Control Order Nginx Will Use to Match File System to URL Request
		try_files $uri $uri/ /index.php;

		# Limit Request Types to GET and POST
		limit_except GET POST {
			deny all;
		}
	}

	##
	# Location Rules for All PHP Files
	##
	location ~* \.php$ {
		# PHP FPM Processing
		# Block PHP FPM From Executing Code in Uploads Directory
		if ($uri !~ "^/uploads/") {
			# Execute PHP FPM
			fastcgi_pass unix:/run/php/php8.0-fpm_saffiregrills.com.sock;
		}

		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_param SCRIPT_NAME $fastcgi_script_name;
	}

	##
	# Location Rules for All . Files
	##
	# Hide Dot Type Files For Security Reasons
	location ~* /\. {
		return 404;
	}

	##
	# Hide SQL, Backup, and Temporary Files
	##
	location ~* \.(?:sql|bak|php~|php#|save|swp|swo|tmp)$ {
		return 404;
	}

	##
	# Location Rules for All Image Files
	##
	# Client Side Caching of Static Content
	# Cache Image Files
	location ~* \.(?:ico|gif|jpe?g|png|webp|svg)$ {
		expires 1d;
		access_log off;
		log_not_found off;
		add_header Cache-Control private;
		open_file_cache max=3000 inactive=120s;
		open_file_cache_valid 120s;
		open_file_cache_min_uses 4;
		open_file_cache_errors on;
	}

	##
	# Location Rules for All Font Files
	##
	# Cache Font Files
	location ~* \.(?:otf|ttf|eot|woff|woff2)$ {
		expires 30d;
		access_log off;
		log_not_found off;
		add_header Cache-Control private;
		open_file_cache max=3000 inactive=120s;
		open_file_cache_valid 120s;
		open_file_cache_min_uses 4;
		open_file_cache_errors on;
	}

	##
	# Location Rules for All CSS, JS, HTML, and XML Files
	##
	# Cache CSS, JavaScript, HTML, and XML Files
	location ~* \.(css|js|html|xml)$ {
		expires 48h;
		access_log on;
		add_header Cache-Control public;
	}

	##
	# Hide PHP Files in Locations Where Hackers May Attempt to Run Malicious Code Previously Uploaded
	##
	location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/*.php$ {
		return 404;
		access_log off;
		log_not_found off;
	}

	##
	# Specific Location Rules
	##
	# Deny Access to Wordpress' XMLRPC for Security, and to Save Memory Consumption
	location /xmlrpc.php {
		deny all;
	}

	##
	# Gzip Settings
	##
	gzip on;
	gzip_comp_level 6;
	gzip_min_length 5120;
	gzip_types
		text/plain
		text/css
		application/javascript
		application/json
		application/x-font-ttf
		font/opentype
		image/svg+xml
		image/x-icon;

	gunzip on;

	##
	# Rate Limiting
	##
	# Limite Server Requests to 900,000 above the 100,000 Limit in nginx.conf, With Delays Over 100,000
	limit_req zone=server burst=900000;

	# Limit Requests to 400 per IP Over the 100 Limit in nginx.conf, With Delays Over 100
	limit_req zone=per-ip burst=400;

	##
	# Header Settings
	##
	##
	# Header Configuration
	##
	# Enforce Strict Transport Security
#	add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

	# Disallow Sniffing Byte Order to Help Prevent XSS
	add_header X-Content-Type-Options nosniff;

	# Disallow Embeds and IFrames from Any Other Website; Replaced with Content-Security-Policy frame-ancestors
	add_header X-Frame-Options SAMEORIGIN;

	# Tell Browsers to Turn on XSS Protection, If Disabled By User; Replaced with Content-Security-Policy reflected-xss
	add_header X-XSS-Protection "1; mode=block";

	# Only Load Content From This Server
	add_header X-Permitted-Cross-Domain-Policies master-only;

	# Prevent Browser From Sharing Link Origin with Linked Websites
	add_header Referrer-Policy SAMEORIGIN;

	# Miscellaneous XSS Protection Measures; Allows Loading Images from Anywhere; Automatically Loads Resources with HTTPS over HTTP, Etc.
	# See 1) https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
	# See 2) https://research.nccgroup.com/wp-content/uploads/2020/07/csp_best_practices.pdf
#	add_header Content-Security-Policy "default-src 'self'; object-src 'none'; reflected-xss; upgrade-insecure-requests; img-src 'self' https: data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline'; font-src 'self' https:";
}

What's the content of the above file?

3 Likes

I was wondering if you would ask.

# /etc/nginx/includes/letsencrypt_challenge

location /.well-known/acme-challenge/ {
    alias /home/letsencrypt_challenge/.well-known/acme-challenge/;
}

The file follows this guide, which worked for a test domain that came with this new server.

And what if you put a test file at /home/letsencrypt_challenge/.well-known/acme-challenge/ ? E.g.:

echo "test" > /home/letsencrypt_challenge/.well-known/acme-challenge/1234

That file should become available at http://saffiregrills.com/.well-known/acme-challenge/1234

3 Likes

It returned 404. I then commented out this line in the saffiregrills.com.conf file.

        ##
        # Location Rules for All . Files
        ##
        # Hide Dot Type Files For Security Reasons
#       location ~* /\. {
#               return 404;
#       }

It now says unable to connect.

Please excuse me for being totally new to setting up a NGINX server. I've studied several guides, but am still a beginner.

Thank you very much for trying to help in this matter, by the way.

I'm sorry, scratch that. It was because my config file referenced the TLS certificate files, when they weren't installed yet. I've commented out those lines and I'm getting a 404 error again after I restart NGINX.

I can now download the test file. Try running acme.sh again.

2 Likes

No, you were on the right track. That location would have returned a 404 for the acme challenge requests to /.well-known/acme-challenge. You can make a location just for that to avoid collision. Or make a better regex.

You can just comment out the lines for your certificate files if they do not yet exist. You are only listening to port 80 anyway so they are not needed.

Or, you could create a self-signed cert and use that temporarily. But, best for now to comment out I think.

2 Likes

Ah, great! So that was it. That code is meant to restrict access to files like .htaccess (where present), .ini, and so on. Do you happen to know of a rewrite to the following snippet for NGINX that would do that without also blocking .well-known?

##
        # Location Rules for All . Files
        ##
        # Hide Dot Type Files For Security Reasons
#       location ~* /\. {
#               return 404;
#       }

As @MikeMcQ said, I'm still seeing a 404 in my browser. How did you download the TXT, using wget? I would like to know so I can verify it is accessible in the future if I make any configuration changes.

Which regex would you suggest?

Using curl but that's almost the same as wget. I just like curl more for debugging servers:

osiris@erazer ~ $ curl -Lv http://saffiregrills.com/.well-known/acme-challenge/1234
*   Trying 209.126.82.159:80...
* Connected to saffiregrills.com (209.126.82.159) port 80 (#0)
> GET /.well-known/acme-challenge/1234 HTTP/1.1
> Host: saffiregrills.com
> User-Agent: curl/7.77.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 18 Nov 2021 19:18:58 GMT
< Content-Type: application/octet-stream
< Content-Length: 5
< Last-Modified: Thu, 18 Nov 2021 19:07:38 GMT
< Connection: keep-alive
< ETag: "6196a47a-5"
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< X-Permitted-Cross-Domain-Policies: master-only
< Referrer-Policy: SAMEORIGIN
< Accept-Ranges: bytes
< 
test
* Connection #0 to host saffiregrills.com left intact
osiris@erazer ~ $ 
2 Likes

Great, thanks. That's good to know. I am not very familiar with curl or wget, although I know about them. I should probably start using curl more often.

Thank you again for your help!

1 Like

I've changed the regex to the following. It seems to be working so far, as I am still able to access the file using curl, like @Osiris mentioned.

        ##
        # Location Rules for All . Files
        ##
        # Hide Dot Type Files For Security Reasons
        location ~* /\.(^well-known) {
                return 404;
        }

Maybe someone else will come across this and it will help them too. There doesn't seem to be much documentation on NGINX regular expressions, unfortunately. They are clearly different than PHP and JS regular expressions in some ways.

1 Like

Well, you might not need that one for "." at all. There are no .htaccess files with nginx so if you do not have any others just leave it out.

Otherwise, you could add a location like below and that should take precedence over less qualified ones (I did not study all of yours). You can read about nginx location precedence in their docs. I like to test by putting an odd return code like 418 in a location to see when it triggers. Shown below but remove the "return" line for actual use :slight_smile:

location /.well-known/acme-challenge/ {
   return 418;
}
3 Likes

I've seen this stuff at other sites too, blocking .ht* files on nginx. Even if nginx doesn't use .ht* files, it doesn't mean webapps install them anyway, being ignorant of the webserver used. Most .ht* files are benign, but you probably don't want to leak your .htpasswd files.

2 Likes

That's a good idea, using a unique return code. I'll have to remember that.

1 Like

Thanks to both of you!

2 Likes