Documentation menu

Trusting the root CA

Add the root CA to the system, Firefox and Java trust stores, so browsers, curl and JVMs accept the certificates issued under it.

Commands

$ homepki trust install   -d runlocal.dev                   # every store available on this host
$ homepki trust install   -d runlocal.dev --store nss,java  # Firefox and Java only, no sudo
$ homepki trust status                                      # every root CA in the workdir
$ homepki trust status    -d runlocal.dev -o json
$ homepki trust uninstall -d runlocal.dev

install and uninstall require --domain. status takes it optionally; without it, every root CA in the workdir is reported. All three take --store, repeatable or comma-separated.

Trust stores

--storePlatformWhere the root goesHow
systemmacOS/Library/Keychains/System.keychainsecurity add-trusted-cert -d -r trustRoot
systemFedora, RHEL, CentOS/etc/pki/ca-trust/source/anchors/homepki-<root>.crtthen update-ca-trust extract
systemDebian, Ubuntu, Alpine/usr/local/share/ca-certificates/homepki-<root>.crtthen update-ca-certificates
systemArch/etc/ca-certificates/trust-source/anchors/homepki-<root>.crtthen trust extract-compat
systemopenSUSE/usr/share/pki/trust/anchors/homepki-<root>.crtthen update-ca-certificates
nssmacOS, Linuxevery Firefox profile; on Linux also the Chrome/Chromium database ~/.pki/nssdbcertutil -A -t C,,, nickname homepki <root> root CA
javamacOS, Linux$JAVA_HOME/lib/security/cacerts (jre/lib/security/cacerts on JDK 8)keytool -importcert, alias homepki-<root>

<root> is the root CA's literal name, for example runlocal-dev. On Linux the first anchor directory that exists, in the order above, is used.

NSS databases

homepki looks for databases in these places under your home directory, and uses those that hold cert9.db (or the legacy cert8.db):

  • Library/Application Support/Firefox/Profiles/* (Firefox on macOS)
  • .mozilla/firefox/*, snap/firefox/common/.mozilla/firefox/*, .var/app/org.mozilla.firefox/.mozilla/firefox/* (Firefox on Linux, snap, Flatpak)
  • .pki/nssdb, snap/chromium/current/.pki/nssdb (Chrome and Chromium on Linux)

certutil comes with NSS: brew install nss, apt install libnss3-tools or dnf install nss-tools. Restart Firefox after installing.

Which stores are used

Without --store, homepki uses every store available on the host:

  • system on macOS, and on Linux when a known anchor directory exists;
  • nss when at least one database is found and certutil is installed;
  • java when JAVA_HOME is set and holds bin/keytool and a cacerts keystore.

An unavailable store is skipped with a note, for example Skipping nss: 1 Firefox/NSS database(s) found, but certutil is missing. No note is printed when there is simply no Firefox profile or no JAVA_HOME.

A store named with --store must be available, or the command fails:

$ homepki trust status -d runlocal.dev --store java
Error: --store java: JAVA_HOME is not set

When sudo is needed

StoreNeeds root
systemyes, on install and uninstall
nssno: the databases belong to you
javaonly when your user cannot write cacerts

homepki runs those commands under sudo, which may prompt for a password, unless it already runs as root (for example in a container). status never needs privileges and never prompts. In an unattended script, call install only when sudo is cached or passwordless, or use --store nss,java.

Install and uninstall

install is idempotent: a store that already trusts the root is reported and skipped. After adding the root to a store, homepki checks it again and fails if the store still does not trust it.

$ homepki trust install -d runlocal.dev --store nss,java
nss    adding to ~/Library/Application Support/Firefox/Profiles/x1y2.default-release
java   adding to /opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home/lib/security/cacerts
Certificate was added to keystore
Root CA for runlocal.dev is trusted in 2 store(s).
Restart Firefox and Java processes to pick it up.
Serve leaves with the intermediate chain file so clients can reach this root.

uninstall removes the root from each selected store and skips stores where it is not present. On macOS the certificate may remain in the System keychain without its trust setting; remove it with Keychain Access if you want it gone.

Status

$ homepki trust status -d runlocal.dev
Root CA trust:
  runlocal-dev             ✗ partly trusted
      ✓ system /Library/Keychains/System.keychain
      ✓ nss    ~/Library/Application Support/Firefox/Profiles/x1y2.default-release
      ✗ java   …/lib/security/cacerts (alias homepki-runlocal-dev not in the keystore)

On macOS the system store is checked with security verify-cert. On Linux homepki reads the CA bundle files the distribution builds from its anchors, so it reports what Go, curl and OpenSSL see.

JSON

$ homepki trust status -d runlocal.dev -o json
[
  {
    "name": "runlocal-dev",
    "certificate": "~/.homepki/runlocal-dev/ca/runlocal-dev-root-ca.crt",
    "trusted": false,
    "detail": "system: Cert Verify Result: CSSMERR_TP_NOT_TRUSTED",
    "stores": [
      {
        "store": "system",
        "location": "/Library/Keychains/System.keychain",
        "trusted": false,
        "detail": "Cert Verify Result: CSSMERR_TP_NOT_TRUSTED"
      },
      {
        "store": "nss",
        "location": "~/Library/Application Support/Firefox/Profiles/x1y2.default-release",
        "trusted": false,
        "detail": "certutil: could not find certificate named \"homepki runlocal-dev root CA\": PR_FILE_NOT_FOUND_ERROR: File not found"
      }
    ]
  }
]
FieldContent
namethe root CA's literal name, as root-ca list reports it
certificatethe root certificate that was checked
trustedtrue only when every store checked accepts the root
detailthe first failing store and its reason
stores[]one entry per store: store, location, trusted, detail
ℹ

Pass the same --store to status that you used for install. Otherwise a store you never installed into, such as a Firefox profile, makes the top-level trusted false.

Script example

# install into Firefox only when it is not trusted there yet
homepki trust status -d runlocal.dev --store nss -o json | jq -e '.[0].trusted' >/dev/null \
  || homepki trust install -d runlocal.dev --store nss

Serve the chain file

Trusting the root is not enough on its own. A server must present the leaf followed by <intermediate>-intermediate-ca-chain.crt, or clients cannot build the path from the leaf to the trusted root. See Using the certificates.

Constrain the root first

A trusted root can vouch for any name. Restrict it to your own domain with a name constraint before installing it, so a leaked key cannot impersonate other sites.

Windows

Windows is not supported: homepki ships macOS and Linux binaries only, and trust has no Windows store.