Local HTTPS on Mac with mkcert (Vite, Next.js & .test Domains)

Local HTTPS on Mac with mkcert (Vite, Next.js & .test Domains)

Updated 7 min read

Install mkcert on Mac, trust the local CA, and generate HTTPS certs for localhost and .test domains. Includes Vite, Next.js, Docker, and NET::ERR_CERT_AUTHORITY_INVALID fixes.

mkcert ssl local is the fastest way to get browser-trusted HTTPS on Mac for localhost, 127.0.0.1, and custom .test domains - no self-signed warnings, no tunneling.

mkcert ssl local - copy-paste setup (Mac)

Run these three commands in Terminal:

brew install mkcert
mkcert -install
mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem localhost 127.0.0.1 ::1 myproject.test "*.myproject.test"
How many times will you retype this command this month?Automate it with ToggleHosts

Then point your dev server at certs/local-cert.pem and certs/local-key.pem. Open https://localhost:3000 or https://myproject.test - the padlock should be green.

StepCommandWhat it does
1brew install mkcertInstalls the mkcert CLI
2mkcert -installCreates a local CA trusted by macOS + browsers
3mkcert localhost …Generates a signed cert + private key

Still seeing NET::ERR_CERT_AUTHORITY_INVALID? → Fix mkcert certificate errors Changed /etc/hosts or DNS? → Flush DNS on Mac first.


Developing a PWA and Service Workers refuse to activate? Geolocation, Clipboard, and WebRTC APIs require a secure context (HTTPS). mkcert fixes this permanently on your machine in under two minutes.

Why mkcert ssl local beats alternatives

ApproachBrowser trustSetup timeBest for
mkcertTrusted padlock~2 minDaily local dev
Self-signed OpenSSLWarnings every time~10 minQuick one-off tests
ngrok / Cloudflare TunnelPublic HTTPS URL~5 minWebhooks, mobile testing
Caddy auto-HTTPSLocal trust~15 minAlways-on local proxy

Use mkcert when you want https://myproject.test to behave exactly like production HTTPS on your Mac.

Quick setup: mkcert SSL local on Mac

For most local development projects, this is the fastest path:

  1. Install mkcert with Homebrew.
  2. Run mkcert -install once to trust the local certificate authority.
  3. Generate certificates for localhost, 127.0.0.1, ::1 and your custom .test domains.
  4. Point your dev server to the certificate and key files.
  5. Restart the browser if it still shows a certificate warning.
brew install mkcert
mkcert -install
mkdir -p certs
mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem localhost 127.0.0.1 ::1 myproject.test "*.myproject.test"

You can now configure your server with certs/local-cert.pem and certs/local-key.pem.

Why HTTPS locally?

APIs that require HTTPS

Many modern web APIs only work in secure contexts (HTTPS):

  • Service Workers: Required for PWAs
  • Geolocation API: GPS location
  • Clipboard API: Copy/paste
  • WebRTC: Video/audio
  • Web Bluetooth: Bluetooth devices
  • Push Notifications: Push API

Other advantages

  • Dev/prod parity: Same behavior everywhere
  • Secure cookies: Test Secure and SameSite attributes
  • HTTP/2: Requires HTTPS
  • Credibility: No browser warnings

Installing mkcert

What is mkcert?

mkcert is a tool created by Filippo Valsorda that:

  1. Creates a local certificate authority (CA)
  2. Installs this CA in your system and browsers
  3. Generates certificates signed by this CA

Result: your local certificates are recognized as valid.

Installation on Mac

# With Homebrew
brew install mkcert

# Install root certificates
mkcert -install

You'll see a message asking for your password to install the CA in the system keychain.

Verify installation

mkcert -CAROOT

Shows the folder containing your local CA.

Creating certificates

For localhost

mkcert localhost 127.0.0.1 ::1

Creates two files:

  • localhost+2.pem: The certificate
  • localhost+2-key.pem: The private key

For a custom domain

mkcert myproject.test

With wildcard (subdomains)

mkcert myproject.test "*.myproject.test"

Allows using api.myproject.test, admin.myproject.test, etc.

All-in-one certificate

mkcert localhost 127.0.0.1 ::1 myproject.test "*.myproject.test"

Configuring your server

Node.js / Express

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

const app = express();

const options = {
    key: fs.readFileSync('./localhost+2-key.pem'),
    cert: fs.readFileSync('./localhost+2.pem')
};

https.createServer(options, app).listen(3000, () => {
    console.log('HTTPS server running on https://localhost:3000');
});

See also: mkcert + Vite & Next.js local HTTPS for a full monorepo setup.

// vite.config.js
import { defineConfig } from 'vite';
import fs from 'fs';
import path from 'path';

const certDir = path.resolve(__dirname, 'certs');

export default defineConfig({
    server: {
        host: 'myproject.test',
        https: {
            key: fs.readFileSync(path.join(certDir, 'local-key.pem')),
            cert: fs.readFileSync(path.join(certDir, 'local-cert.pem')),
        },
    },
});

Add 127.0.0.1 myproject.test to your hosts file (see edit hosts on Mac), then run npm run dev and open https://myproject.test:5173.

Next.js 15+ (experimental HTTPS)

next dev --experimental-https --experimental-https-key certs/local-key.pem --experimental-https-cert certs/local-cert.pem

Recent Next.js versions can run the development server over HTTPS directly. If your setup needs custom routing or a proxy, use a custom server instead:

// next.config.js with custom server
const { createServer } = require('https');
const { parse } = require('url');
const next = require('next');
const fs = require('fs');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

const httpsOptions = {
    key: fs.readFileSync('./localhost+2-key.pem'),
    cert: fs.readFileSync('./localhost+2.pem')
};

app.prepare().then(() => {
    createServer(httpsOptions, (req, res) => {
        const parsedUrl = parse(req.url, true);
        handle(req, res, parsedUrl);
    }).listen(3000);
});

Webpack Dev Server

// webpack.config.js
const fs = require('fs');

module.exports = {
    devServer: {
        https: {
            key: fs.readFileSync('./localhost+2-key.pem'),
            cert: fs.readFileSync('./localhost+2.pem')
        }
    }
};

Using with custom domains

Configure the hosts file

To use myproject.test instead of localhost:

# /etc/hosts
127.0.0.1    myproject.test
127.0.0.1    api.myproject.test

Create the corresponding certificate

mkcert myproject.test "*.myproject.test"

Configure the server

Use the newly generated files in your server configuration.

Advanced use cases

Laravel Valet

Valet integrates mkcert natively:

valet secure myproject

That's it! Valet automatically generates and configures certificates.

Docker

# docker-compose.yml
services:
  web:
    volumes:
      - ./certs:/etc/nginx/certs:ro
    environment:
      - VIRTUAL_HOST=myproject.test
      - CERT_NAME=myproject.test

MAMP Pro

  1. Preferences > Hosts
  2. Select your host
  3. SSL > Enable
  4. Import your mkcert certificates

Troubleshooting

"NET::ERR_CERT_AUTHORITY_INVALID"

The CA is not installed in the browser.

mkcert -install

Then restart your browser. If the error persists after reinstalling the CA, follow the dedicated walkthrough on how to fix NET::ERR_CERT_AUTHORITY_INVALID for hostname-coverage and stale-certificate causes.

Chrome still ignores the certificate

Chrome may need a full restart:

# Mac
killall "Google Chrome"
open -a "Google Chrome"

If Chrome still shows NET::ERR_CERT_AUTHORITY_INVALID, confirm the certificate covers the exact hostname in the address bar. A certificate for localhost will not automatically cover myproject.test.

Firefox doesn't recognize the CA

Firefox uses its own certificate store. Install it manually:

  1. Preferences > Privacy & Security > Certificates
  2. View Certificates > Authorities > Import
  3. Select rootCA.pem from mkcert -CAROOT

Best practices

Certificate organization

~/certs/
├── localhost/
│   ├── localhost+2.pem
│   └── localhost+2-key.pem
├── myproject.test/
│   ├── myproject.test+1.pem
│   └── myproject.test+1-key.pem
└── README.md

Never commit keys

# .gitignore
*.pem
certs/

Keep the certificate generation command in your README or setup script, but keep the generated key files out of Git.

Project setup script

#!/bin/bash
# setup-certs.sh
mkdir -p certs
cd certs
mkcert localhost 127.0.0.1 ::1 myproject.test "*.myproject.test"
echo "Certificates created in ./certs/"

Alternatives to mkcert

Work but generate constant browser warnings.

Tunnels (ngrok, localtunnel)

Expose your localhost on the Internet with HTTPS. Useful for mobile testing or webhooks.

Caddy

Web server with automatic HTTPS, even locally.

Conclusion

HTTPS locally is no longer optional in 2026. With mkcert, installation takes 2 minutes and saves you hours of frustration with modern APIs. Combine it with .test domains managed via ToggleHosts for a professional development environment.

Frequently Asked Questions

Certain modern APIs (Service Workers, Geolocation, Clipboard, WebRTC) only work over HTTPS. Plus, it avoids differences between dev and production.

mkcert is a tool that creates a local certificate authority and generates trusted SSL certificates for your development domains.

For local development, yes. Never use mkcert in production. The certificates are only valid on your machine.

After installing mkcert, run 'mkcert localhost' to create certificates, then configure your server to use them.

Related Articles