Documentation menu

Signing external CSRs

Issue a certificate for a request generated elsewhere. The private key never reaches homepki.

When to use sign

Use homepki sign when the private key is generated somewhere else: a service that makes its own key, a cert-manager request, or a hand-written openssl req. Only the request goes in and only the certificate comes out. homepki never sees the private key.

$ openssl req -new -nodes -newkey rsa:2048 -keyout my-service.key -out my-service.csr \
    -subj "/O=runlocal-dev/OU=bu1/CN=my-service.bu1.runlocal.dev" \
    -addext "subjectAltName=DNS:my-service.bu1.runlocal.dev,DNS:my-service.local"

$ homepki sign -d runlocal.dev -i bu1 --csr my-service.csr
Signing my-service.csr as a server certificate for my-service.bu1.runlocal.dev under runlocal.dev/bu1
Certificate written to ~/.homepki/runlocal-dev/bu1/server-tls/my-service.crt
Serve it with the chain file ~/.homepki/runlocal-dev/bu1/bu1-intermediate-ca-chain.crt; the private key stays wherever you generated it.

Subject policy

The intermediate signs only requests that carry its own organization and organizational unit:

FieldRequired valueExample
Othe root CA's literal name: the domain with dots replaced by dashesrunlocal-dev
OUthe intermediate namebu1
CNany valuemy-service.bu1.runlocal.dev

A request that does not match is rejected, and the error prints the -subj to use:

$ homepki sign -d runlocal.dev -i bu1 --csr bad.csr
Error: bad.csr: the request subject does not satisfy the CA policy:
  want O=runlocal-dev, got O=acme
  want OU=bu1, got OU=(none)

Regenerate the request with a matching subject, for example:
  openssl req -new -nodes -newkey rsa:2048 -keyout my.key -out my.csr \
    -subj "/O=runlocal-dev/OU=bu1/CN=my-service.bu1.runlocal.dev"

What is copied from the request

  • Subject Alternative Names: every DNS, IP, email and URI SAN in the request.
  • Subject: the C, ST, L, O, OU and CN fields.

Every other extension the request asks for is ignored. Basic constraints, key usage and extended key usage are set by homepki, so a request cannot ask to become a CA. The new certificate is verified against its chain before it is written, so the CA's name constraints apply to the SANs in the request.

A request without SANs produces a certificate without SANs, with a warning:

$ homepki sign -d runlocal.dev -i bu1 --csr nosan.csr
Warning: the request carries no Subject Alternative Names — most TLS clients reject a certificate matched on its common name alone.
Signing nosan.csr as a server certificate for nosan.bu1.runlocal.dev under runlocal.dev/bu1
Certificate written to ~/.homepki/runlocal-dev/bu1/server-tls/nosan.crt

Flags

FlagEffect
-d, --domainRoot CA domain. Required.
-i, --intermediateIntermediate CA that signs. Required.
--csrPath to the PEM request. Required.
--typeserver (default) or client. Picks the extended key usage and the destination directory.
--nameFile name for the certificate. Default: the first label of the request's common name.
--outWrite the certificate to this path instead of server-tls/ or client-tls/.
--validityDays (90d) or a duration (24h). Default 365 days, capped at the intermediate's expiry.
-f, --forceReplace an existing certificate at the output path.
$ homepki sign -d runlocal.dev -i bu1 --csr my-client.csr --type client --name my-client
$ homepki sign -d runlocal.dev -i bu1 --csr my-service.csr --out ./my-service.crt --validity 90d

Without --out the certificate lands in <intermediate>/server-tls/<name>.crt or client-tls/<name>.crt, and the list commands report it like any generated leaf. There is no .key next to it: the key stays where the request was made.

Signing refuses to overwrite an existing certificate at the output path unless you pass --force.

Revoking a signed certificate

A certificate written with --out is outside the PKI tree, so revoke takes its path:

$ homepki revoke -d runlocal.dev -i bu1 --cert ./my-service.crt

One written to the default location can be revoked by name with --server or --client. See Revocation.