Todos los artículos
HTTPSmkcertlocal developmentlocalhost tunneling

HTTPS en localhost: mkcert vs túnel, comparados con honestidad

Dos herramientas, un problema: tu servidor de desarrollo necesita ser alcanzable por HTTPS. mkcert te da un certificado TLS confiable localmente para que https://localhost:3000 simplemente funcione. Un túnel te da una URL HTTPS pública respaldada por un certificado real de una CA real. No son competidores — resuelven problemas distintos —, pero la gente sigue tratándolos como si lo fueran.

La respuesta corta

  • ¿Necesitas HTTPS solo en tu propia máquina, para tu propio navegador? Usa mkcert.
  • ¿Necesitas que un servicio externo (Stripe, GitHub, Auth0, un teléfono) alcance tu servidor de desarrollo? Usa un túnel.
  • ¿Ambos? Corre ambos. No entran en conflicto.

Ese es el artículo entero en tres viñetas. El resto es solo el porqué.

mkcert: certificados confiables localmente en 30 segundos

mkcert instala una autoridad de certificación local en el almacén de confianza de tu sistema operativo y emite certificados desde ella. Tu navegador ve el certificado como confiable porque la CA lo es. Sin avisos de tu conexión no es privada, sin flags --ignore-certificate-errors, sin armar tus propios certificados autofirmados.

# una vez por máquina
mkcert -install

# una vez por proyecto
mkcert localhost 127.0.0.1

# ahora tienes localhost.pem y localhost-key.pem

Conéctalos a tu servidor de desarrollo (Vite, Next.js, Express, Django runserver_plus, todos soportan args de TLS) y tienes https://localhost:3000 con un certificado real.

El truco: solo tu máquina confía en esa CA. El navegador de tu compañero avisará. Tu teléfono no confiará sin instalar manualmente la raíz de la CA.

Túnel: HTTPS real, URL pública real

Un túnel localhost reenvía tráfico desde una URL HTTPS pública a tu puerto local. El certificado lo emite una CA real (Let's Encrypt o similar) y lo confía cada navegador en cada dispositivo.

npx portpreview 3000

El túnel gestiona la terminación TLS en la pasarela de la nube. Tu servidor local puede quedarse en HTTP plano — la URL pública es HTTPS, y esa es la superficie que toca cada servicio externo.

Lado a lado

NecesidadmkcertTúnel
HTTPS en tu navegador localSí (vía la URL pública)
Pruebas de service worker / cookie segura en tu navegador
Un proveedor externo puede alcanzarteNo
El teléfono en tu mano puede alcanzarteNo (sin instalar la CA)
El proveedor OAuth acepta la URLA veces (Google: sí; muchos: no)
Stripe / GitHub / Twilio pueden hacer webhookNo
Tiempo de configuración30 segundos por máquinaUn comando por sesión
Funciona sin conexiónNo
Sobrevive al modo aviónNo

Donde la gente se equivoca

Intentar usar mkcert para pruebas de webhook

Stripe no puede confiar en la CA local de tu máquina. No importa cuán confiable se vea el certificado en tu navegador — Stripe está en una red distinta. Necesitas un túnel para cualquier tráfico entrante de la internet pública.

Usar un túnel para HTTPS en solitario solo de navegador

Si solo quieres que funcionen los service workers o que se ponga una cookie segura en tu propio navegador, mkcert es más rápido y funciona sin conexión. No quemes una sesión de túnel por lo que resuelve un archivo de certificado.

Elegir una herramienta y forzar por ella el otro caso de uso

Correr ambas está bien. La mayor parte de nuestra configuración usa mkcert para el trabajo diario del lado del navegador y un túnel cuando probamos webhooks o callbacks OAuth. Cohabitan en package.json sin conflicto.

¿Y Caddy o nginx?

Sí, puedes correr Caddy con HTTPS automático delante de tu servidor de desarrollo, y eso también funciona — es esencialmente «mkcert con pasos extra y un proxy inverso». Para la mayoría del desarrollo local, mkcert es más simple. Para enrutamiento más elaborado con varios servicios locales, Caddy se gana su lugar.

Nuestra configuración real

Un repo en el que trabajamos tiene mkcert en el script de desarrollo para HTTPS del lado localhost, y un script npm tunnel aparte que corre portpreview cuando alguien necesita webhooks o pruebas en móvil. La URL del túnel se pasa por variable de entorno para que las redirect URIs de OAuth sean fáciles de intercambiar. Tomó 20 minutos conectarlo y nunca volvimos a pensar en TLS local.

Para configuración de túnel específica de OAuth, mira cómo probar callbacks OAuth en local. Para compartir previews con compañeros o diseñadores, compartir tu servidor de desarrollo local. Únete a la lista de espera de PortPreview para el lado del túnel de esta configuración.

Preguntas frecuentes

¿Debo usar mkcert o un túnel para HTTPS local?
Ambos, para cosas distintas. mkcert le da a tu propio navegador un certificado confiable en localhost y funciona sin conexión. Un túnel te da una URL HTTPS pública que servicios externos y otros dispositivos pueden alcanzar. No entran en conflicto — la mayoría de los equipos usan ambos.
¿Puede mkcert manejar pruebas de webhook desde Stripe o GitHub?
No. Los certificados de mkcert son confiables solo en la máquina que instaló la CA. Los proveedores de webhook externos no pueden alcanzar localhost por más confiable que sea el certificado en tu navegador local. Usa un túnel para cualquier tráfico público entrante.
¿Funciona mkcert para callbacks OAuth en localhost?
Algunos proveedores (Google, ciertos niveles de desarrollo de Auth0) aceptan localhost por HTTP o HTTPS para desarrollo. Muchos no. mkcert te da HTTPS para los que sí; para los estrictos se requiere un túnel con URL HTTPS pública.