# How to Use mkcert Certificates with Node.js Using NODE_EXTRA_CA_CERTS

> Learn to use mkcert certificates with Node.js by setting the NODE_EXTRA_CA_CERTS environment variable. Trust your local development certificates easily.

- Repository: [Filippo Valsorda/mkcert](https://github.com/FiloSottile/mkcert)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Set the `NODE_EXTRA_CA_CERTS` environment variable to the path of mkcert's `rootCA.pem` file to make Node.js trust locally-generated development certificates.**

When developing applications with Node.js, you often need HTTPS for local testing. While **mkcert** (by FiloSottile) creates a local Certificate Authority and installs it into your operating system's trust store, Node.js maintains its own hardcoded list of trusted CAs and ignores the system root store by design. To bridge this gap, you must explicitly point Node.js to mkcert's root certificate using the `NODE_EXTRA_CA_CERTS` environment variable.

## Why Node.js Requires NODE_EXTRA_CA_CERTS for mkcert

Node.js validates TLS connections against a **built-in list of root CAs** bundled with the runtime. Unlike browsers or other applications, Node.js does not read certificates from the operating system's trust store (macOS Keychain, Windows Certificate Store, or Linux NSS/CA bundles).

When you run `mkcert -install`, the tool creates a local CA (generating `rootCA.pem` and `rootCA-key.pem` in the mkcert data directory) and attempts to install it into the system trust store via platform-specific implementations in [`truststore_darwin.go`](https://github.com/FiloSottile/mkcert/blob/main/truststore_darwin.go), [`truststore_windows.go`](https://github.com/FiloSottile/mkcert/blob/main/truststore_windows.go), [`truststore_linux.go`](https://github.com/FiloSottile/mkcert/blob/main/truststore_linux.go), and [`truststore_nss.go`](https://github.com/FiloSottile/mkcert/blob/main/truststore_nss.go). However, Node.js remains unaware of these system-level changes until you explicitly provide the CA file via `NODE_EXTRA_CA_CERTS`.

## Step-by-Step Guide to Configure NODE_EXTRA_CA_CERTS with mkcert

### Install the Local CA with mkcert -install

First, initialize mkcert and install the local CA into your system trust store. This command, implemented in [`main.go`](https://github.com/FiloSottile/mkcert/blob/main/main.go), creates the root certificate authority files.

```bash
mkcert -install

```

This generates `rootCA.pem` (the public certificate) and `rootCA-key.pem` (the private key) in mkcert's data directory. You can locate this directory by running `mkcert -CAROOT`.

### Generate Development Certificates for Your Hosts

Create a certificate for the specific hostnames or IP addresses you need for local development. The certificate generation logic resides in [`cert.go`](https://github.com/FiloSottile/mkcert/blob/main/cert.go).

```bash
mkcert localhost 127.0.0.1 ::1

```

This produces files named `localhost+2.pem` (certificate) and `localhost+2-key.pem` (private key) in your current directory.

### Export NODE_EXTRA_CA_CERTS Environment Variable

Set the `NODE_EXTRA_CA_CERTS` environment variable to the absolute path of the `rootCA.pem` file. This variable instructs Node.js to append the specified CA certificate to its built-in trust store.

```bash
export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"

```

For persistent use across terminal sessions, add this line to your shell profile (`.bashrc`, `.zshrc`, or `.bash_profile`).

### Run Your Node.js Application

Start your Node.js server with the environment variable set. Node.js will now trust certificates signed by your mkcert CA.

```bash
node server.js

```

## Complete Node.js HTTPS Server Example

Here is a practical implementation using the certificates generated above. This example creates a simple HTTPS server in Node.js using the mkcert-generated files.

```javascript
const https = require('https');
const fs = require('fs');
const path = require('path');

// Paths to the certificate and key generated by mkcert
const certPath = path.join(__dirname, 'localhost+2.pem');
const keyPath = path.join(__dirname, 'localhost+2-key.pem');

const serverOptions = {
  cert: fs.readFileSync(certPath),
  key: fs.readFileSync(keyPath)
};

https.createServer(serverOptions, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Successfully serving HTTPS via mkcert certificates\n');
}).listen(8443, () => {
  console.log('HTTPS server running at https://localhost:8443');
});

```

When you run this server with `NODE_EXTRA_CA_CERTS` set, any Node.js client connecting to `https://localhost:8443` will validate the certificate successfully without throwing `UNABLE_TO_VERIFY_LEAF_SIGNATURE` errors.

## Verifying the Certificate Trust

To confirm that Node.js recognizes the mkcert CA, you can test with a simple HTTPS request using `curl` or a Node.js client.

Using curl (without the `-k` insecure flag):

```bash
curl https://localhost:8443

```

If `NODE_EXTRA_CA_CERTS` is properly set in your environment, the connection succeeds. If you encounter `curl: (60) SSL certificate problem`, verify that the environment variable points to the correct `rootCA.pem` file located at `$(mkcert -CAROOT)/rootCA.pem`.

## Summary

- **mkcert** generates a local CA and installs it into the OS trust store via `truststore_*.go` implementations, but Node.js maintains its own CA list.
- **Node.js** requires the `NODE_EXTRA_CA_CERTS` environment variable to trust additional CAs, as it does not read the system root store.
- Set `NODE_EXTRA_CA_CERTS` to `$(mkcert -CAROOT)/rootCA.pem` to enable trust for all Node.js processes in that environment.
- Use the generated certificate files (e.g., `localhost+2.pem` and `localhost+2-key.pem`) in your Node.js HTTPS server configuration.

## Frequently Asked Questions

### What is the default location of mkcert's rootCA.pem?

The default location depends on your operating system. Run `mkcert -CAROOT` to display the exact path. On macOS and Linux, this is typically `~/Library/Application Support/mkcert` or `~/.local/share/mkcert`. On Windows, it resides in `%LOCALAPPDATA%\mkcert`. The file `rootCA.pem` resides in this directory alongside `rootCA-key.pem`.

### Does NODE_EXTRA_CA_CERTS work with Node.js cluster mode?

Yes, `NODE_EXTRA_CA_CERTS` works with Node.js cluster mode, but you must ensure the environment variable is set in the parent process before forking workers. Child processes inherit the environment from the parent, so if the variable is exported in the main process, all cluster workers will also trust the mkcert CA. If you set the variable only in a worker after forking, it will not affect TLS validation in that worker.

### Can I use NODE_EXTRA_CA_CERTS in production environments?

While technically possible, using `NODE_EXTRA_CA_CERTS` with mkcert in production is strongly discouraged. mkcert is explicitly designed for **local development** only. The root CA private key (`rootCA-key.pem`) is stored on your development machine, and mkcert does not implement the security controls, auditing, or certificate transparency required for production use. For production, use certificates from a publicly trusted CA (e.g., Let's Encrypt) or your organization's internal PKI infrastructure.

### Why does Node.js ignore the system certificate store?

Node.js uses a **statically linked** OpenSSL (or BoringSSL in some builds) with a bundled CA certificate file. This design ensures consistent behavior across all platforms and prevents system-wide CA changes from unexpectedly breaking or altering Node.js TLS validation. While this improves reproducibility and security isolation, it means Node.js does not automatically trust certificates added to the macOS Keychain, Windows Certificate Store, or Linux CA bundles. The `NODE_EXTRA_CA_CERTS` environment variable provides the explicit mechanism to extend trust for specific use cases like local development with mkcert.