Introducción
Este proyecto demuestra cómo ejecutar un modelo de lenguaje (LLM) de forma local, exponerlo de forma segura a través de Internet mediante Cloudflare Tunnel, e interactuar con él mediante una aplicación web con streaming en tiempo real. Todo corriendo en hardware propio, sin depender de APIs de terceros.
El Problema
Las APIs de IA como OpenAI o Gemini dependen de servicios externos, implican costos por token y comparten datos con terceros. Para un SaaS como MyPetCare, se buscaba:
- Sin costo por uso (tokens ilimitados)
- Datos sensibles (expedientes clínicos) nunca salen del servidor
- Sin dependencia de APIs externas (disponibilidad 24/7)
- Acceso desde cualquier lugar vía web
Stack Tecnológico
Ollama 0.33.3
qwen2.5-coder:1.5b
Cloudflare Tunnel
Tailwind CSS
Fetch API + TextDecoder
systemd (Linux)
Modelo Local con Ollama
Ollama permite ejecutar modelos de lenguaje de forma local con un solo comando. Se instaló el modelo qwen2.5-coder:1.5b (1.5B parámetros, cuantización Q4_K_M) que ofrece un balance ideal entre calidad de respuesta y consumo de recursos:
# Instalación y ejecución
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5-coder:1.5b
ollama serve
Exposición vía Cloudflare Tunnel
Para acceder al modelo desde Internet sin abrir puertos en el router, se configuró un Cloudflare Tunnel dedicado. Este túnel crea una conexión segura bidireccional entre el servidor local y el edge de Cloudflare:
Servidor Local (192.168.1.80:11434)
↕ (conexión saliente, sin puertos abiertos)
Cloudflare Edge
↕ (HTTPS/TLS)
Usuario final → https://ollama.y3n.store
Se creó un servicio systemd dedicado (cloudflared-ollama.service) que depende de ollama.service, garantizando que ambos arranquen automáticamente con el sistema.
Problemas Resueltos
403 Forbidden desde Cloudflare
Ollama rechazaba conexiones externas por CORS. Solución: configurar OLLAMA_ORIGINS=* en el servicio systemd.
Conflicto de túneles Cloudflare
Dos túneles competían por el mismo dominio. Solución: crear túnel dedicado e0d5f023 con su propio DNS y servicio systemd separado.
DNS CNAME no propagado
El registro CNAME apuntaba a un túnel eliminado. Solución: actualizar el target a e0d5f023...cfargotunnel.com y verificar con dig.
Interfaz Web — Chat AI
Se desarrolló una interfaz de chat completa con las siguientes características:
- Streaming en tiempo real — respuestas token por token con TextDecoder
- Detección automática del modelo — consulta
/api/tags al cargar
- Indicador de estado — puntos animados mientras el modelo "piensa"
- Formato de código — bloques syntax-highlighted para respuestas técnicas
- Enter para enviar, Shift+Enter para nueva línea
- Auto-resize del textarea según contenido
- Modo oscuro con colores consistentes y3n.store
Abrir Chat AI
Arquitectura
┌─────────────────────────────────────────────┐
│ Navegador del usuario │
│ https://y3n.store/chat-ai/ │
└──────────────────┬──────────────────────────┘
│ HTTPS
┌──────────────────▼──────────────────────────┐
│ Cloudflare Edge (CDN + TLS) │
│ ollama.y3n.store → CNAME al tunnel │
└──────────────────┬──────────────────────────┘
│ QUIC/HTTP2
┌──────────────────▼──────────────────────────┐
│ cloudflared (Tunnel e0d5f023) │
│ Servicio: cloudflared-ollama.service │
└──────────────────┬──────────────────────────┘
│ HTTP localhost:11434
┌──────────────────▼──────────────────────────┐
│ Ollama (qwen2.5-coder:1.5b) │
│ Servicio: ollama.service │
│ Puerto: 11434 (solo localhost) │
└─────────────────────────────────────────────┘
Conclusión
Este proyecto demuestra que es posible ejecutar modelos de IA de forma completamente local y privada, exponerlos de forma segura a través de Internet, e interactuar con ellos mediante interfaces web modernas. El modelo qwen2.5-coder:1.5b ofrece respuestas útiles para tareas de código y texto, ejecutándose en una PC normal sin GPU dedicada, con costo operativo cero en tokens.