# vite-plugin-mkcert: local certificates for the Vite dev server

> vite-plugin-mkcert uses mkcert to install a local certificate authority and hand Vite a trusted certificate, so the dev server runs over HTTPS without the browser warning on every reload. The plugin's real reason to exist is HTTP/2, because the plain HTTP dev server caps the number of concurrent requests, and the options cover everything from a local mkcert binary to a corporate proxy.

**liuweiGL/vite-plugin-mkcert** — Provide certificates for vite's https dev service.

- Repository: https://github.com/liuweiGL/vite-plugin-mkcert
- Website: https://www.npmjs.com/package/vite-plugin-mkcert
- Stars: 771 · Forks: 47
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/liuweigl-vite-plugin-mkcert

## A trusted certificate for the dev server

The plugin provides certificates for the Vite https development service, and its principle section states the mechanism in one sentence: it uses mkcert to install the local CA certificate and generate the certificate for the server.https configuration.

mkcert is the well known tool for this, and the plugin is a thin, well parameterised wrapper around it. What that means in practice is that the security properties are mkcert's, not the plugin's, and the plugin's job is to find or fetch the binary, run it, and give Vite the key and certificate paths it expects.

The requirements are Node.js 22.19.0 or newer. The installation is a development dependency.

```bash
yarn add vite-plugin-mkcert -D
```

And the configuration is three lines in the Vite config file.

```ts
import {defineConfig} from 'vite'
import mkcert from 'vite-plugin-mkcert'

// https://vitejs.dev/config/
export default defineConfig({
  server: {
    https: true
  }, // Not needed for Vite 5+ (simply omit this option)
  plugins: [mkcert()]
})
```

The comment on the https option is worth noting. It is not needed for Vite 5 and later, because the plugin itself turns on HTTPS as part of what it does, so the option can simply be omitted there. On older Vite you still set it, and the plugin fills in the certificate.

The package is published as vite-plugin-mkcert, version 2.1.0 at the time of writing, MIT licensed, with the last push on 2026-07-01. The recent tags are v2.1.0 from 2026-06-03, v2.0.0 from 2026-04-09, and v1.17.12 from the same day, so the 1.x line was long lived and the 2.x line is new.

## HTTP/2 is the actual reason to care

The section on when to use the plugin lists two reasons, and the first one is the technical motivation while the second is, in the author's words, obsessive-compulsive disorder and the hope that the browser will not show annoying https certificate errors.

The first reason is the one to take seriously. When you want to use HTTP/2 to solve the concurrency limit of the Vite http dev server requests, you find that the browser cache is invalid, with a link to the Vite issue about it.

The mechanics are worth spelling out. The HTTP/1.1 dev server serves many separate module requests, and browsers cap the number of concurrent connections per origin. When a project has a few hundred modules, the requests queue, and the dev server can appear to hang on a cold load. HTTP/2 multiplexes many streams over one connection, which removes that cap, and that requires HTTPS in the browser, because HTTP/2 in the browser is only available over a secure origin. localhost counts as a secure origin, which is why a self signed certificate is enough for it and why the plugin exists at all.

The certificate error part is the other half. A Vite dev server over plain HTTPS with a self signed certificate produces a browser warning that has to be clicked through on every origin, and while the browser remembers that choice per origin, the first run of every new origin is a broken-looking page.

The plugin fixes both at once, because mkcert produces a certificate that the browser already trusts, since the authority that signed it is in the system trust store. That is why the plugin has to install a certificate authority at all, and why the CA removal step later in the README matters as much as the setup.

## The options that decide whether it works on your network

The parameter list is where this plugin earns its keep, because mkcert has to be downloaded and that is the step that fails behind a firewall.

The hosts option sets the custom hosts, and its default value is localhost plus the local IP addresses, which is the right default for a developer machine serving a phone on the same network.

The force option controls whether to force generation, and the autoUpgrade option controls whether to automatically upgrade mkcert itself.

The source option is the one for networks outside the usual ones. You can specify the download source of mkcert, and domestic users can set it to coding to download from the coding.net mirror, or provide a custom source by implementing the base source type whose file is in the plugin directory.

The mkcertPath option is the escape hatch for a restricted network: you can specify a local mkcert file instead of downloading it from the network.

The proxy option is the proxy URL used when downloading the mkcert binary, with the example of a local proxy on port 7890. If you do not provide it, the plugin falls back to the environment variables, and the four it names are HTTPS_PROXY, https_proxy, HTTP_PROXY, and http_proxy. That fallback is worth noting because the environment variable conventions are inconsistent in case between the secure and insecure variants, and a plugin that checks all four is one that has been through a corporate proxy.

The savePath option sets the location to save the files, which are the downloaded mkcert program and the generated CA file, the private key, and the certificate file. Its default value is a plugin data directory whose constant lives in the plugin source. The keyFileName and certFileName options set the names of the private key and the certificate file that mkcert generates.

For debugging, the plugin prints diagnostics when the DEBUG environment variable is set to the value vite:plugin:mkcert, which is the convention the debug package uses, and the plugin depends on that package directly.

## Getting the certificate onto a phone

The mobile section is the part that will take you the longest, and it is worth reading before you start, because a certificate that is trusted on your laptop is not trusted on a phone.

For the certificates to be trusted on mobile devices, you have to install the root CA yourself, and it is the rootCA.pem file in the folder printed by the mkcert command that shows the CA root.

On iOS there are three ways to get the file onto the device: AirDrop it, email the CA to yourself, or serve it from an HTTP server. Then you open it, install the profile in the settings under Profile Downloaded, and then enable full trust in it, which is a separate step in iOS and the one most people miss. Installing a profile and trusting it are two different actions.

For Android the sequence is to install the CA and then enable user roots in the development build of the app, with a link to a StackOverflow answer that describes the process.

Both of those steps put a signing authority on a device, which is why the friendly reminder at the end of the README exists. The reminder is to uninstall the CA certificate, and the command for it is the mkcert uninstall flag. The CA is a machine wide trust decision, and a developer machine that keeps a local authority installed after the project that needed it is finished is a machine with an unnecessary root of trust on it.

The last piece of the mobile story is the hosts. The default set of hosts is the local host and the local IP addresses, and a phone on the same wifi network reaches the machine by one of those addresses, so the certificate covers it. The screenshots in the README show the same effect for localhost, for the loopback address, and for a local IP, which is the three-way check you want to make before you debug anything else.

## The package metadata, and the fact that the plugin is mostly plumbing

The package manifest is short, and it tells you what the plugin is and is not.

The dependencies are three: debug, which is the logging library behind the DEBUG variable, supports-color, and undici, the fetch implementation used to download the mkcert binary. There is no certificate library and no TLS implementation in the dependency tree, which confirms that the plugin does the downloading and the running and lets mkcert own the cryptography.

The distribution is a TypeScript source in the plugin directory plus a built dist directory, with a CommonJS build, an ES module build, and type declarations. The published files are the plugin directory and the dist directory, and the exports map exposes the package root for both import and require, plus the package.json for tools that read it.

The publishing is set up with npm provenance enabled, which means the published tarball carries a signature tying it to the source commit, and the release process is semantic-release, with a changelog generator and a git plugin in the development dependencies. The lint setup is Biome for linting and formatting and tsc for the type check, and the test script is not a unit test at all: it is a build followed by a playground run, which starts Vite against a playground configuration. The playground directory is the manual test harness, and the playground script clears the .mkcert directory first so that each run regenerates the certificate from scratch.

The package also declares itself compatible with Vite 3 and later through the extended package metadata, which is the registry schema for Vite plugins, and the README carries a compatibility badge generated from the same registry data.

## An authority on your machine, and the alternative to it

The acknowledgements name mkcert and another project called https-localhost, which is the same problem solved with a different certificate generation approach, and the difference in approach is the interesting comparison. That project generates certificates without installing a local authority, which is cleaner in some ways and less capable in others, and this plugin chose the mkcert route, with a real CA and a real trust store, because that is what browsers already trust.

The cost of the mkcert route is the authority itself. A local CA in the system trust store is a machine wide trust decision, and it is the reason the plugin ships a removal command rather than leaving it to you to find. The alternative, and the project the README thanks, generates certificates without installing an authority at all, and that is a genuinely different approach to the same problem.

The two designs trade off in opposite directions. An authority based scheme produces certificates that every browser on the machine trusts immediately, with no per-browser install step, which is why it is the one that works on a phone after a single profile install. A scheme without an authority produces certificates that the browser still has to be told to trust, and each browser and each device needs its own step, but nothing machine wide is changed, and there is no root to forget to remove.

Which one you want depends on whether the machine is yours alone. On a developer laptop that is dedicated to one project, an authority that you install and remove with the project is a reasonable trade for a dev server that behaves like production. On a shared machine, a build agent, or anything managed by someone else, a root certificate is a change you should not be making quietly, and the no-authority route is the correct one to insist on.

## Conclusion

vite-plugin-mkcert fits a team that has moved their Vite dev server to HTTPS, either because they want HTTP/2 to escape the browser's per origin connection limit or because they want the browser to stop showing a certificate warning on every reload. It does not suit a machine where you are not allowed to install a root certificate, and it does not suit a shared build agent where a local authority on the machine is unwelcome. Verify first that the mkcert binary can be obtained on your network, using the source, mkcertPath, or proxy options, that the hosts you serve are covered by the default set of the local host and the local addresses or that you set them explicitly, and that you know how to remove the authority again with mkcert -uninstall when you are done.

## FAQ

### What does vite-plugin-mkcert do?

It uses mkcert to install a local certificate authority and generate a certificate for the Vite server.https configuration, so the dev server runs over HTTPS with a certificate the browser already trusts. It installs the mkcert binary, runs it, and passes the key and certificate paths to Vite.

### Why would I use HTTPS in a Vite dev server?

The plugin's stated reason is to use HTTP/2 to solve the concurrency limit of the Vite http dev server, since the browser cache becomes invalid under the request limit. HTTP/2 in the browser needs a secure origin, which is what the local certificate provides.

### How do I install vite-plugin-mkcert?

With yarn add vite-plugin-mkcert -D, then add the plugin to the Vite config with plugins: [mkcert()]. Node.js 22.19.0 or newer is required, and on Vite 5 and later the server https option can be omitted because the plugin enables it.

### How do I use vite-plugin-mkcert behind a corporate proxy?

Set the proxy option to the proxy URL used when downloading the mkcert binary, and if you do not provide it the plugin falls back to the HTTPS_PROXY, https_proxy, HTTP_PROXY, and http_proxy environment variables. You can also point the mkcertPath option at a local mkcert file and skip the download entirely.

### How do I trust the certificate on a phone, and how do I remove it?

For mobile devices you install the root CA, which is the rootCA.pem file in the folder printed by the mkcert CA root command. On iOS you then install the profile and separately enable full trust, and on Android you enable user roots in the development build. To remove the authority afterwards, run mkcert with the uninstall flag.

## Sources

- [License: MIT](https://github.com/liuweiGL/vite-plugin-mkcert/blob/main/LICENSE)
- [liuweiGL/vite-plugin-mkcert on GitHub](https://github.com/liuweiGL/vite-plugin-mkcert)
- [Project website](https://www.npmjs.com/package/vite-plugin-mkcert)
- [README](https://github.com/liuweiGL/vite-plugin-mkcert/blob/main/README.md)
- [Releases](https://github.com/liuweiGL/vite-plugin-mkcert/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/liuweigl-vite-plugin-mkcert
