Documentation menu

CLI reference

Every command and flag, as homepki <command> --help prints them in v0.8.0.

Commands

CommandWhat it does
root-caGenerate a self-signed Root CA. root-ca list lists them.
intermediate-caGenerate an Intermediate CA signed by a Root CA, with its chain file.
server-certGenerate a serverAuth certificate and key under an Intermediate CA.
client-certGenerate a clientAuth certificate and key under an Intermediate CA.
signSign a certificate signing request generated elsewhere.
revokeRevoke a leaf and re-sign the CRLs.
crlWrite or re-sign the CRLs without revoking anything.
trustInstall, remove or check a Root CA in the system, Firefox/NSS and Java trust stores.
skillInstall the Agent Skill for AI coding tools.
versionPrint the version, commit and build date.
completionGenerate a shell completion script (cobra built-in): homepki completion zsh.

Global flags

FlagShortDefaultDescription
--workdir$HOMEPKI_WORKDIR, then ~/.homepkiWorking directory holding every PKI. Accepted by every command.
--help-hHelp for any command.
--version-vPrint the version (root command only).

The working directory is resolved in this order: --workdir, then the HOMEPKI_WORKDIR environment variable, then ~/.homepki. In a script that runs several commands, exporting HOMEPKI_WORKDIR once is shorter than repeating the flag.

Errors and exit codes

  • A successful command exits 0. Any failure exits 1.
  • An unknown flag, or a value a typed flag cannot parse, prints the error followed by the command's usage.
  • Every other error prints on its own, without usage: a missing required flag, existing material without --force, a missing tier, a name-constraint violation, a failed sudo.
  • Generate commands print what they do and each file written on stdout. Errors go to stderr. In scripts, rely on the exit code and check results with list -o json.

root-ca

Generate a self-signed Root CA for a domain. The certificate and key go to <workdir>/<domain-with-dashes>/ca/. The root may sign intermediates only (pathlen:1).

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name, e.g. runlocal.dev.
--key-typersaPrivate key algorithm: rsa, ecdsa, ecdsa-p256, ecdsa-p384, ecdsa-p521, ed25519.
--validity2190dDays (90d) or a Go duration (24h, 30m).
--name-constraintRepeatable. Restrict the names this CA may issue for, in openssl syntax: permitted;DNS:.example.internal or excluded;IP:10.0.0.0/8. Types: DNS, IP, email, URI. permitted; may be omitted.
--force-ffalseReplace an existing Root CA. Orphans every certificate under it.
$ homepki root-ca -d runlocal.dev
$ homepki root-ca -d klimax.internal --key-type ecdsa --validity 3650d \
    --name-constraint "permitted;DNS:.klimax.internal"

See Name constraints and Server and client certificates for key types and validity.

intermediate-ca

Generate an Intermediate CA signed by the domain's Root CA. It writes the certificate, the key and <name>-intermediate-ca-chain.crt (intermediate followed by root). An intermediate may sign leaves only (pathlen:0).

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--name-nrequiredIntermediate CA name, e.g. bu1.
--key-typersaSame values as root-ca.
--validity2190dCapped at the Root CA's expiry, with a note.
--name-constraintRepeatable. Same syntax as root-ca.
--force-ffalseReplace an existing Intermediate CA and delete its CRLs. Orphans every leaf under it.
$ homepki intermediate-ca -d runlocal.dev -n bu1
$ homepki intermediate-ca -d klimax.internal -n bu1 \
    --name-constraint "permitted;DNS:.bu1.klimax.internal"

server-cert

Generate a key and a serverAuth certificate under an Intermediate CA, in <intermediate>/server-tls/. The common name is <server>.<intermediate>.<domain>, which is also the first SAN. The certificate is verified against its chain before anything is written.

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--intermediate-irequiredIntermediate CA name.
--server-srequiredServer name, e.g. kong-gateway.
--sanRepeatable. Additional Subject Alternative Name. Bare values are detected as IP or DNS; prefix with DNS:, IP:, email: or URI: to force a type.
--key-typersaSame values as root-ca.
--validity365dCapped at the Intermediate CA's expiry, with a note.
--pkcs12falseAlso write <server>.p12 with the key, certificate and CA chain.
--pkcs12-passwordchangeitPassword of the PKCS#12 file.
--force-ffalseReplace an existing certificate of the same name. The key is regenerated.
$ homepki server-cert -d runlocal.dev -i bu1 -s kong-gateway \
    --san kong.local --san 192.168.1.10 --san 'DNS:*.kong.local'
$ homepki server-cert -d runlocal.dev -i bu1 -s kong-gateway --validity 24h --pkcs12 --force
⚠

Quote SANs that contain *. zsh expands an unquoted --san DNS:*.kong.local and fails the command with no matches found.

client-cert

Generate a key and a clientAuth certificate under an Intermediate CA, in <intermediate>/client-tls/. Same naming and checks as server-cert.

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--intermediate-irequiredIntermediate CA name.
--client-crequiredClient name, e.g. my-client.
--sanRepeatable. Same syntax as server-cert; use URI: for a SPIFFE ID.
--key-typersaSame values as root-ca.
--validity365dCapped at the Intermediate CA's expiry, with a note.
--pkcs12falseAlso write <client>.p12 with the key, certificate and CA chain.
--pkcs12-passwordchangeitPassword of the PKCS#12 file.
--force-ffalseReplace an existing certificate of the same name. The key is regenerated.
$ homepki client-cert -d runlocal.dev -i bu1 -c my-client \
    --san URI:spiffe://runlocal.dev/ns/default/sa/my-client
$ homepki client-cert -d runlocal.dev -i bu1 -c my-client --pkcs12

list subcommands

Every tier has a list subcommand, with aliases ls and l. It reports expiry, days left and a verified chain of trust. Leaf lists also report revocation.

CommandRequired flagsWhat it verifies
root-ca listnone (lists every root in the workdir)Each root is a CA and correctly self-signed.
intermediate-ca list-dEach intermediate is a CA signed by the root.
server-cert list-d, -iChain to the root, serverAuth usage, not revoked.
client-cert list-d, -iChain to the root, clientAuth usage, not revoked.
FlagShortDefaultDescription
--output-otabletable (coloured, for people) or json (for scripts).
$ homepki server-cert ls -d runlocal.dev -i bu1 -o json \
    | jq -e 'all(.[]; .chain_valid)' >/dev/null || echo "broken chain"

The JSON format is described in Listing and verification.

sign

Sign a PEM certificate signing request with an Intermediate CA. Only the subject (C, ST, L, O, OU, CN) and the SANs are taken from the request. Basic constraints and key usages are set by homepki, so a request cannot ask to become a CA. The subject must carry O= the root's literal name and OU= the intermediate name.

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--intermediate-irequiredIntermediate CA name.
--csrrequiredPath to the PEM request.
--typeserverserver or client: sets the extended key usage and the destination directory.
--namefirst label of the CNFile name for the certificate.
--outWrite the certificate here instead of server-tls/ or client-tls/.
--validity365dCapped at the Intermediate CA's expiry.
--force-ffalseReplace an existing certificate at the output path.
$ homepki sign -d runlocal.dev -i bu1 --csr my-service.csr
$ homepki sign -d runlocal.dev -i bu1 --csr my-client.csr --type client --name my-client --out ./my-client.crt

See Signing external CSRs.

revoke

Add a leaf's serial number to the Intermediate CA's CRL, then re-sign the intermediate CRL, the root CRL and the CRL chain file. Pass exactly one of --server, --client or --cert. Revoking a certificate that is already revoked prints a message and exits 0.

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--intermediate-irequiredIntermediate CA name.
--server-sServer certificate to revoke, by name.
--client-cClient certificate to revoke, by name.
--certPath of a certificate to revoke, e.g. one written by sign --out. It must have been issued by this intermediate.
--reasonunspecifiedRFC 5280 reason: affiliationChanged, cACompromise, certificateHold, cessationOfOperation, keyCompromise, privilegeWithdrawn, superseded, unspecified. Case-insensitive.
--validity365dHow long the CRLs stay current (their nextUpdate).
$ homepki revoke -d runlocal.dev -i bu1 -c my-client --reason keyCompromise
$ homepki revoke -d runlocal.dev -i bu1 --cert ./my-service.crt

crl

Write or re-sign the CRLs of an Intermediate CA and its Root CA, keeping every revocation already recorded. Use it before anything is revoked, since a server configured with a CRL file refuses to start without one, and to push nextUpdate forward before the CRLs go stale.

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--intermediate-irequiredIntermediate CA name.
--validity365dHow long the CRLs stay current. Capped at each issuer's expiry.
$ homepki crl -d runlocal.dev -i bu1
$ homepki crl -d runlocal.dev -i bu1 --validity 7d

See Revocation for the files written.

trust

Manage the trust stores that accept a Root CA. --store takes system, nss and java, repeated or comma-separated. Without it, every store available on the host is used; a store named explicitly must be available.

trust install

Add the Root CA to each selected store. A store that already trusts it is skipped. The system store, and a Java cacerts file you cannot write, are changed under sudo.

FlagShortDefaultDescription
--domain-drequiredRoot CA domain name.
--storeevery available storesystem, nss, java.

trust uninstall

Remove the Root CA from each selected store. Stores that do not hold it are skipped. Same flags as install.

trust status

Report which stores accept the Root CA. Alias st. Needs no privileges and never prompts.

FlagShortDefaultDescription
--domain-devery Root CA in the workdirRoot CA domain name.
--storeevery available storesystem, nss, java.
--output-otabletable or json.
$ homepki trust install -d runlocal.dev --store nss,java
$ homepki trust status -d runlocal.dev -o json | jq '.[0].trusted'

See Trusting the root CA for each store and the JSON fields.

skill

Install the Agent Skill compiled into the binary. See Agent Skill.

skill install

FlagShortDefaultDescription
--claudetrueInstall into Claude Code's user skills directory, ~/.claude/skills/homepki.
--printfalseWrite the skill to stdout instead of installing.
--force-ffalseOverwrite an existing installed skill.

skill path

Print where the skill is installed for Claude Code: ~/.claude/skills/homepki/SKILL.md. No flags.

$ homepki skill install
$ homepki skill install --print > ./SKILL.md

version

Print the version, commit and build date. Alias v; homepki --version prints the same.

$ homepki version