ZyVOP Logo
Content That Connects
SeriesCategoriesTags
ZyVOP Logo
Content That Connects

Empowering developers and creators with cutting-edge insights, comprehensive tutorials, and innovative solutions for the digital future.

Content

  • Tags
  • Write Article

Company

  • About Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

© 2026 ZyVOP. Crafted with care for the developer community.

Made with ❤️ by the ZyVOP team
All systems operational
HomeLocal HTTPS Done Right: Wildcard SSL for Modern Development
👍1

Local HTTPS Done Right: Wildcard SSL for Modern Development

Set Up Trusted Local HTTPS with Wildcard Certificates, mkcert, DNS Routing, and Zero Browser Warnings

#SSL#Local Development#Web Security#mkcert#DevOps#Wildcard Certificates#Traefik
Bhavya Arora
Bhavya Arora

Senior Developer

May 22, 2026
4 min read
25 views
Local HTTPS Done Right: Wildcard SSL for Modern Development

Modern web development demands HTTPS. If you are building an application on http://localhost:3000, you will inevitably hit a wall:

  • OAuth providers (Google, GitHub, Apple) often refuse HTTP redirect URIs.

  • Stripe webhooks require a secure context.

  • Cross-domain cookies (SameSite=None) are strictly blocked by browsers without the Secure flag.

  • Service Workers and modern Web APIs (Geolocation, Clipboard) fail silently.

The historical solution was generating self-signed certificates with openssl. But modern browsers hate self-signed certs. They throw terrifying red "Your connection is not private" screens, forcing you to click through hidden "Proceed anyway" menus.

Today, we are going to fix this the right way. We will become our own Certificate Authority (CA) and generate a Wildcard SSL Certificate so you can develop locally on https://app.mylocal.dev with a perfectly green, trusted padlock.


The Secret Weapon: mkcert

mkcert is an incredibly clever tool. Instead of generating a standalone self-signed certificate, it creates a local Certificate Authority (CA) and injects it into your operating system's and browser's trust stores.

Because your OS explicitly trusts this local CA, any certificate signed by it is treated as entirely valid.

Step 1: Install mkcert

macOS (via Homebrew):

brew install mkcert
# If you use Firefox, it manages its own trust store, so we need nss
brew install nss 

Windows (via Chocolatey):

choco install mkcert

Ubuntu/Debian:

sudo apt install libnss3-tools
brew install mkcert # via Linuxbrew, or download the binary from GitHub

Step 2: Initialize Your Local CA

Run the following command once per machine:

mkcert -install

Your operating system will prompt you for an admin password. You are giving mkcert permission to add a root certificate to your keychain.

Step 3: Generate the Wildcard Certificate

Choose a Top-Level Domain (TLD) for local development. Do not use .dev or .app—Google owns these and strictly enforces HSTS (HTTPS routing) at the DNS level, which can cause annoying conflicts.

The internet standard for local development is .test or .loc. Let's use *.myapp.test.

mkdir -p ~/local-certs && cd ~/local-certs
mkcert "*.myapp.test"

This generates two files:

  1. _wildcard.myapp.test.pem (The Public Certificate)

  2. _wildcard.myapp.test-key.pem (The Private Key)

Step 4: Map Local DNS

We need to tell your computer that api.myapp.test and app.myapp.test should resolve to localhost (127.0.0.1).

Edit your hosts file:

  • Mac/Linux: sudo nano /etc/hosts

  • Windows: Open Notepad as Administrator, then open C:\Windows\System32\drivers\etc\hosts

Add your domains to the bottom:

127.0.0.1   myapp.test
127.0.0.1   app.myapp.test
127.0.0.1   api.myapp.test

Step 5: Implementation

You have the trusted certificates and the DNS mapping. Now you just need to serve them. You can do this at the application level or the proxy level.

Approach A: Using Docker and Nginx (Recommended)

This closely mirrors a production environment. Nginx handles the SSL termination and passes standard HTTP traffic to your Node/Python app.

docker-compose.yml:

version: '3.8'
services:
  web:
    image: node:18
    command: npm run dev
    # Notice we don't expose ports directly

  proxy:
    image: nginx:alpine
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      # Mount the folder containing our certificates
      - ~/local-certs:/etc/nginx/certs:ro

nginx.conf:

events {}
http {
    server {
        listen 443 ssl;
        server_name app.myapp.test api.myapp.test;

        ssl_certificate /etc/nginx/certs/_wildcard.myapp.test.pem;
        ssl_certificate_key /etc/nginx/certs/_wildcard.myapp.test-key.pem;

        location / {
            proxy_pass http://web:3000;
            proxy_set_header Host $host;
        }
    }
}

Approach B: Native Node.js (Next.js / Vite)

If you don't use Docker, you can pass the certificates directly to your dev server.

For Vite, add this to vite.config.ts:

import fs from 'fs';

export default defineConfig({
  server: {
    https: {
      key: fs.readFileSync('/Users/bhavya/local-certs/_wildcard.myapp.test-key.pem'),
      cert: fs.readFileSync('/Users/bhavya/local-certs/_wildcard.myapp.test.pem'),
    },
    host: 'app.myapp.test'
  }
})

Crucial Tip: Node.js Backend-to-Backend Requests

If your Node.js backend tries to fetch data from your own secure local API (e.g., Server-Side Rendering hitting https://api.myapp.test), Node will throw an UNABLE_TO_VERIFY_LEAF_SIGNATURE error.

Why? Because Node.js does not use the operating system's trust store. It uses its own hardcoded list of root authorities.

To tell Node.js to trust your mkcert CA, you must pass an environment variable when starting your Node script:

# Find where mkcert put your root CA
export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"

# Then run your app
npm run dev

Conclusion

Boot up your application and navigate to https://app.myapp.test.

You will be greeted by a flawless, green padlock. No warnings, no "Proceed to unsafe" buttons. Your cookies will adhere to strict security policies, third-party APIs will accept your webhooks, and your local development environment will finally mirror production parity.

Bhavya Arora

Bhavya Arora

Passionate developer sharing knowledge about modern web technologies and best practices.

Comments (0)

Login to post a comment.

Stay Updated

Get the latest articles delivered to your inbox.

We respect your privacy. Unsubscribe anytime.

Related Posts

Docker for Developers: Stop "It Works on My Machine" Forever

Docker eliminates the “works on my machine” problem by packaging your app, dependencies, and runtime into portable containers. This guide covers production-grade Dockerfiles, layer caching, multi-stage builds, Docker Compose, volumes, networking, and practical workflows for real applications.

Read article

The Developer's Guide to Environment Variables and Secrets Management

Environment variables are easy in local development and much harder in production. This guide covers secure configuration management across .env files, CI/CD pipelines, containers, staging, and production — including validation, documentation, secret rotation, and production-grade secrets management.

Read article

NestJS Error Monitoring with Sentry: Production-Grade Setup Guide

Read article

TypeORM is Killing Your Node Process: Handling Large Datasets Without OOM Crashes

Read article

Stateless vs Stateful Systems: The Architecture Decision That Changes Everything

Read article

Popular Tags

#.env.example Node.js#0x profiling#12-factor#AI agents#AI code security#AI coding tools 2026#AI-assisted development#AI-generated vulnerabilities#ALTER TABLE no lock#API Design