Certificate Operations Manual
On this page
Identify the certificate under inspection: issued by the CA, installed on disk, loaded by the service or received by the client. These can differ. HTTPS validation also requires matching identity, time, chain and trust.
| Task | Start here |
|---|---|
| Browser certificate error | Inspect the served certificate |
| Renewed but still expired | Renewal to deployment |
| Create CSR / local certificate | Names, keys and trust |
SNI selects the site; hostname verification checks identity
Live endpoint: verify handshake and identity
# Connect to the site without suppressing validation failures
-connect sets TCP destination, -servername SNI, -verify_hostname name checking, and -verify_return_error aborts on validation failure. -showcerts prints the supplied chain. Inspect verification and stderr.
For a specific edge IP, change -connect but retain the real SNI/hostname. Use a controlled CAfile for private trust rather than disabling verification.
Disk file: inspect metadata and expiry
# Read the first certificate’s names, issuer, and dates
A fullchain normally starts with the leaf, then intermediates. This parses only the first certificate; it does not validate the chain. Use the service’s actual file.
# Check whether expiry falls within the next 24 hours
Exit 0 means no expiry in that window; inspect errors/results otherwise. The interval is seconds and says nothing about name or trust.
Keep verification errors visible during the complete handshake check. For a private CA provide an intended trusted -CAfile. -servername alone does not verify hostname. checkend 86400 tests expiry within the next day, not just expiry now, and does not replace identity, trust-chain or notBefore checks.
| Check | Failure evidence | Fix location |
|---|---|---|
| SAN / hostname | Connection name absent from SAN | Issue correct identity or fix the URL |
| notBefore / notAfter | Clock error, not yet valid or expired | Correct clock / renew and deploy |
| Chain | Missing intermediate or wrong chain | Install the proper fullchain |
| Trust | Client does not trust the root | Use an appropriate CA or managed trust, not disabled verification |
Renewal completes at the client
Match installed and served certificates
# Read the configured on-disk certificate identity
Record serial and SHA-256 fingerprint, then compare the same endpoint/SNI.
# Extract only the live leaf fingerprint for comparison
|
This metadata extraction suppresses handshake diagnostics and is not a trust test. Run full validation afterward; mismatches may identify a CDN/LB or another instance.
The pipeline extracts identity only, not trust; use the earlier validation command. If disk and served certificates differ, inspect configured paths, permissions, reload hooks and TLS termination at load balancers/CDNs. Verify all relevant edge nodes.
Choose one certificate owner
acme.sh, Certbot, and Caddy automatic HTTPS are alternatives. Identify the existing owner and prepare destination permissions; do not apply all clients to one certificate.
# List issued names and key types as the acme.sh owner
The next step assumes an issued ECC certificate. Complete the appropriate HTTP/DNS challenge first if absent; install-cert is not issue.
# Install the issued certificate at stable service paths
Use this reload command only for manually managed Caddy certificates and an account permitted to write/reload. Omit --ecc for RSA. Verify permissions, fingerprint, reload logs, and live TLS.
Certbot: inspect existing certificates or issue first
# List Certbot certificate names, domains, and paths
Cert Name need not equal a domain. Use the listed name for --cert-name and inspect plugins separately.
For first-time webroot issuance, an existing HTTP server must expose /.well-known/acme-challenge/ from /var/www/acme on public port 80, with correct A/AAAA. These steps do not apply to Caddy automatic HTTPS.
# Test the HTTP-01 path against the staging CA
-w is the server webroot and -d the requested name. Follow account prompts. Dry-run creates no deployable production certificate; fix path/DNS failures first.
# Issue after testing, then configure the service separately
certonly does not install server configuration. Inspect actual paths, configure/validate/reload the service, then verify TLS from a client.
# Test existing renewal configuration and challenges
Success does not prove deployment. Verify scheduling and deploy hooks; dry-run hook execution depends on options such as --run-deploy-hooks and version behavior.
The acme.sh example assumes an issued ECC certificate, prepared paths/permissions and a valid deployment reload command; omit --ecc for RSA. Serve the stable install-cert paths, not internal working files. Choose one renewal owner; verify installed Certbot DNS plugins and scoped credentials.
Caddy automatic HTTPS normally owns issuance/renewal; see Caddy. Use external renewal when manual certificates are intentional. Diagnose challenge paths, delegation, TXT and authorization before retrying; use staging/dry-run for tests. Cloud load balancers additionally need certificate binding.
Create a SAN request and compare public keys
New key and CSR: protect output first
# Restrict new private-key file permissions in this shell
Use a controlled directory with unused filenames; do not overwrite an existing server.key.
# Create a private key and CSR with the intended SANs
OpenSSL 3 -noenc leaves the key unencrypted; use only with planned filesystem/deployment protection. Omit it for encrypted storage and plan unlocking. SAN lists actual identities; CN is not a substitute.
# Check the CSR signature, SANs, and public-key parameters
-verify checks the CSR signature, not CA issuance or acceptance of every SAN. Submit only the CSR; retain the private key.
Compare public-key hashes after issuance
# Hash the public key derived from the private key
|
Only the public-key hash is shown; compare with the same DER encoding below.
# Hash the public key in the issued certificate
|
|
server.crt is the issued leaf. Matching hashes prove key pairing, not SAN, validity, chain, or client trust.
OpenSSL 3 example. -noenc leaves the private key unencrypted, requiring protected storage. A CSR contains no private key. Compare public-key digests after issuance; equality is not trust. A self-signed localhost certificate needs appropriate SANs and explicit trust. Key compromise requires replacement and CA revocation, not just chmod.
OpenSSL s_client · OpenSSL x509 · acme.sh installation · Certbot
Deployment runbook: WildWind CLB certificate renewal and binding.