LetsEncrypt DNS Validation Template Using Cloudflare

Hi @LotusJeff,

A Cloudflare 521 means Cloudflare could not connect to your server at all. It is not a certificate error (a bad certificate gives a 525 or 526). So nginx in the Discourse container was not running. I assume your main domain shows the same error because it points at the same server. The DNS plugin only adds and removes one TXT record. It does not change any A or CNAME records.

Is it trying to create a wildcard? No. The stock script asks for a certificate for DISCOURSE_HOSTNAME only, plus any names in DISCOURSE_HOSTNAME_ALIASES. acme.sh adds a TXT record _acme-challenge.forum.website.tld, waits for Let’s Encrypt to check it, and then deletes it. If you use DISCOURSE_HOSTNAME_ALIASES, all of those names must be in the zone that CF_Zone_ID points to.

How do I force a new certificate? Moving the old letsencrypt folder aside before the rebuild is the force. With an empty folder, acme.sh has no certificate to keep, so it does a new DNS validation at the next start. Please don’t repeat --force runs: each run that works issues two certificates (RSA and ECDSA), and Let’s Encrypt allows only 5 certificates for the same hostname in 7 days.

Why nginx did not start. The Let’s Encrypt script runs at container start, before nginx. If you moved the folder aside, there are two likely causes:

  1. It was still waiting. With DNS validation, acme.sh waits until the TXT record shows in public DNS. With Cloudflare this normally takes less than a minute. But if the record does not show, acme.sh waits up to 20 minutes for each certificate, and Cloudflare shows 521 for all of that time.
  2. The DNS step failed. Then the stock script still writes empty files into shared/ssl, and nginx cannot start.

If you did not move the folder aside, acme.sh skips the DNS step until renewal is due, so the 521 more likely came from the rebuild itself. Check that you added my lines to the existing templates:, env: and run: sections of app.yml, and did not add new ones. The stock app.yml already has a run: section at the bottom. If a key is in the file twice, only the last one counts.

Find the cause. The acme.sh log stays in the shared folder after a rebuild, so it still has the errors from the failed start:

cd /var/discourse
grep -a -i -E 'error|invalid|can not find|timed out|cert success' shared/standalone/letsencrypt*/acme.sh.log | tail -n 40

Feel free to post the output here. acme.sh does not write the token to this log at its default log level, but check the lines before you post.

Test before you try again. This does a full DNS validation against the Let’s Encrypt staging server, from a temporary folder inside the running container. It does not touch your live certificates or the production rate limit, so your forum stays up:

cd /var/discourse
./launcher enter app

mkdir -p /tmp/acme-test/dnsapi
curl -fsSL https://raw.githubusercontent.com/acmesh-official/acme.sh/3.0.6/acme.sh -o /tmp/acme-test/acme.sh
curl -fsSL https://raw.githubusercontent.com/acmesh-official/acme.sh/3.0.6/dnsapi/dns_cf.sh -o /tmp/acme-test/dnsapi/dns_cf.sh
chmod +x /tmp/acme-test/acme.sh
CF_Token="YOUR_TOKEN" CF_Zone_ID="YOUR_ZONE_ID" /tmp/acme-test/acme.sh --home /tmp/acme-test \
  --server letsencrypt_test --issue --dns dns_cf -d forum.website.tld

rm -rf /tmp/acme-test
exit

If it ends with Cert success., your token, zone ID and DNS are fine, and the problem is in the app.yml changes. If it fails, the error tells you why. For example, invalid domain usually means a wrong zone ID, or a token that has no access to that zone.

When you rebuild again, watch the start with docker logs -f app and give it a few minutes before you revert. You should see Cert success. twice, and then nginx starts.