Skip to content

Renew through a paid / third-party CA (with key reuse)

What you'll have at the end: an endpoint renewing through a commercial ACME CA (DigiCert ONE, or any RFC 8555 CA that gave you a directory URL and EAB credentials), with the endpoint's existing private key kept across the renewal and the web server following the new certificate without a config change.

This is the full third-party flow, end to end. If your endpoint does not need to keep its key, the flow is the same minus Steps 6–7 — the renewal just generates a fresh key.

Prerequisites:

  • The endpoint is visible on Manage with served proof — else do Track a new endpoint first.
  • From your CA account team or portal: the ACME directory URL, the EAB key ID, and the EAB HMAC key. These identify your CA account to the ACME endpoint.
  • A check that your domain's DNS doesn't forbid the CA: run dig CAA shop.example.com +short (and the parent zones). No CAA records means any CA may issue; if records exist, one must authorize this CA. The Hub re-checks this before every order, fail-closed.

Time: 30–45 minutes for the first endpoint (subsequent ones reuse Steps 1–3 and take minutes).

Mock values used throughout — substitute your real ones:

Endpoint shop.example.com, Scout web-01, serving from /etc/nginx/ssl/
Hub https://hub.example.internal
CA directory https://acme.example-ca.com/directory
EAB key ID EXAMPLEKID_x9y8z7A6b5C4d3E2f1G0hIjKlMnOpQrS
EAB HMAC key RXhhbXBsZUhtYWNLZXlNb2NrVmFsdWVGb3JEb2NzT25seU5vdFJlYWxLZXlNYXRlcmlhbEF0QWxs

Step 1 — Register the CA as a provider

Settings → Certificate Providers → Add custom provider. Fill in:

Field Value Why
Provider ID example-ca Lowercase slug, letters/digits/hyphens only. Permanent — pick a name you'll recognize in profile dropdowns.
Display name Example CA What the dashboard shows.
Directory URL https://acme.example-ca.com/directory Exactly as the CA gave it. Must be https://.
Staging directory URL (optional) (leave blank) Most commercial ACME endpoints publish no staging directory. Blank means profiles on this provider are production-only — which is correct, not a compromise.
CAA issuer domain example-ca.com The domain this CA tells its customers to put in CAA records. Mandatory: it's what the Hub's fail-closed CAA pre-check compares against.
Requires EAB credentials Refuses account registration with nothing stored, instead of failing later with a CA error.

Click Add provider.

You should now see the provider in the panel's provider list, with External Account Binding: Required — not set.

Step 2 — Enter the EAB credentials

Still on the provider's detail: the EAB key ID / EAB HMAC key form. Paste both values exactly as issued — no trimming, no re-encoding, no added padding. The HMAC is a base64url string and is stored as that string; the Hub decodes it at signing time. Click Save EAB credentials.

You should now see the EAB state change to Configured (kid EXAMPLEKID_x9y8z7A6b5C4d3E2f1G0hIjKlMnOpQrS). The HMAC is write-only — it is encrypted at rest and never displayed again. A typo'd HMAC is not detected here; it surfaces in Step 8 at account registration, which is free — before any order exists (see the note there).

Step 3 — Create the renewal profile

Settings → Renewal Profiles → New Profile.

Field Value Why
Profile Name example-ca-rsa-reuse Named for what it does.
Contact Email ops@example.com Registers the ACME account (keyed by email + provider + environment).
Issuer Type Public ACME
Provider Example CA The Step-1 row.
Environment Production The only choice on a provider without a staging directory.
Validation Method DNS-01 (Manual TXT) The lane for third-party CAs: EAB and custom directories are Hub-side, which HTTP-01 (Scout-side, Let's Encrypt-only this phase) cannot carry. Manual works even with zero DNS automation — and on a prevalidated CA account there is often no DNS step at all (Step 8).
Key Type RSA 2048 (legacy compatibility) Match the endpoint's existing key — check with openssl rsa -in shop.key -noout -text | head -1. On this lane an RSA type nominates the reused key; it will not generate a fresh RSA key.
Preferred Chain Default (CA decides) The only accepted value off Let's Encrypt.
Delivery Mode Scout (installs and reloads locally)
Key Handling Reuse private key across renewals (for pins/DANE) The point of this guide. If reuse is impossible the renewal is refused, never silently rotated.
Max Retries 0 Every order on this CA costs money. Zero retries means one attempt per explicit click — a failure stops and tells you, instead of retrying a paid operation on its own.

Click Create Profile. You should now see it in the Renewal Profiles table with issuance DNS-01 (Manual TXT) and env production.

Step 4 — Make the certificate directory visible to the Scout

On the endpoint host, the directory the web server serves from must be in the Scout's cert-dirs file — this is what lets the Scout find the served key (Step 6), adopt it (Step 7), and later re-point the served files at the renewal (Step 9):

$ echo "/etc/nginx/ssl" >> /opt/cyphers/cert-dirs.conf
$ sudo systemctl reload cyphers-scout

You should now see cert-dir file reloaded — starting a scan cycle in journalctl -u cyphers-scout, and within a couple of minutes the endpoint's drawer shows the discovered on-disk certificate.

Step 5 — Adopt the endpoint with the profile

On Manage, the shop.example.com row (Untracked) offers Adopt. Pick example-ca-rsa-reuse in the Renewal profile select and click Apply.

You should now see the row managed. Nothing has been ordered yet. (Details: Adopt an endpoint.)

Step 6 — First Renew Now: the expected refusal

Click Renew Now. You should see:

pre-flight refusal: key_reuse_adoptable

The Activity feed spells it out: the key this endpoint serves is at /etc/nginx/ssl/shop.key, which the Hub does not manage — reuse can only load a key the Scout itself holds. This refusal is free (no order was created) and it is the design working: the alternative would be silently rotating a key you configured the profile to keep.

Step 7 — Adopt the key

Open the drawer and click Adopt key from /etc/nginx/ssl/shop.key. The Scout verifies the key matches what the endpoint currently serves, then copies it (on the host — it never crosses the network) into its managed storage. Verify yourself:

$ sudo openssl rsa -noout -modulus -in /etc/nginx/ssl/shop.key | openssl sha256
SHA2-256(stdin)= ab12cd34ef56...
$ sudo openssl rsa -noout -modulus -in /opt/cyphers/data/certs/shop.example.com/privkey.pem | openssl sha256
SHA2-256(stdin)= ab12cd34ef56...

Same digest = same key. (Full detail: Adopt a private key.)

Step 8 — Renew Now again — ⚠ this may be the paid click

Where money is spent

On a CA account whose domains are prevalidated (typical for OV/organization-validated setups), the order arrives with nothing left to prove, and the Hub's DNS watchdog finalizes it automatically within ~30 seconds — there is no second confirmation between this click and a billed certificate. Treat Renew Now as the purchase.

Before the order, the first-ever renewal on this provider registers the ACME account — which is free and is where bad EAB credentials fail. The Hub log line Persisted new ACME account credentials marks success; a registration error at this point has cost nothing — re-check Step 2 and click again.

Click Renew Now. The endpoint's hostname is added to the ACME domain allowlist automatically, the CAA pre-check runs, and the order is created. Two shapes from here:

Shape A — prevalidated (no DNS work). The drawer briefly shows Complete renewal"No DNS records are required — the CA has already validated every domain on this order." — and the watchdog completes it on its own within about 30 seconds. You'll simply see the renewal close.

Shape B — TXT records required. The drawer shows Add DNS TXT record with the exact record(s):

_acme-challenge.shop.example.com
= ab12cd34ef56gh78...

Publish them in your DNS console. There is no deadline — the order parks until you act, and the Hub re-checks it every 30 seconds, completing the renewal on its own once every authoritative nameserver of your zone serves the records. Verify & Complete just runs that check immediately.

The all-nameservers bar is deliberate: the CA validates against whichever authoritative host it likes, so the Hub refuses to submit for validation — which is one-shot, and burns the order on a wrong answer — until the whole fleet agrees. Right after you edit a record, "still waiting on ns2.example-dns.com" is normal; it clears as your provider's servers converge.

Step 9 — Verify the result

Wait for the renewal to close (Scout install + reload + served re-probe; usually under a minute after finalization), then check each claim:

The renewal is closed — drawer → Renewals tab: the newest entry reads Closed, with Key: reused.

The served files followed — on the host, the external path is now a symlink into the Scout's managed directory, so nginx's unchanged config follows every future renewal:

$ ls -l /etc/nginx/ssl/shop.pem
lrwxrwxrwx ... /etc/nginx/ssl/shop.pem -> /opt/cyphers/data/certs/shop.example.com/fullchain.pem

The original files were quarantined by the deploy transaction, not deleted.

The key never changed:

$ sudo openssl rsa -noout -modulus -in /opt/cyphers/data/certs/shop.example.com/privkey.pem | openssl sha256
SHA2-256(stdin)= ab12cd34ef56...        # identical to Steps 1/7

The world sees the new certificate — from any other machine:

$ echo | openssl s_client -connect shop.example.com:443 -servername shop.example.com 2>/dev/null | openssl x509 -noout -serial -issuer -enddate
serial=04ABCD1234EF...
issuer=CN=Example CA TLS RSA CA G1...
notAfter=Mar  8 12:00:00 2027 GMT

The row is healthy — back on Manage, after the next observations the row shows the new expiry and no findings. A brief "waiting on re-check" right after renewal is normal: it clears as soon as both vantages have re-observed the endpoint.


Troubleshooting

What you see Meaning Remedy
pre-flight refusal: key_reuse_adoptable Served key exists but isn't under management. Expected once — Step 7.
pre-flight refusal: key_reuse_key_missing The Scout holds no key and can't see the served one — usually the cert directory isn't in cert-dirs.conf. Do Step 4, wait one cycle, retry.
pre-flight refusal: key_reuse_algo_mismatch Profile key type ≠ held key (e.g. rsa_4096 profile, 2048-bit key). Fix the profile's Key Type to match the real key.
pre-flight refusal: key_reuse_diverged Something else rotated the served key after adoption — another renewer (certbot?) is still active. Stop the other renewer, re-adopt, retry. See Take over certbot.
Provider option flagged — EAB required / issuance blocked on EAB Provider requires EAB, none stored. Step 2.
Renewal fails during account setup, no order created Bad EAB credentials or directory URL — caught at free registration. Re-enter Step 2 values exactly as issued; retry costs nothing.
CAA refusal in pre-flight The domain's CAA records don't authorize this CA (or the provider row's CAA issuer domain is wrong). Fix the CAA record — or the Step-1 field — and retry.
Parked on TXT, then failed after 5 minutes The manual-DNS window lapsed. Order unfinalized — unpaid. Renew again with the records ready.
Renewal parks in action needed after install Certificate issued + installed but the reload didn't take (hook failed or reload ineffective). No re-issue happens. Fix the reload/hook on the host; the next routine scan closes the renewal on its own.
a renewal is already in progress for this endpoint In-flight dedup — the previous attempt hasn't reached a terminal state. Wait for it to close or fail; check the drawer.