Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

mkcert User Guide

Generated April 2026 from FiloSottile/mkcert at 1c1dc4e

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

mkcert is a simple, zero-config tool for making locally-trusted development certificates. It creates a local Certificate Authority (CA) on your machine, adds it to the system (and optionally Firefox/Chromium and Java) trust stores, and then issues short-lived TLS certificates for any hostname, IP address, email, or URI you supply. The result: green padlocks in browsers, working HTTPS in development, and no more "self-signed cert" red banners — without asking the public web to trust you.

This guide is for developers who want to use mkcert day-to-day. For architecture, full configuration reference, security analysis, and developer internals, see the mkcert Administrator & Developer Guide in the same output directory.

1. Quick Start

Install mkcert with your package manager, install the local CA into your trust stores, and issue a certificate for localhost — three commands.

Install in 60 seconds (macOS)

brew install mkcert
mkcert -install
mkcert localhost 127.0.0.1 ::1

That generates two files in your current directory:

The certificate is at "./localhost+2.pem" and the key at "./localhost+2-key.pem"
It will expire on 28 July 2028

Wire those two PEM files into whatever HTTPS server you're testing — Caddy, nginx, Express, Go's http.ListenAndServeTLS, Vite, Next.js dev server, etc. Open https://localhost in any browser and you will see a valid, trusted certificate. No flag-overrides, no --insecure, no exception clicks.

Tip

Run mkcert -install only once per machine. After that, every certificate you mint with mkcert <host> is automatically trusted by the browsers and system services that use the OS root store, and (if installed) by Firefox and Java. You can re-issue per-project certificates as often as you like.

What mkcert does (and doesn't) do

  • Generates a private root CA stored in a per-user directory and adds it to your system, NSS (Firefox/Chromium/Chrome), and Java trust stores.
  • Issues leaf certificates valid for exactly 2 years and 3 months for any combination of DNS names, IP addresses, email addresses, and URIs.
  • Supports wildcards (*.example.test), ECDSA keys, client-auth certs, PKCS#12 (.p12 / .pfx) bundles, and certificate signing from a CSR.
  • Does not issue publicly-trusted certificates. The CA mkcert creates is trusted only on your machine. mkcert certificates will not work for production, public websites, or anything outside your dev environment.

Caution

The rootCA-key.pem mkcert generates is a private key for a root certificate authority that your machine will trust completely. Anyone who obtains this key can issue trusted certificates for any domain, including google.com or your bank. Never copy rootCA-key.pem between machines, commit it to source control, or share it. See Section 7 of the Admin Guide for the full security discussion.

2. Installation

mkcert is a single Go binary with no runtime dependencies. The fastest path is your operating system's package manager. Pre-built binaries and a build-from-source option are available for unsupported platforms.

Choose your install method

Pick the row that matches your environment, then run one command.

Platform Easiest method One-liner
macOS Homebrew brew install mkcert
macOS (MacPorts) MacPorts sudo port selfupdate && sudo port install mkcert
Windows Chocolatey choco install mkcert
Windows Scoop scoop bucket add extras && scoop install mkcert
Linux Linuxbrew brew install mkcert
Arch Linux pacman sudo pacman -S mkcert
Any Pre-built binary Download from the releases page (see below)
Any Build from source git clone … && go build -ldflags …

Important

macOS users: You also need the NSS tools so mkcert can install the CA into Firefox. Install them with brew install nss. Without them, Firefox will not pick up your local CA and you will see "this connection is not secure" warnings only in Firefox.

Important

Linux users: To support Firefox and Chromium, install the certutil binary from your distro's NSS tools package. mkcert auto-detects the right command and prints the install instruction if it is missing — apt install libnss3-tools on Debian/Ubuntu, yum install nss-tools on RHEL family, or zypper install mozilla-nss-tools on openSUSE.

macOS (Homebrew)

brew install mkcert
brew install nss   # required for Firefox trust

macOS (MacPorts)

sudo port selfupdate
sudo port install mkcert
sudo port install nss

Windows (Chocolatey)

choco install mkcert

Windows (Scoop)

scoop bucket add extras
scoop install mkcert

Linux (Homebrew on Linux)

brew install mkcert

If you are not on a distro with a native package, Homebrew on Linux is the smoothest path. It installs the binary into ~/.linuxbrew/bin (or /home/linuxbrew/.linuxbrew/bin on shared machines).

Arch Linux

sudo pacman -Syu
sudo pacman -S mkcert
sudo pacman -S nss   # for Firefox trust

Fallback: pre-built binary

If your platform isn't listed above, download a pre-built binary from the GitHub releases page at github.com/FiloSottile/mkcert/releases, mark it executable, and put it on your PATH.

# Linux x86_64 example
curl -L "https://dl.filippo.io/mkcert/latest?for=linux/amd64" -o mkcert
chmod +x mkcert
sudo mv mkcert /usr/local/bin/
mkcert -version

Note

Pre-built binaries are published for linux/amd64, linux/arm, linux/arm64, darwin/amd64, darwin/arm64, and windows/amd64. Other platforms must build from source.

Last resort: build from source

You need Go 1.18 or newer.

git clone https://github.com/FiloSottile/mkcert
cd mkcert
go build -ldflags "-X main.Version=$(git describe --tags)"
./mkcert -version

The -ldflags "-X main.Version=…" step is what makes mkcert -version print a real version string instead of (devel).

Warning

Building inside a Go module that is not the mkcert module will leave mkcert -version reporting (devel). This is a known Go limitation, not a bug — it is documented in the mkcert source comments. Either build outside any other module, or pass an explicit -X main.Version=… linker flag.

Install the local CA

Whichever method got you the binary, the next step is the same: install the local CA into your trust stores. Do this once per machine.

mkcert -install

Expected output:

Created a new local CA 💥
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox and/or Chrome/Chromium trust store (requires browser restart)! 🦊
The local CA is now installed in Java's trust store! ☕️

The exact emoji-flagged lines you see depend on which trust stores are detected on your machine. mkcert auto-detects:

  • The OS system store (macOS Keychain, Windows root store, Linux /etc/ssl/... or equivalent).
  • NSS-based browsers — Firefox, Chrome, and Chromium — when certutil is on your PATH.
  • The Java keystore at $JAVA_HOME/lib/security/cacerts (or $JAVA_HOME/jre/lib/security/cacerts for older JDKs), when keytool is available.

Important

Restart any open browser after running mkcert -install. Browsers cache the trust store at startup; without a restart, freshly-issued certificates may still show as untrusted in tabs that were already open.

Verify your install

Confirm mkcert is on your PATH and find out where it stores the CA:

mkcert -version
mkcert -CAROOT

Expected output:

v1.4.4
/home/jane/.local/share/mkcert

The exact -CAROOT location varies by platform — see the platform table in Section 3.

3. Configuration

mkcert is built to be zero-config. Everything you'd normally need to tune is exposed as either a CLI flag or one of three environment variables. There are no config files — nothing in ~/.config, no mkcert.yaml, nothing to edit. If you want to change behavior, you set an env var or pass a flag.

Environment variables

Variable Purpose Default
CAROOT Override the CA storage directory. Useful for keeping multiple parallel CAs (one per project, one for CI, etc.). Per-platform path (see table below).
TRUST_STORES Comma-separated allow-list of trust stores. Valid entries: system, java, nss. All detected stores.
JAVA_HOME Required only for Java trust-store integration. Tells mkcert where to find keytool and cacerts. Read from environment.

The CA storage location, when CAROOT is unset, is computed from the OS and a small set of standard environment variables.

Platform Default CAROOT
Windows %LocalAppData%\mkcert
macOS $HOME/Library/Application Support/mkcert
Linux $XDG_DATA_HOME/mkcert (if set) or $HOME/.local/share/mkcert

You can always ask mkcert directly:

mkcert -CAROOT

Limit which trust stores get the CA

By default, mkcert -install writes the CA into every trust store it detects. Set TRUST_STORES to limit that to just the ones you want. The value is a comma-separated subset of system, java, nss.

# Install only into the OS system store (skip Firefox + Java)
TRUST_STORES=system mkcert -install

# Install only into Firefox/Chromium (skip system + Java)
TRUST_STORES=nss mkcert -install

Tip

The TRUST_STORES filter applies to both -install and -uninstall. If you only ever installed into nss, set the same value when you uninstall — otherwise mkcert will quietly skip stores it can't find the CA in, which is harmless but might look confusing.

Run multiple CAs side-by-side

Because every aspect of CA storage is keyed on $CAROOT, you can keep as many independent CAs as you want by switching directories. This is the recommended way to keep "personal" and "client work" CAs separate, or to build a one-off CA for a CI pipeline.

# Personal CA (default)
mkcert example.test

# Client-X CA (separate root, separate trust)
CAROOT=$HOME/.mkcert-clientx mkcert -install
CAROOT=$HOME/.mkcert-clientx mkcert client-x.test

Each CA gets its own rootCA.pem and rootCA-key.pem inside its directory.

4. Core Usage

Most of mkcert's surface area is the leaf-certificate command. Run mkcert with one or more host arguments and it issues a cert. Everything else is trust-store management.

Top-level commands

Command What it does
mkcert -install Create the local CA (if missing) and install it into every detected trust store.
mkcert -uninstall Remove the local CA from every trust store. Does not delete the CA on disk.
mkcert <hosts…> Issue a leaf certificate covering the listed hosts.
mkcert -CAROOT Print the directory where the CA is stored.
mkcert -help Print full help, including advanced options.
mkcert -version Print mkcert version and exit.

Issue a certificate

Pass any combination of DNS names, IP addresses, email addresses, and URIs on the command line. mkcert validates each, normalizes IDN domains to punycode, and emits a single cert covering all of them as Subject Alternative Names (SANs).

mkcert example.com myapp.dev localhost 127.0.0.1 ::1

Expected output:

Created a new certificate valid for the following names 📜
 - "example.com"
 - "myapp.dev"
 - "localhost"
 - "127.0.0.1"
 - "::1"

The certificate is at "./example.com+4.pem" and the key at "./example.com+4-key.pem" ✅

It will expire on 28 July 2028 🗓

Two files appear in the current directory:

  • example.com+4.pem — the certificate (PEM-encoded, world-readable, mode 0644).
  • example.com+4-key.pem — the private key (PEM-encoded, mode 0600).

The filename pattern is the first hostname plus +N where N is the count of extra hosts. Wildcards have * replaced by _wildcard, and colons in IPv6 addresses are replaced by underscores.

Choose your output filenames

If you don't want the auto-generated names, point each output to a custom file with the corresponding flag:

mkcert -cert-file server.crt -key-file server.key example.test

For PKCS#12, use -p12-file:

mkcert -pkcs12 -p12-file bundle.p12 example.test

CLI flag reference

Flag Type Effect
-install bool Install local CA into all detected trust stores.
-uninstall bool Remove the CA from all detected trust stores.
-CAROOT bool Print the CAROOT path and exit.
-help bool Print short + advanced usage and exit.
-version bool Print the mkcert version and exit.
-cert-file FILE string Write the leaf certificate to FILE.
-key-file FILE string Write the leaf private key to FILE.
-p12-file FILE string Write the PKCS#12 bundle to FILE (requires -pkcs12).
-client bool Issue a client-authentication cert (sets extKeyUsage clientAuth).
-ecdsa bool Use an ECDSA P-256 key instead of RSA-2048.
-pkcs12 bool Output a PKCS#12 (.p12 / .pfx) bundle instead of PEM.
-csr CSR string Sign the supplied CSR file instead of generating a new key.

Note

All flags use a single dash (-install, not --install). This is Go's standard flag package style and is the only form mkcert accepts.

Combining flags

Most flags can be combined. The hard rules are:

  • -install and -uninstall cannot be set together.
  • -CAROOT cannot be combined with -install or -uninstall.
  • -csr is exclusive with -pkcs12, -ecdsa, and -client. The only flags allowed alongside -csr are -install and -cert-file.
  • -csr cannot be combined with positional host arguments — the hosts are taken from the CSR itself.

If you violate any of these, mkcert exits with ERROR: … immediately and issues nothing.

5. Common Tasks

The recipes below cover the day-to-day workflows that nearly every mkcert user hits eventually. Each one lists the goal, what you need first, the exact steps, how to verify, and what to do if it fails.

5.1 Issue a certificate for localhost

Goal: A trusted certificate so https://localhost works in your local dev server with no browser warnings.

Prerequisites:

  • mkcert installed.
  • mkcert -install already run on this machine.

Steps:

mkcert localhost 127.0.0.1 ::1

Verify:

ls localhost+2.pem localhost+2-key.pem
openssl x509 -in localhost+2.pem -noout -text | grep -A1 "Subject Alternative Name"

You should see DNS:localhost, IP:127.0.0.1, IP:::1 listed.

If it fails: If you see the local CA is not installed in the system trust store, run mkcert -install and retry. If you don't see a +2 suffix on the filename, you only passed one host — that's fine, the file will just be named localhost.pem / localhost-key.pem.

5.2 Issue a certificate for a custom dev domain

Goal: A trusted certificate for myapp.test (or any custom dev TLD) that you point at 127.0.0.1 via /etc/hosts or a local DNS resolver.

Prerequisites:

  • mkcert installed and mkcert -install complete.
  • A line like 127.0.0.1 myapp.test in your hosts file, or a wildcard resolver like dnsmasq pointing *.test at loopback.

Steps:

mkcert myapp.test

Verify:

curl -v https://myapp.test/   # once your dev server is running

The * SSL certificate verify ok. line confirms trust.

If it fails: curl: (6) Could not resolve host means the hosts file or resolver isn't set up — that's a DNS problem, not a mkcert problem. certificate verify failed: unable to get local issuer certificate means mkcert -install was not run, or your client (curl) is using its own bundled CA store rather than the system store. Use --cacert "$(mkcert -CAROOT)/rootCA.pem" for clients that ignore the system store.

5.3 Issue a certificate with multiple SANs (including a wildcard)

Goal: Cover several services from one cert: a wildcard, the apex, localhost, and an IPv4 loopback.

Prerequisites: mkcert -install complete.

Steps:

mkcert "*.dev.local" dev.local localhost 127.0.0.1

Verify:

openssl x509 -in _wildcard.dev.local+3.pem -noout -text | grep "DNS:\|IP:"

You should see all four names.

If it fails: Quote the wildcard. If you see no matches found, that's your shell expanding * — wrap it in single or double quotes ("*.dev.local").

Warning

X.509 wildcards only match one DNS label. *.dev.local covers app.dev.local but not api.staging.dev.local. mkcert prints a reminder when you issue a wildcard cert. Many browsers also reject second-level wildcards like *.local — mkcert prints an explicit warning when it sees one.

5.4 Issue a PKCS#12 bundle for legacy applications

Goal: A .p12 (or .pfx) bundle for IIS, older Java apps, or any tool that wants the cert and key combined into a single PKCS#12 file.

Prerequisites: mkcert -install complete.

Steps:

mkcert -pkcs12 example.test

Verify:

openssl pkcs12 -in example.test.p12 -info -nokeys -password pass:changeit

If it fails: PKCS#12 bundles are encrypted with the password changeit — this is a deliberate, hardcoded default for compatibility with the broad set of tools that expect that password. mkcert prints this in the output of every PKCS#12 issue. If your tool prompts for a password, that's the one.

Important

The PKCS#12 password is changeit — always. It's hardcoded in the source and is intentional: many tools assume that default password. If you need a different password, re-encrypt with openssl pkcs12 -in bundle.p12 -out new.p12 -nodes then re-export with the password you want.

5.5 Issue a client-authentication certificate

Goal: A cert with extKeyUsage = clientAuth, suitable for mTLS or client-cert auth in a browser/curl.

Prerequisites: mkcert -install complete.

Steps:

mkcert -client [email removed]

Verify:

openssl x509 -in 'jane@example.test-client.pem' -noout -text | grep -A1 "Extended Key Usage"

You should see both TLS Web Client Authentication and (because the SAN is an email) E-mail Protection.

If it fails: mkcert validates each argument as DNS, IP, URI, or email in turn. If your value isn't recognized as any of those, you get ERROR: "<value>" is not a valid hostname, IP, URL or email. Quote email addresses to keep your shell from interpreting @.

5.6 Sign a custom CSR

Goal: Issue a certificate from a CSR generated elsewhere (your CI, your load balancer, your hardware token).

Prerequisites:

  • A CSR file in PEM format with type CERTIFICATE REQUEST or NEW CERTIFICATE REQUEST.
  • mkcert -install complete.

Steps:

mkcert -csr request.csr

Verify: mkcert prints the output filename and SANs:

Created a new certificate valid for the following names 📜
 - "myapp.test"

The certificate is at "./myapp.test.pem" ✅

If it fails:

  • failed to read the CSR: unexpected content — the file isn't a PEM block. Re-export.
  • expected CERTIFICATE REQUEST, got … — the PEM type is wrong (often CERTIFICATE instead of CERTIFICATE REQUEST). Generate a CSR, not a cert.
  • invalid CSR signature — the CSR was tampered with or its signature doesn't match the embedded public key. Regenerate.

Note

When using -csr, mkcert ignores -pkcs12, -ecdsa, and -client, and you cannot pass extra host arguments — names come from the CSR's subjectAltName extension (or, as a fallback, the CSR's Common Name).

5.7 Find and back up your CA

Goal: Locate the CA on disk so you can back it up, or copy it to another machine you control.

Prerequisites: mkcert installed.

Steps:

mkcert -CAROOT
ls "$(mkcert -CAROOT)"

Verify:

/home/jane/.local/share/mkcert
rootCA-key.pem  rootCA.pem

If you want to back the CA up, copy the entire directory to a trusted backup location:

tar -czf mkcert-ca-backup.tar.gz -C "$(mkcert -CAROOT)" .

If it fails: If -CAROOT prints nothing, mkcert couldn't compute a default. That happens on Linux when both XDG_DATA_HOME and HOME are empty. Set CAROOT explicitly: export CAROOT=/path/of/your/choice.

Caution

rootCA-key.pem is the private key for a root CA your machine trusts unconditionally. Treat the backup file at least as carefully as you treat your SSH private keys. Encrypt the archive at rest, and never commit it.

5.8 Uninstall the local CA

Goal: Remove the CA from your trust stores when you're done with mkcert (or moving to a different machine).

Prerequisites: None.

Steps:

mkcert -uninstall

Expected output:

The local CA is now uninstalled from the system trust store(s)! 👋

Verify: Re-run mkcert <some host>. mkcert will print Note: the local CA is not installed in the system trust store along with whichever stores it could not find the CA in.

If it fails: mkcert -uninstall only removes the CA from trust stores. The CA files (rootCA.pem, rootCA-key.pem) stay on disk at -CAROOT. To purge them too:

rm -rf "$(mkcert -CAROOT)"

Do this only if you are certain you don't want any previously-issued certificates to be re-installable.

5.9 Use an ECDSA key instead of RSA

Goal: Smaller, faster keys (P-256 ECDSA) for tools or servers where that matters.

Prerequisites: mkcert -install complete.

Steps:

mkcert -ecdsa example.test

Verify:

openssl x509 -in example.test.pem -noout -text | grep "Public Key Algorithm"

You should see Public Key Algorithm: id-ecPublicKey.

If it fails: ECDSA leaf certs work in every modern browser. If your specific tool rejects them, drop -ecdsa and use the default RSA-2048. The CA itself uses RSA-3072 regardless of -ecdsa — that flag only affects the leaf key.

6. Troubleshooting

When something goes wrong, the first move is almost always to re-run the failing command and read the actual error. mkcert prints clear ERROR:, Warning:, and Note: lines and exits non-zero on hard failures.

Diagnostic decision tree

  1. Is mkcert on your PATH? mkcert -version should print a version.
  2. Is the CA installed? mkcert -install should be idempotent — run it. If it prints "already installed", you're good.
  3. Did you restart the browser? Browsers cache trust at startup.
  4. Is the certificate actually loaded by your server? A trusted cert in a file is useless if your server is using a different one.

Error: failed to find the default CA location, set one as the CAROOT env var

Cause: mkcert couldn't compute a default CAROOT because both XDG_DATA_HOME and HOME are unset (typically only happens in stripped container environments or some CI runners).

Solution:

export CAROOT=$HOME/.mkcert
mkcert -install

Prevention: Set CAROOT explicitly in CI configs and ephemeral containers — never rely on the auto-detected default in those environments.

Error: can't create new certificates because the CA key (rootCA-key.pem) is missing

Cause: mkcert is running in "keyless mode" — it found rootCA.pem but not rootCA-key.pem in CAROOT. This happens when you copy only the public CA cert to a machine and try to issue from it.

Solution: Either issue certs on the machine that has the key, or copy rootCA-key.pem to the keyless machine. Keyless mode supports -install but not certificate issuance.

Prevention: When provisioning a new dev machine, copy both rootCA.pem AND rootCA-key.pem from the source CAROOT.

Error: "<value>" is not a valid hostname, IP, URL or email

Cause: mkcert validates every positional argument as DNS, IP, URL, or email and rejects anything that doesn't match. Common causes:

  • A trailing comma or space inside what you thought was one hostname.
  • A hostname with characters mkcert's regex doesn't allow (only 0-9a-z._- and an optional leading *.).
  • A URL that's missing a scheme (example.com/path — no scheme means it's parsed as a hostname, and /path makes it invalid).

Solution: Quote each host, drop trailing punctuation, and lowercase everything. For URIs, include the scheme: spiffe://trust-domain/foo.

Prevention: Echo your command back before running it — trailing characters are easy to miss.

Error: no Firefox and/or Chrome/Chromium security databases found

Cause: mkcert searches a fixed list of NSS database paths (~/.pki/nssdb, ~/snap/chromium/.../nssdb, /etc/pki/nssdb, plus Firefox profile directories). If none exist, you get this error. This is the situation tracked by issue #120.

Solution:

  1. Open Firefox or Chromium at least once. NSS databases are created lazily on first run.
  2. Confirm the database exists: ls ~/.pki/nssdb (Chromium) or check your Firefox profile dir.
  3. Re-run mkcert -install.

Prevention: On a fresh user account, start the browsers once before running mkcert -install.

Error: Firefox on macOS still shows "Not Secure"

Cause: Several open issues track this — #326, #370, and #662. The common root causes are: (a) the NSS tools aren't installed (brew install nss was skipped); (b) Firefox is using a custom profile directory that mkcert doesn't search (issue #521); (c) Firefox Developer Edition uses a separate trust DB.

Solution:

  1. brew install nss and re-run mkcert -install.
  2. Restart Firefox completely (not just the window — quit the app).
  3. If you use a custom profile, copy rootCA.pem and import it manually via Firefox → Settings → Privacy & Security → View Certificates → Authorities → Import.

Prevention: Stick to the default Firefox profile if you want mkcert to manage trust automatically.

Error: SSL_ERROR_RX_RECORD_TOO_LONG in Firefox

Cause: Tracked in issue #361. This is almost always a server-side misconfiguration: your dev server is speaking plain HTTP on the port Firefox is connecting to as HTTPS. mkcert is not at fault — it's a wiring problem.

Solution: Confirm your dev server is actually listening for TLS on the port you're hitting. For Vite, that's server.https = true; for Express, https.createServer({key, cert}, app); for nginx, ssl on; ssl_certificate …; ssl_certificate_key …;.

Prevention: When wiring up a new dev server, hit it once with curl -v https://localhost:PORT first — curl errors are clearer than browser ones for TLS-vs-HTTP confusion.

Error: "sudo" is not available, and mkcert is not running as root

Cause: On Linux/macOS, mkcert needs root to update the system trust store. It uses sudo by default; if sudo isn't on your PATH and you aren't already root, the install of the system store will be skipped or will fail.

Solution: Either run mkcert as root (su -; mkcert -install) or install sudo (apt install sudo, etc.).

Prevention: Don't run mkcert in stripped containers without sudo — use TRUST_STORES=nss mkcert -install if you only need browser trust.

Error: PKCS#12 won't import — wrong password

Cause: The PKCS#12 export password is hardcoded to changeit. If your tool is prompting and changeit doesn't work, the file is corrupted, not the password.

Solution: Re-issue the bundle: mkcert -pkcs12 -p12-file new.p12 example.test. Use the changeit password to import.

Prevention: Save the bundle straight to where it's needed; don't roundtrip through scp/email/etc., which can corrupt binary files if a client treats them as text.

Error: Cert is rejected by Traefik / cert-manager / your tool

Cause: Tracked in issue #646 for Traefik, #350 for cert-manager comparisons. mkcert certs are short-lived (≈2y3m) and are signed by a CA your tool may not trust by default. Tools running inside containers do not see your host's trust store.

Solution: Mount the CA into the container at the right path:

docker run -v "$(mkcert -CAROOT)/rootCA.pem:/etc/ssl/certs/mkcert-rootCA.pem" …

or copy it into the container image during build.

Prevention: When containerizing your dev stack, treat the mkcert root CA as a build-time secret/asset and mount it explicitly.

Note: macOS 26.1 — root certificate no longer applicable for leaf certs

Cause: Tracked in issue #651. Newer macOS releases tightened root-cert acceptance rules.

Solution: Watch the upstream issue. As of commit 1c1dc4e, no mitigation has shipped in mkcert itself. Workaround: re-issue with a shorter validity if your tool requires it, or pin the root through your app rather than the OS keychain.

Prevention: None — track the issue.

7. FAQ

Q: Where does mkcert store the CA?

In a per-user directory determined by your OS. On macOS it's $HOME/Library/Application Support/mkcert; on Windows, %LocalAppData%\mkcert; on Linux, $XDG_DATA_HOME/mkcert or $HOME/.local/share/mkcert. Override this with the CAROOT environment variable. To see the active path:

mkcert -CAROOT

Q: How long are mkcert certificates valid for?

Leaf certificates are valid for 2 years and 3 months. The CA itself is valid for 10 years. macOS and iOS reject leaf certs valid for longer than 825 days, so mkcert's 2y3m is the safe ceiling.

Q: Can I use mkcert in production?

No. The CA mkcert creates is trusted only on machines where you've run mkcert -install. Anyone else hitting your service will see a "not trusted" error. For production use Let's Encrypt or a commercial CA. See the Admin Guide Section 7 for the full security discussion.

Q: Why doesn't mkcert -version print a real version when I built from source?

Go embeds the version of the main module via debug.BuildInfo, but if you build mkcert as part of a different module (or directly from a Git clone without any module context), Go reports (devel). Build with go build -ldflags "-X main.Version=$(git describe --tags)" to bake in a real version. This is documented in mkcert's source comments referencing golang/go#29814 and golang/go#29228.

Q: How do I share my CA between machines I own?

Copy the entire CAROOT directory (both rootCA.pem and rootCA-key.pem) to the same path on the other machine, then run mkcert -install there. Treat the copy operation like sharing an SSH private key — encrypted transport, no clouds you don't control. See Section 5.7.

Q: Can I customize the root CA's name (Organization, Common Name, etc.)?

Not via flags. The CA's Subject is hardcoded to O=mkcert development CA, OU=<user>@<host>, CN=mkcert <user>@<host>. Issue #229 tracks this as a feature request. If you must customize, build mkcert from source with a patched newCA() in cert.go.

Q: Does mkcert support IPv6?

Yes. Pass IPv6 addresses on the command line just like IPv4:

mkcert localhost ::1 fe80::1

The output filename uses underscores in place of colons.

Q: Why is the PKCS#12 password changeit?

It's the de facto standard default for keystores (Java's cacerts uses it, many tools assume it). mkcert hardcodes it for compatibility with the broadest set of tools. There is no flag to change it; re-encrypt with openssl if you need a different password.

Q: Can I limit which trust stores mkcert touches?

Yes — set TRUST_STORES to a comma-separated subset of system, nss, java. Example: TRUST_STORES=system mkcert -install only writes to the OS root store.

Q: How do I issue a cert with a wildcard?

Quote it so your shell doesn't expand the asterisk:

mkcert "*.example.test"

The output filename will be _wildcard.example.test.pem. Wildcards only match one DNS label (the asterisk does not match dots), and many browsers reject second-level wildcards like *.test — mkcert prints a warning when it sees one. See Section 5.3.

Q: Can I use mkcert without installing the CA into the system store?

Yes — skip mkcert -install, and use clients that take an explicit CA file. With curl --cacert "$(mkcert -CAROOT)/rootCA.pem" you can verify mkcert-issued certs without touching any trust store. This is also useful in CI: ship rootCA.pem as a build artifact, point your test clients at it.

Q: Does mkcert work on Apple Silicon / ARM Linux?

Yes — pre-built binaries exist for darwin/arm64 and linux/arm64. See the GitHub releases page. For other ARM variants (e.g. armv5), build from source with the appropriate GOARCH. Issue #652 discusses cross-arch support more broadly.

Q: How do I rotate or regenerate the CA?

Run mkcert -uninstall, then rm -rf "$(mkcert -CAROOT)", then mkcert -install. mkcert will create a fresh CA. Every previously issued leaf certificate becomes invalid the moment you do this — they were signed by a CA that no longer exists in any trust store. Re-issue the certs you still need.

Q: Is mkcert affected by recent macOS / iOS root-cert restrictions?

Some are tracked in upstream issues — see issue #651 for the macOS 26.1 changes and #343 for general expiration discussion. mkcert already targets the 825-day ceiling Apple platforms enforce, so most users are unaffected.