mkcert is a small tool that creates locally trusted HTTPS certificates for development. It saves you from browser warnings when your app needs https://localhost, 127.0.0.1, or a custom local hostname.
Use it when the browser on your own machine must trust the local server. Use a tunnel when you only need to send someone else a temporary HTTPS review link.
mkcert setup in one pass
The basic flow has three steps:
- Install mkcert and any browser trust helpers.
- Run
mkcert -installonce to create and trust a local CA. - Generate certificates for the names your dev server will use.
On macOS with Homebrew:
brew install mkcert
brew install nss # if you use Firefox
mkcert -install
mkcert localhost 127.0.0.1 ::1
The final command creates a certificate file and key file in the current directory. The filenames include the hostnames you requested.
On Linux, install certutil first. Package names vary by distro:
# Debian or Ubuntu
sudo apt install libnss3-tools
# Fedora, RHEL, or CentOS
sudo yum install nss-tools
# Arch
sudo pacman -S nss
# openSUSE
sudo zypper install mozilla-nss-tools
Then install mkcert with Homebrew on Linux, a package manager, a prebuilt binary, or from source. After install:
mkcert -install
mkcert localhost 127.0.0.1 ::1
On Windows, the mkcert README lists Chocolatey and Scoop paths:
choco install mkcert
mkcert -install
mkcert localhost 127.0.0.1 ::1
or:
scoop bucket add extras
scoop install mkcert
mkcert -install
mkcert localhost 127.0.0.1 ::1
If Windows permissions block root store changes, run the install step from an Administrator shell.
Create a certificate for localhost and custom hostnames
Most local apps use localhost, an IP loopback address, or a custom hostname mapped through /etc/hosts.
Generate a certificate for several names at once:
mkcert localhost 127.0.0.1 ::1 app.test api.test
For wildcard subdomains:
mkcert "*.app.test" app.test
Then point local DNS at your machine. On macOS and Linux, edit /etc/hosts:
127.0.0.1 app.test
127.0.0.1 api.test
The certificate must include the exact hostname the browser opens. If you open https://app.test:3000, the cert needs app.test. If you open https://localhost:3000, it needs localhost.
Configure your dev server
mkcert creates certificates. It does not reconfigure your dev server.
For a Node HTTPS server:
import fs from "node:fs";
import https from "node:https";
const options = {
key: fs.readFileSync("localhost+4-key.pem"),
cert: fs.readFileSync("localhost+4.pem"),
};
https.createServer(options, (request, response) => {
response.end("ok");
}).listen(3000);
For Vite, you can pass certificate files through server HTTPS config:
import fs from "node:fs";
import { defineConfig } from "vite";
export default defineConfig({
server: {
https: {
key: fs.readFileSync("localhost+4-key.pem"),
cert: fs.readFileSync("localhost+4.pem"),
},
},
});
Framework options change over time. Check your framework docs for current config keys before copying this into a production repo.
Security notes for mkcert
mkcert is for development. Do not use it for production certificates.
The main file to protect is rootCA-key.pem. The mkcert README warns that this key gives complete power to intercept secure requests from your machine because your machine trusts the local CA. Do not share that private key with teammates, clients, or CI systems.
To find the CA directory:
mkcert -CAROOT
Team workflows should document the commands each developer runs on their own machine. They should not commit local certificates or root CA keys unless a specific dev environment requires disposable certs and your team has reviewed the risk.
Node has one more edge case: Node does not always use the same system trust store as your browser. If a Node process must trust mkcert certificates for outbound requests, the README recommends NODE_EXTRA_CA_CERTS:
export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"
When mkcert is the wrong tool
mkcert solves local trust. It does not create a public URL.
If your real goal is “send this local build to a reviewer,” use a tunnel. wiremaven creates temporary encrypted public links for local dev servers. Your machine opens an outbound-only WebSocket connection to the relay. The reviewer gets a browser link. You see viewer joins, request outcomes, failures, and the TTL.
npx wiremaven-cli 3000 --expires 30m --name https-review
During beta, wiremaven does not require an account. You can choose 15, 30, or 60 minute review windows.
Use mkcert when your local browser needs https://localhost. Use wiremaven when someone outside your machine needs a temporary HTTPS link to your running local server.
For setup paths, see the wiremaven docs. For the relay architecture, read how wiremaven works.
Troubleshooting
If the browser still warns, check the hostname first. Certificates do not cover names you did not include.
If Firefox warns, install NSS support and restart Firefox. On macOS, that usually means brew install nss before mkcert -install.
If your server fails to start, confirm that the key and cert paths match the generated filenames. If Node cannot call an HTTPS local service, set NODE_EXTRA_CA_CERTS for that process.
If a teammate cannot open your local HTTPS URL, remember that mkcert trust is per machine. They need their own setup or a tunnel link.
FAQ
What does mkcert do?
mkcert creates a local certificate authority and certificates your machine trusts for development hostnames such as localhost or app.test.
Is mkcert safe?
mkcert is safe for local development when you protect the root CA private key. Do not share rootCA-key.pem.
Does mkcert make localhost public?
No. mkcert only handles local certificate trust. Use a tunnel when a remote reviewer needs to open your local app.
Can I use mkcert with Firefox?
Yes. Install NSS support first on macOS and Linux, then run mkcert -install.
Start with the right HTTPS path
For ongoing local HTTPS:
mkcert -install
mkcert localhost 127.0.0.1 ::1
For a temporary reviewer link:
npx wiremaven-cli 3000 --expires 30m
Related: HTTPS Localhost: mkcert, Self-Signed Certs, and Tunnels | How to Share Localhost with a Client | What Is a Localhost Tunnel?