Skip to content

Walkthroughs ​

The reference pages each answer one question. A platform page says how nginx reads a certificate; gateways/vault.md says what the Vault gateway can and cannot do; deployment.md says what a target is. None of them gets you from an empty CertPilot to a web server serving a certificate it renewed by itself, because that crosses five of those pages and the connecting steps live in none of them.

These do. Each one starts from nothing, names every prerequisite before it is needed, and ends at a check you can run to see whether it worked.

What it gets you
Vault to nginxAn internal CA in HashiCorp Vault, issuing to a host that installs and reloads nginx by itself
ACME to nginxThe same, from a public CA over ACME, with the domain-control challenge solved for you
Windows and IISA binding re-pointed by thumbprint, on a platform that reads no certificate files
A CA is expiringFinding out before issuance starts failing, and what the failure looks like if you do not
A renewal or deployment failedReading the refusal, finding what is still being served, and recovering

The first two are alternatives, not a sequence. Read the one whose CA you have.

What was actually run ​

Every command on these pages was run, and the output quoted is what came back. Where something could not be run here, the page says so in place — there are no silent gaps, and a step nobody exercised is worth less than one that says why.

Version
CertPilot coreda9423f, development mode, in-memory store
Agentcertpilot-agent@v0.2.0, linux/arm64
Vault gatewaycertpilot-gateway-vault@v0.3.0
ACME gatewayghcr.io/certpilot/gateway-acme:0.3.0
HashiCorp Vault2.0.3, vault server -dev
ACME CAPebble (ghcr.io/letsencrypt/pebble:latest), http-01
nginx1.29.8 (nginx:1.29-alpine), OpenSSL 3.5.8
HostmacOS on aarch64, Docker 29.5.2 under colima

What was not run, and why ​

  • Let's Encrypt staging. Proving control of a domain means a name that resolves on the public internet and a listener the CA can reach. Neither exists here. The ACME protocol path — directory, account, order, http-01 challenge, finalize, download — was exercised in full against Pebble, which is the ACME server Let's Encrypt builds for exactly this purpose. What Pebble cannot tell you is anything about Let's Encrypt's rate limits, its account policy or its CAA handling. ACME to nginx marks those steps where they occur.
  • Windows and IIS. There is no Windows host here. What can be checked off Windows was checked, and it is a short list: the profile's contents, and the agent's refusal to install a Windows destination on a machine that is not Windows. The store import, the binding and the post-binding handshake were not run. Windows and IIS says so at the top rather than at the bottom.
  • dns-01 challenges, which need a real DNS provider and a token for it.
  • Deployment targets other than the agent — webhook, AWS ACM, Azure Key Vault, F5. Those are deployment.md's subject and none of them was exercised here.

Three defects these turned up ​

Walking the paths end to end found things that reading the pages did not. Each one is linked from the step that hits it:

  • #107, fixed — manually renewing an agent-held certificate made CertPilot hold its private key. The core now refuses it.
  • #108, fixed — a SAN-only certificate could not be found by name. The name filter now matches the SANs.
  • #109, fixed — a certificate shorter than the renewal lead time renewed on every agent cycle. The lead time is now bounded by the certificate's own lifetime.

Before any of them ​

Two things every walkthrough assumes, and neither is part of the walkthrough itself:

A running CertPilot. evaluation.md is the shortest route to one — a container stack and a password, in about twenty seconds. operations.md is the route for something you intend to keep.

A credential. Every route except /healthz and the three that sign-in itself needs is a 401 without one. A password sign-in sets a cookie and returns no token, so the examples here carry a cookie jar:

bash
JAR=$(mktemp)
curl -sS -c "$JAR" -X POST localhost:8080/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email": "you@example.com", "password": "..."}'

-H "Authorization: Bearer $TOKEN" substitutes for -b "$JAR" anywhere below and is what a script in a real deployment uses; it needs an identity provider, which an evaluation does not have. See api-reference.md.

Do not run these against a database you care about. They create CA accounts, templates, grants and certificates, and the failure walkthroughs break things on purpose.