Skip to content
Dev Tools Beginner Tutorial

Set Up Trusted Local HTTPS with mkcert

Generate a real, browser-trusted TLS certificate for localhost in minutes — no more certificate warnings during local development.

Lenn Voss
Lenn Voss
Cloud & Infrastructure Writer · Jun 12, 2026 · 4 min read

What You'll Build

You'll install mkcert, register a local Certificate Authority with your OS and browser, and generate a TLS certificate so any dev server runs on https://localhost with a padlock and no warnings — identical behavior to a production HTTPS endpoint.

Prerequisites

Requirement Details
macOS 12+ or Ubuntu 20.04+ Windows users: swap brew install for scoop install mkcert
Homebrew macOS/Linux — install at brew.sh
Node.js 18+ Only needed for the example server

Step 1 — Install mkcert

brew install mkcert

Firefox users need extra NSS tooling installed before Step 2, or Firefox won't trust the CA:

# macOS
brew install nss

# Ubuntu / Debian Linux
sudo apt install libnss3-tools

Step 2 — Create and Install Your Local CA

This single command creates a root Certificate Authority and registers it with your OS trust store. Chrome and Safari pick it up automatically. Run this once per machine — not once per project.

mkcert -install

You'll be prompted for your system password. To confirm where the CA files live:

mkcert -CAROOT
# Example: /Users/you/Library/Application Support/mkcert

⚠ Security note: The CA root key lives only on your machine. Never commit it or share it — anyone with it can issue trusted certificates for any domain on any browser that trusts your CA.

Step 3 — Generate a Certificate for Localhost

From your project directory, run:

mkcert localhost 127.0.0.1 ::1

Covering the hostname, IPv4, and IPv6 loopback means it works however your server binds. Two files appear in the current directory:

Advertisement
File Purpose
localhost+2.pem Certificate (public — safe to commit if needed)
localhost+2-key.pem Private key — never commit this

Add the key pattern to .gitignore immediately:

echo "*-key.pem" >> .gitignore

Step 4 — Start a Secure Dev Server

Create server.js using Node's built-in https module — no extra packages required:

const https = require('https');
const fs = require('fs');

const server = https.createServer(
  {
    key: fs.readFileSync('localhost+2-key.pem'),
    cert: fs.readFileSync('localhost+2.pem'),
  },
  (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello, secure localhost!\n');
  }
);

server.listen(3000, () => console.log('Listening on https://localhost:3000'));
node server.js

Verify It Works

Open https://localhost:3000 in your browser. You should see:

  • A padlock icon with no security warning
  • The text Hello, secure localhost!

Also verify with curl — if the CA is trusted system-wide, this works too:

curl https://localhost:3000
# Hello, secure localhost!

Troubleshooting

Firefox still shows a certificate warning Firefox uses its own NSS certificate store. Install nss (macOS: brew install nss) or libnss3-tools (Linux: sudo apt install libnss3-tools), then re-run mkcert -install and fully restart Firefox.

mkcert -install warns it can't write to the system trust store on Linux Always run mkcert -install as your normal (non-root) user — never prefixed with sudo. mkcert internally requests elevated privileges (via sudo or pkexec) only when it needs to write to the system trust store, so you'll be prompted automatically. Running the entire command as root stores the CA under the root user's home directory; subsequent non-root runs won't find it and will generate a new, untrusted CA instead.

ENOENT: no such file or directory, open 'localhost+2-key.pem' Cert files are created in whichever directory was active when you ran mkcert. Move them to your project root or use the full absolute path in readFileSync.

Chrome shows NET::ERR_CERT_AUTHORITY_INVALID right after install Chrome caches the trust store at startup. Fully quit Chrome (Cmd+Q / Alt+F4) and relaunch — it will pick up the new CA on restart.

Next Steps

  • Vite projects: vite-plugin-mkcert automates certificate wiring inside vite.config.js.
  • Custom .test domains: Add 127.0.0.1 myapp.test to /etc/hosts, then run mkcert myapp.test to mirror your real domain name locally.
  • Other frameworks: Pass the same key/cert paths to Express, Fastify, or any HTTPS-capable server — the options are identical.
  • Production TLS: mkcert is development-only. Use Let's Encrypt (via Certbot or your platform's managed TLS) for staging and production environments.
Lenn Voss
Written by
Lenn Voss · Cloud & Infrastructure Writer

Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.

Discussion 0

Join the discussion

Sign in or create an account to comment and vote.

No comments yet

Be the first to weigh in.

Related Reading