mkcert: local development certificates
mkcert is the tool you reach for the moment a browser throws a trust error at a self-signed localhost certificate. It skips the entire manual CA workflow — generating a root CA, importing it into every browser's trust store, and reissuing certs by hand — down to two commands. For local HTTPS work it's about as close to zero-config as certificate tooling gets.
The HTTPS headache in local development
Local HTTPS breaks in a specific way: browsers reject self-signed certificates outright, and getting a real CA-signed cert for `localhost` or `example.test` isn't possible because those names aren't publicly resolvable. The usual fallback — hand-rolling a CA with openssl, then digging through each browser's and OS's separate trust-store UI to import it — is the kind of one-off task developers redo badly every few months because nobody remembers the flags. It's tedious, not hard.
A zero-config local Certificate Authority
mkcert is a small Go command-line tool that acts as a local Certificate Authority on your own machine. Instead of letting a browser warn about a self-signed certificate, mkcert creates a root CA, installs it into the system, Firefox NSS, and Java trust stores, then signs TLS certificates for any names you give it — including localhost, 127.0.0.1, ::1, and custom `.test` domains.
What mkcert can do
- ✓Creates and installs a local root CA with one command (`mkcert -install`), covering the system trust store, Firefox's NSS store, and Java's store when `JAVA_HOME` is set
- ✓Issues TLS certificates for multiple names in one call — domains, wildcards like `*.example.com`, localhost, IPv4/IPv6 addresses, and `.test` TLDs
- ✓Generates S/MIME certificates automatically when one of the supplied names is an email address
- ✓Supports ECDSA keys via `-ecdsa` and PKCS#12 (`.p12`/`.pfx`) bundles via `-pkcs12` for apps that need older certificate formats
- ✓Can sign an existing CSR directly with the `-csr` flag instead of generating a new key pair
- ✓Lets you export just the root CA (`rootCA.pem`) to install on other machines without exposing the private key
Installing mkcert
macOS: `brew install mkcert` (add `brew install nss` if you use Firefox), or via MacPorts with `sudo port install mkcert`. Linux: install `certutil` first (e.g. `sudo apt install libnss3-tools`), then `brew install mkcert` through Homebrew on Linux, build from source with Go 1.13+, or grab a prebuilt binary from the releases page — Arch users can also run `sudo pacman -Syu mkcert`. Windows: `choco install mkcert` via Chocolatey, or `scoop bucket add extras && scoop install mkcert` via Scoop; if you hit permission errors, run it as Administrator. After installing the binary, run `mkcert -install` once to create and trust the local CA.
Generating trusted certificates with mkcert
Run `mkcert -install` once per machine to create the local CA and register it with the system (and Firefox, if `nss` is installed) — you'll see a confirmation line for each store. Then generate a certificate with `mkcert example.com "*.example.com" example.test localhost 127.0.0.1 ::1`, which writes a `.pem` cert and `-key.pem` key named after the first domain, e.g. `example.com+5.pem`. mkcert only produces the cert and key files; it does not configure your server to use them. For Node.js, since Node ignores the system trust store, set `NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"` before running your app.
Strengths
- ✓Collapses a normally multi-step manual CA process into two commands instead of separate openssl and trust-store steps
- ✓Covers more trust stores in one pass than a hand-rolled CA usually would — system, Firefox/NSS, and Java when configured
- ✓Handles mixed name types (domains, wildcards, IPs, `.test` TLDs) in a single invocation rather than one cert per format
- ✓The root CA can be exported and copied to another machine, so a team can share one trusted CA instead of each person generating their own
Security caveats and what mkcert is not
- △The generated `rootCA-key.pem` file grants full power to intercept any HTTPS traffic trusted by that CA — the README warns explicitly not to share it, and that's a real risk, not a hypothetical one
- △mkcert only creates and installs certificates; it does nothing to configure your web server, proxy, or app to actually serve them
- △Node.js doesn't read the system trust store at all, so every Node process needs `NODE_EXTRA_CA_CERTS` set manually or it still rejects mkcert certs
- △It's explicitly a development tool: the README says it should not be used on end users' machines or in production, since that means distributing a CA whose private key you control
- △Mobile trust setup is manual and OS-specific — iOS needs AirDropping or emailing the CA file and enabling full trust in Settings, Android needs installing the CA and enabling user roots in a development build
Alternatives and similar tools
Frequently asked questions
mkcert is safe for local development because it only touches your own machine's trust stores and keeps the CA's private key file, `rootCA-key.pem`, on disk under your control. The catch is that anyone who gets a copy of that key file can mint certificates your browser will trust, so treat it like a secret and never commit or share it.
mkcert does support Firefox on Linux — it's listed as one of the supported root stores, alongside macOS. You need `certutil` installed first, for example `libnss3-tools` on Debian/Ubuntu or `nss-tools` on Fedora/RHEL, otherwise mkcert can create the CA but can't register it in Firefox's separate NSS trust store.
On iOS, AirDrop or email yourself the `rootCA.pem` file from the folder mkcert prints via `mkcert -CAROOT`, open it to install the profile under Settings > Profile Downloaded, then enable full trust for it separately. On Android, install that same CA file and enable user roots inside the development build of your app, since the OS store alone isn't enough.
mkcert certificates need one extra step for Node.js because Node doesn't read the operating system's trust store the way browsers do. Set the environment variable `NODE_EXTRA_CA_CERTS` to the path of `rootCA.pem`, for example `export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"`, before starting your Node process.
mkcert certificates are not meant for production — the project describes itself as a development tool, and using its certs on end users' machines would mean distributing a CA whose private key you control, which defeats the purpose of public certificate validation. Production HTTPS needs a certificate from a publicly trusted CA instead.
Installing the mkcert root CA elsewhere only needs the certificate, not the private key: copy `rootCA.pem` from the folder shown by `mkcert -CAROOT` to the other machine, point the `CAROOT` environment variable at its directory, then run `mkcert -install` there to register it in that machine's trust stores.
Best use cases
- •Running a local dev server over HTTPS without a certificate warning on every reload
- •Testing OAuth callbacks, service workers, or browser APIs that only work on a secure context
- •Generating a client-auth or S/MIME certificate to test mutual TLS or signed email locally
- •Sharing one team-wide root CA across a few machines so a shared `*.test` staging setup stays trusted
Who should try it — and who should skip
Reach for mkcert if you're setting up any local dev server that needs HTTPS — an OAuth callback, a service worker, a webhook receiver — and you're tired of clicking through browser warning pages. It also fits teams that want one shared root CA across a handful of dev machines instead of everyone hand-rolling their own. Skip it if you need production-grade certificate issuance or automated renewal — mkcert has no ACME support, and the README is explicit that it's not meant for end users' machines.
Related repositories
Is mkcert worth your time?
ChatGPT, Claude and Perplexity can all read this page. Ask one of them what it makes of mkcert.
