Web & Networking

Troubleshooting Google Public CA and acme.sh

A focused troubleshooting companion for Google Public CA EAB registration, DNS-01 validation, installation, and renewal with acme.sh.

3 min readUpdated Sunday, Aug 16, 2026
#ssl#tls#troubleshooting#acme.sh#google-cloud

A certificate troubleshooting illustration

Start with the current setup guide: Google Trust Services Certificates with acme.sh. This companion intentionally avoids guessed quotas and destructive “reset everything” commands.

EAB registration fails

Confirm four facts before changing local state:

  1. The selected Google Cloud project is the project that created the EAB secret.
  2. publicca.googleapis.com is enabled.
  3. The caller can create external account keys.
  4. keyId and b64MacKey were copied as complete, separate values.

Google documents two easy-to-miss rules: the EAB secret must be used within seven days and can register only one ACME account. If it expired or was consumed, create a new secret. Do not delete acme.sh’s internal CA directory as a first response.

Check the client and server selection:

~/.acme.sh/acme.sh --version
~/.acme.sh/acme.sh --register-account \
  --server google \
  --accountemail admin@example.com \
  --eab-kid 'YOUR_KEY_ID' \
  --eab-hmac-key 'YOUR_B64_MAC_KEY' \
  --debug 2

Do not paste debug output publicly before checking it for credentials and account identifiers. Production and staging are separate ACME environments; do not assume an EAB secret from one will register an account in the other.

DNS-01 validation fails

Find the authoritative name servers, then ask one directly for the challenge record:

dig +short NS example.com
dig @ns1.example-dns.net +short TXT _acme-challenge.example.com

If the authoritative server lacks the expected value, waiting on a public resolver will not repair the API call. Check that the Cloudflare token is limited to the correct zone, has DNS edit permission, and that CF_Zone_ID belongs to that zone.

For a certificate containing both example.com and *.example.com, two authorizations can use the same TXT owner. Multiple temporary TXT values may legitimately coexist. Do not delete records blindly while another order is active.

The website still serves the old certificate

Inspect the public endpoint:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -serial -issuer -dates

If issuance succeeded but this output did not change, inspect the file paths configured in the web server. Usually the answer is not another issuance; it is installing to stable paths and successfully reloading the service:

~/.acme.sh/acme.sh --install-cert --ecc -d example.com \
  --key-file /etc/nginx/ssl/example.com/privkey.pem \
  --fullchain-file /etc/nginx/ssl/example.com/fullchain.pem \
  --reloadcmd 'sudo nginx -t && sudo systemctl reload nginx'

--install-cert saves the reload action for renewals. Serving files directly from acme.sh’s internal certificate directory bypasses that stable installation contract.

Automatic renewal does not happen

Check each link in the chain:

crontab -l | grep acme.sh
~/.acme.sh/acme.sh --info -d example.com
timedatectl status

The DNS token must still work, the client must be scheduled, destination files must remain writable, and the reload command must return success. A renewed file is not enough if Nginx still holds the old certificate.

Monitor the public endpoint from another machine and alert well before expiry. That one observation covers issuance, installation, reload, DNS routing, and the certificate a client actually receives.

Corrections to the old article

The previous version listed certificate limits without a Google source, claimed EAB keys did not expire, suggested unsupported gcloud list commands, required billing without evidence, and recommended deleting internal acme.sh state. Those claims and procedures have been removed.

References