Skip to content

Private PKI

Not every certificate should come from a public CA. Service-to-service mTLS, device identity and internal tooling all need certificates that public CAs cannot sensibly issue - you cannot get a WebPKI certificate for payment-svc.svc.cluster.local, and you should not want one.

NextPKI includes a private CA for exactly this.

NextPKI Root CA (offline)
└── Tenant Issuing CA (one per tenant)
├── leaf certificates
└── delegated OCSP signer

The root signs tenant intermediates and nothing else. Every leaf you receive is issued by your tenant’s intermediate, so one tenant’s CA cannot issue for another.

Signing keys live behind a pluggable key provider: PKCS#11 for HSM-backed deployments, a cloud KMS in production, SoftHSM for development. The private keys are never in application memory in a form that can be exported.

Four built-in certificate profiles cover the usual internal cases, and a profile governs key usage, extended key usage, validity ceiling and whether SANs are permitted. A request that violates its profile is rejected before signing rather than producing a certificate nobody wanted.

Issued leaves carry CRL distribution points and AIA extensions, so revocation and issuer discovery work the way relying parties expect.

Both mechanisms are available:

  • CRL - a signed v2 certificate revocation list per tenant intermediate, with a monotonic CRL number.
  • OCSP - RFC 6960 responses. Signing is delegated to a dedicated OCSP signer certificate carrying id-kp-OCSPSigning and ocsp-nocheck, rather than using the intermediate’s key directly for online responses.

Both are verified against openssl rather than only against our own code, which matters for a component whose output other people’s TLS stacks have to accept.

Every signing operation is recorded, and the audit log is hash-chained and append-only: entries link to their predecessor, and there is no update or delete path. Tampering with history breaks the chain visibly instead of quietly.

For a private CA this is the difference between “we believe only authorised certificates were issued” and being able to demonstrate it.

The private CA is operational for issuance, revocation, CRL and OCSP, driven today by operator tooling rather than by the public API. It is not exposed through the v1 API, and there is no public endpoint for requesting an internal certificate yet.

Planned, in order:

  1. HTTP OCSP responder - a served /ocsp endpoint rather than command-line responses.
  2. Internal ACME server - RFC 8555 against the private CA with mandatory EAB, so certbot, acme.sh, Caddy and Traefik can request internal certificates with no NextPKI-specific code at all. This is the interface that matters for most internal automation.
  3. Public API surface for issuance.

If internal mTLS automation is what you need, the ACME server is the thing to wait for - and saying so affects its priority.