Juan Elosegui

Use .NET developer certificate with Vite

Saturday, 30 August 2025

Today I was working on a side project (ASP.NET + React with Vite) and I wanted to run the frontend over HTTPS. After a quick search I found the handy plugin vite-plugin-basic-ssl, which made it trivial to enable HTTPS. But I still had a problem: either trust the self-signed cert that plugin generates or provide a certificate my machine already trusts.

Since I’m using .NET and it supports a local developer certificate, I thought: why not reuse that cert for Vite too?

That’s when I dug into how Vite expects HTTPS configuration via server.https. After a bit of fiddling, I landed on a setup that ensures a valid .NET developer cert exists, exports it as a PFX, and feeds it to Vite during vite serve.

Here’s the core of it:

import fs from 'node:fs'
import path from 'node:path'
import { execSync } from 'node:child_process'

const tryExportDotnetDevCert = () => {
  try {
    const certDir = path.resolve(process.cwd(), '.certs');
    const exportPath = path.join(certDir, 'aspnet-devcert.pfx');
    const passphrase = 'vite-devcert';

    if (!fs.existsSync(certDir)) {
      fs.mkdirSync(certDir, { recursive: true });
    }

    // Ensure a valid/trusted dev cert exists. If check fails (expired/missing), recreate it.
    try {
      execSync('dotnet dev-certs https --check', { stdio: 'ignore' });
    } catch {
      try { execSync('dotnet dev-certs https --clean', { stdio: 'ignore' }); } catch {}
      execSync('dotnet dev-certs https --trust', { stdio: 'ignore' });
    }

    execSync(`dotnet dev-certs https --export-path "${exportPath}" --password "${passphrase}"`, { stdio: 'ignore' });

    if (fs.existsSync(exportPath)) {
      return {
        pfx: fs.readFileSync(exportPath),
        passphrase,
      } as const;
    }
  } catch {
    // could not configure dotnet development certificate. 
  }
  return undefined;
};

export default defineConfig(({ command }) => {
  const httpsConfig = command === 'serve' ? tryExportDotnetDevCert() : undefined;

  return {
    server: {
      https: httpsConfig,
    },
  };
});

With that in place:

  • On vite serve, the config checks for a valid .NET dev cert, trusts it if needed, exports it to .certs/aspnet-devcert.pfx, and passes it to Vite via server.https.
  • On vite build, HTTPS isn’t needed, so it skips the export.

Notes I found useful:

  • If you’ve got a stale/expired cert, the code calls dotnet dev-certs https --clean and then --trust to recreate it.
  • You can still use vite-plugin-basic-ssl if you want a self-signed quick start, but the .NET dev cert avoids browser trust prompts on your machine.

References:

comments powered by Disqus