Open-Source Wikis

/

Caddy

/

Apps

/

PKI

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| TrustStore

CA lifecycle

CA.Provision ensures both a root and an intermediate exist:

  1. If storage doesn't have a root for this CA ID, one is generated on the fly with a long lifetime (default 10 years).
  2. An intermediate is generated under the root with a shorter lifetime (default 7 days for the local CA, longer for explicitly configured ones).
  3. maintain.go starts 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

  • tls app: the internal issuer is the consumer. It calls caddypki.GetCA to 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 trust and caddy untrust import / 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.go and ca.go.
  • Tweak intermediate renewal timing? maintain.go.
  • New admin endpoints? adminapi.go plus the caddy.AdminRouter interface guard.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

PKI – Caddy wiki | Factory