Skip to content

Platform support

localca's certificate generation is pure Go and works anywhere Go builds. Installing the root into a trust store does not — that part shells out to platform tools, and the platforms differ. This page states exactly where each store works.

Which stores work on which OS

OS StoreSystem StoreNSS (Firefox/Chromium)
Linux works works when certutil is installed
macOS works works when certutil is installed
Windows does not work — see below not supported
FreeBSD untested; the underlying library has a FreeBSD path not supported
anything else not supported not supported

The trust-store install is not exercised by the default pipeline — it mutates the real machine, so it lives behind env-gated integration tests (INT_TEST=1) that are run by hand on Linux. macOS uses the same code path as mkcert and is expected to work, but has no automated coverage either. Certificate generation and the pure logic around it are unit tested on every pipeline.

What a system-store install actually does

StoreSystem is the OS-wide trust store — the one Chrome, Safari, Edge and Go's own net/http client read.

Linux. The root certificate is written into the distribution's anchor directory and the distribution's update command is run, both through sudo. The anchor directory is detected at runtime, in this order: /etc/pki/ca-trust/source/anchors/ (with update-ca-trust extract), /usr/local/share/ca-certificates/ (with update-ca-certificates), /usr/share/pki/trust/anchors/ (with update-ca-certificates), /etc/ca-certificates/trust-source/anchors/ (with trust extract-compat), then /etc/ssl/certs/ (with trust extract-compat). The file is named after the trust-store entry name, <AppName>-localca-<serial>.

macOS. security add-trusted-cert adds the root to the system keychain, then the trust settings are exported, patched and re-imported — again through sudo.

If none of the Linux anchor directories exists, the install fails rather than silently doing nothing.

Why Windows does not work

Two independent reasons, and both are in localca or its trust library rather than in Windows:

  1. The elevation pre-flight cannot succeed. Before any system-store install, localca checks that it can obtain administrator privileges: it is satisfied by os.Geteuid() == 0, otherwise it requires sudo on PATH and an interactive terminal on standard input. On Windows os.Geteuid() always returns -1, so the root branch can never be taken — not even in an already-elevated Administrator console. With no sudo on PATH the check returns ErrElevationUnavailable before the install is attempted. Where a sudo shim is on PATH the check proceeds to run sudo -v, which is not a command Windows sudo accepts, and the install fails with a wrapped error instead.
  2. NSS is not implemented for Windows. The underlying trust library supports NSS on macOS and Linux only. On Windows, targeting StoreNSS is silently skipped and TrustState.NSS is always false.

What still works on Windows: minting the root and leaf, storing them, and serving TLS with them. What does not: getting a browser to trust the result without importing rootCA.pem into the Windows root store yourself.

This is a gap in this module, not a decision. It is recorded in limitations.

What StoreNSS covers

NSS is the certificate database Mozilla products use. localca installs into every NSS profile it finds:

  • every directory matching the Firefox profile glob — ~/.mozilla/firefox/* on Linux, ~/Library/Application Support/Firefox/Profiles/* on macOS;
  • ~/.pki/nssdb, which is what Chrome and Chromium read on Linux.

Chrome and Chromium on macOS read the system keychain, not NSS, so StoreSystem is what covers them there.

A profile counts only if it contains a cert9.db (modern, SQLite) or a cert8.db (legacy). A profile directory that a browser has never opened contains neither and is skipped.

certutil is required for NSS

The NSS install runs certutil from the NSS tools package. Without it:

  • Install skips NSS silently and continues with the system store;
  • Installed reports NSS: false;
  • nothing errors.

Install it with one of:

sudo apt-get install -y libnss3-tools   # Debian, Ubuntu
sudo dnf install -y nss-tools           # Fedora, RHEL
brew install nss                        # macOS

On macOS, certutil is also found via brew --prefix nss when it is not on PATH.

If you cannot install packages, see getting certutil without root.

TrustState.NSS means every profile

The NSS state check reports true only when the root is present in every NSS profile it finds. Adding a new Firefox profile after installing flips NSS back to false until you install again. This never affects serving, because only the system store gates provisioning.

What elevation looks like

Situation Behaviour
Only StoreNSS targeted no elevation, no prompt
Process already running as root (euid == 0) no prompt
Non-root, sudo present, interactive terminal one sudo -v password prompt, then the install runs without prompting again
Non-root, no sudo on PATH ErrElevationUnavailable, nothing is installed
Non-root, no interactive terminal (service, CI, GUI app) ErrElevationUnavailable, nothing is installed

The pre-flight exists so a tool never hangs on a password prompt that nothing can answer. A consumer catches ErrElevationUnavailable and falls back — to an NSS-only install, to an untrusted self-signed certificate, or to telling the user to run one command in a terminal.

There is no desktop password dialog. A windowed application with no terminal gets ErrElevationUnavailable; see no GUI elevation.

Headless servers and CI

A headless Linux box with no sudo, no TTY and no certutil is a supported build target and an unsupported install target: certificate generation works, trust installation returns ErrElevationUnavailable. For CI that needs the root trusted, run the container as root — the pre-flight passes on euid == 0 and no prompt appears.