Túnel Cloudflare Laravel sin mixed content – 2026
Exponer tu aplicación Laravel local con un túnel Cloudflare Laravel es un golazo para mostrar prototipos, pero apenas lo abrís te encontrás con dos dolores de cabeza: los assets se cargan desde localhost y Livewire emite URLs HTTP que el navegador bloquea por mixed content. La solución, que Nasrul Hazim compartió, pasa por configurar trustProxies y apuntar la base de assets a la URL del túnel.
Un túnel Cloudflare Laravel — usando cloudflared — crea una conexión HTTPS pública que apunta a tu entorno local, permitiendo que cualquiera vea tu app sin desplegarla. El mixed content aparece porque el túnel termina TLS y reenvía HTTP plano a Laravel con el header X-Forwarded-Proto: https. Si Laravel no confía en el proxy, genera recursos con http:// y los navegadores bloquean todo. Con trustProxies(‘*’) y APP_URL apuntando al dominio del túnel, todo carga por HTTPS y los warnings desaparecen.
En resumen
- Los assets sin CSS y Livewire roto son la señal clásica de que Laravel no detecta la conexión como segura detrás del túnel Cloudflare.
- Agregá trustProxies(‘*’) en el middleware para que isSecure() devuelva true y Livewire/Flux generen URLs https://.
- Forzá APP_URL al dominio del túnel antes de compilar assets con Vite o usando el helper del paquete kickoff.
- El comando kickoff:tunnel de cleaniquecoders construye assets, abre el túnel, reescribe la URL y restaura todo al cerrar.
- Cloudflare Tunnels es gratis y permite dominio propio, con menos restricciones que ngrok o Expose en sus planes gratuitos.
Cloudflare es una red de entrega de contenido (CDN) y servicios de seguridad web fundada por Matthew Prince, Lee Holloway y Michelle Zatlyn, que ofrece aceleración de sitios, protección contra ataques DDoS y un túnel para exponer aplicaciones locales de forma segura.
¿Qué pasa con los assets y Livewire cuando expongo mi Laravel local con un túnel HTTPS?
El túnel arranca y le pasás el link a un compañero. Lo primero que ve es HTML pelado, sin una hoja de estilo. El motivo: Vite sirve los JS y CSS desde localhost:5173, una dirección que no existe para el visitante y que encima el navegador bloquea por ser HTTP dentro de una página HTTPS (el famoso “mixed content”). Sobre eso hablamos en la gestión de secretos en Cloudflare Workers.
Livewire y Flux agravan el asunto. Ellos emiten peticiones AJAX usando request()->isSecure(). Si Laravel cree que la conexión es HTTP — porque el túnel le llega en plano —, las URLs quedan http:// y el navegador las rebota. El túnel termina TLS y agrega el header X-Forwarded-Proto: https, pero Laravel lo ignora a menos que le digas que el proxy es de fiar (sí, incluso aunque el candadito verde esté visible).
¿Cómo arreglar el protocolo HTTPS con trustProxies?
La solución más rápida es modificar el middleware TrustProxies para que honre el header de reenvío. En app/Http/Middleware/TrustProxies.php ponés:
protected $proxies = '*';Con esto Laravel acepta que cualquier proxy le pase X-Forwarded-Proto. En desarrollo local es perfecto: tirás el túnel, probás, listo. Para producción la historia cambia. Un comodín deja que cualquier cliente falsifique los headers. Si tu app está hosteada en un VPS, necesitás listar las IPs específicas del balanceador de carga, no un asterisco. Así evitás que alguien meta mano desde afuera. En alternativas de almacenamiento como Cloudflare R2 profundizamos sobre esto.
Apenas hacés ese cambio, isSecure() empieza a devolver true y tanto Livewire como Flux generan las URLs con https://. El mixed content desaparece.
¿Cómo apuntar los assets compilados a la URL del túnel?
El protocolo ya está, pero Vite sigue apuntando a localhost. Necesitás que los helpers asset() y mix() apunten al dominio público. La variable APP_URL del .env controla eso. Opción uno: antes de lanzar el build, cambiás APP_URL por la URL del túnel y corrés npm run build. Opción dos: un script que reescriba la URL base en tiempo de ejecución.
El paquete cleaniquecoders/kickoff, presentado por Hazim, hace exactamente eso con un solo comando: construye los assets apuntando al túnel, levanta cloudflared, y al cerrarlo restaura el .env original. Ideal para equipos que comparten prototipos a diario sin tocar nada a mano.
Pasos para instalar y ejecutar cloudflared con Laravel
Si preferís control directo, la secuencia es:
- Instalá cloudflared: con Homebrew o desde el binario de GitHub.
- Autenticate:
cloudflared tunnel loginy elegí el dominio de Cloudflare. - Creá el túnel:
cloudflared tunnel create laravel-appy anotá el ID. - Configurá el DNS: apuntá un subdominio de tu zona DNS hacia el túnel.
- Ejecutalo:
cloudflared tunnel run --url http://localhost:8000 laravel-app.
Para integrarlo con Artisan, existe el paquete aerni/laravel-cloudflared, que añade comandos como php artisan cloudflared:tunnel y gestiona la autenticación desde el proyecto. Una capa extra de comodidad.
¿Qué es el paquete cleaniquecoders/kickoff y cómo ayuda?
Kickoff es un paquete Laravel que envuelve todo el flujo en un comando: php artisan kickoff:tunnel. Como ya lo cubrimos antes en nuestra comparativa de CI/CD en 2026.
- Ejecuta
npm run buildcon la URL del túnel como base. - Abre el túnel cloudflared.
- Sobrescribe
APP_URLen runtime para los assets. - Al presionar Ctrl+C, restaura el
.envoriginal.
Si laburás en un equipo donde todos necesitan ver las últimas pantallas sin deploy, este paquete ahorra los 15 minutos de configuración manual que repetías cada vez. Lo podés instalar con composer y en segundos tenés un entorno de preview público y sin mixed content.
Errores comunes al exponer Laravel local con túneles HTTPS
- Olvidar trustProxies. Sin eso,
isSecure()nunca será true y los navegadores bloquearán Livewire. Revisá que el middleware esté activo y apuntando a'*'en desarrollo. - Assets quebrados por APP_URL localhost. Si compilaste con
APP_URL=http://localhost, las rutas de Vite quedan fijas. Solución: antes del build, apuntáAPP_URLa la URL completa del túnel o usá el helper de kickoff. - Error 419 por CSRF. El token se emite para un dominio y el navegador llega desde otro. Revisá la configuración de dominio de la sesión en tu aplicación.
- TrustProxies con
'*'en producción. Es un agujero: cualquiera puede enviar headers falsos. En un VPS productivo usá las IPs reales del balanceador, no el comodín.
Alternativas: Cloudflare Tunnels vs ngrok vs Expose
| Característica | Cloudflare Tunnel | ngrok (plan gratis) | Expose (plan gratis) |
|---|---|---|---|
| Dominio propio | Sí, gratis | No, solo subdominios aleatorios | No, solo URLs aleatorias |
| Ancho de banda | No especificado | Limitado | No especificado |
| Persistencia de URL | Sí (mientras el túnel corra) | Cambia cada reinicio | Cambia cada reinicio |
| HTTPS automático | Sí | Sí | Sí |
| Integración con Artisan | vía aerni/laravel-cloudflared | Comando externo | Comando externo |

Para compartir prototipos de Laravel, Cloudflare Tunnels le saca ventaja a los otros dos: dominio fijo y todo bajo tu cuenta de Cloudflare. El plan gratuito de ngrok te impone límites de solicitudes. Si ya tenés tu zona DNS en Cloudflare, la elección es obvia.
Preguntas Frecuentes
¿Cómo evitar el mixed content en Livewire con Cloudflare Tunnel?
Configurá trustProxies('*') en el middleware de Laravel para que Livewire detecte la conexión HTTPS y emita URLs seguras. Además, asegurate de que los assets compilados apunten a la URL pública del túnel cambiando APP_URL. Lo explicamos a fondo en la elección entre Jenkins y GitHub Actions.
¿Qué es cloudflared y cómo se instala?
Cloudflared es el cliente oficial de Cloudflare para crear túneles. Se instala con Homebrew en macOS, o descargando el binario desde GitHub. Luego te autenticás con cloudflared tunnel login.
¿Puedo usar un dominio propio con el túnel gratis?
Sí. Después de crear el túnel, configurás un subdominio de tu zona DNS para que apunte al túnel y el tráfico sale por tu dominio personalizado con HTTPS, sin costo adicional.
¿El paquete cleaniquecoders/kickoff es seguro para producción?
No. Está pensado para desarrollo local y previews. Rewrite de APP_URL sobre la marcha y trustProxies('*') son aceptables en tu máquina, pero en producción necesitás IPs fijas y variables de entorno controladas.
¿Cómo solucionar el error 419 al usar un túnel HTTPS?
El error CSRF (419) suele aparecer cuando el dominio de la sesión no coincide con la URL pública. Revisá la configuración de dominio de sesión de tu aplicación y limpiá la caché de configuración.
Conclusión
Compartir una app Laravel con Cloudflare Tunnel dejó de ser una pesadilla de assets rotos y paneles blancos. Con trustProxies bien configurado y la URL base apuntada al túnel, el mixed content desaparece y tanto Livewire como Vite funcionan como si estuviesen en producción. El paquete kickoff de cleaniquecoders le ahorra a los equipos los pasos manuales y transforma el preview local en un trámite de un comando. Si todavía dependés de ngrok y te cansás de las URLs aleatorias o los límites de conexión, pasarte a Cloudflare Tunnels es el próximo movimiento lógico.
Fuentes
- Share Your Local Laravel App on a Public URL Without Mixed-Content Hell – Nasrul Hazim (Dev.to)
- GitHub – aerni/laravel-cloudflared: Artisan integration for Cloudflare Tunnels
- How to Share Your Local Laravel Site Securely Using Cloudflare Tunnels – Sandro Jhuliano Cagara (Medium)
- Create a Free Public Tunnel to Your Laravel App with Cloudflared, Ngrok or Expose Alternative – Geert Jans (Medium)






![[FREE] I built a WordPress plugin for private team/client documents - ilustracion](https://donweb.news/wp-content/uploads/2026/04/plugin-wordpress-documentos-privados-hero-768x429.jpg)