caddyserver/caddy
PKI
The pki app is Caddy's built-in certificate authority. Module ID pki, defined in modules/caddypki/pki.go.
Purpose
Run one or more local certificate authorities so Caddy can issue certificates for internal names without going to a public CA. The tls app's internal issuer (modules/caddytls/internalissuer.go) calls into this app, and the optional ACME server module (modules/caddypki/acmeserver/) lets non-Caddy clients use the same CA over ACME.
By default, every Caddy instance has a CA called local whose root and intermediate are written into storage on first use. That's what makes tls internal "just work" for localhost and other internal names.
Directory layout
| Path | Role |
|---|---|
modules/caddypki/pki.go |
The PKI app: holds CAs map[string]*CA |
modules/caddypki/ca.go |
CA type — root, intermediate, signer (~15 KB) |
modules/caddypki/certificates.go |
Certificate generation helpers |
modules/caddypki/crypto.go |
Key generation and PEM helpers |
modules/caddypki/maintain.go |
Background goroutine that renews intermediates |
modules/caddypki/command.go |
CLI subcommands (caddy trust, caddy untrust) |
modules/caddypki/adminapi.go |
Admin API endpoints under /pki/ |
modules/caddypki/acmeserver/ |
Optional ACME server (http.handlers.acme_server) |
Key abstractions
| Type | Where | Description |
|---|---|---|
PKI |
pki.go |
The app; map of CA ID to *CA |
CA |
ca.go |
A single certificate authority — root cert, intermediate cert, signer key, lifetimes |
acmeServerHandler |
acmeserver/ |
HTTP handler implementing the ACME server protocol; backed by smallstep/certificates |
How it works
graph TD
Config[pki app config] --> Provision
Provision --> Default["Ensure 'local' CA exists"]
Default --> Storage["Read/write CA material<br/>via caddy.Storage"]
Maintain[maintain.go goroutine] -->|renew intermediate| Storage
Internal["tls.issuance.internal"] -->|GetCA| PKIapp[PKI app]
PKIapp -->|sign| CertOut[issued certs]
AdminAPI["GET /pki/ca/<id>"] -->|JSON details| PKIapp
Cmd["caddy trust"] -->|read root, install in OS trust store| TrustStoreCA lifecycle
CA.Provision ensures both a root and an intermediate exist:
- If storage doesn't have a root for this CA ID, one is generated on the fly with a long lifetime (default 10 years).
- An intermediate is generated under the root with a shorter lifetime (default 7 days for the local CA, longer for explicitly configured ones).
maintain.gostarts a background loop that renews intermediates well before they expire, keeping the root untouched.
Trust installation
caddy trust (registered through modules/caddypki/command.go) writes the local CA's root into the OS trust store, using smallstep/truststore. caddy untrust reverses that. Both subcommands work cross-platform thanks to the underlying library.
ACME server
If you import modules/caddypki/acmeserver, you get the HTTP handler module http.handlers.acme_server. Configured into a route, it speaks ACME on behalf of the configured CA — useful if you want other clients (certbot, lego, …) to obtain certs from your private CA. It is built on top of smallstep/certificates.
Admin API
adminapi.go registers admin routes under /pki/:
GET /pki/ca/<id>— JSON metadata about a CA, including root and intermediate fingerprints and validity windows.GET /pki/ca/<id>/certificates— chain in PEM form.
Integration points
tlsapp: theinternalissuer is the consumer. It callscaddypki.GetCAto obtain a signer for issuing leaf certs.- Storage: all CA private material is persisted under storage, namespaced by CA ID. Lose the storage and you lose the CA.
- CLI:
caddy trustandcaddy untrustimport / remove the local CA root from the OS trust store. - ACME server module: an HTTP handler that re-exposes a CA over ACME.
Entry points for modification
- Add CA defaults?
pki.goandca.go. - Tweak intermediate renewal timing?
maintain.go. - New admin endpoints?
adminapi.goplus thecaddy.AdminRouterinterface guard.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.