Red y exposición¶
Los 5 dominios de abajo son reales y comparten exactamente el mismo camino de red — ninguno tiene un caso especial.
Dominios activos¶
| Dominio | Servicio | Namespace | TLS |
|---|---|---|---|
shop.cruzcloud.net |
Frontend Next.js (storefront) | ecommerce |
Cloudflare (edge) |
commerce.cruzcloud.net |
Medusa Store/Admin API | ecommerce |
Cloudflare (edge) |
media.cruzcloud.net |
MinIO (imágenes de producto) | ecommerce |
Cloudflare (edge) |
gitea.cruzcloud.net |
Gitea | — | Cloudflare (edge) |
docs.cruzcloud.net |
Este portal | docs |
Cloudflare (edge) |
Por qué todos van "proxied" (naranja), ninguno "DNS-only"¶
Un registro DNS-only en Cloudflare expondría directamente la IP real del túnel — pero acá no hay IP pública fija que exponer: el NAS está detrás de NAT residencial. El modo proxied es lo que hace que Cloudflare Tunnel tenga sentido en primer lugar (el tráfico entra por el edge de Cloudflare, nunca directo al origen), así que no hay ningún dominio de este lab para el que DNS-only sea una opción real.
Dónde termina TLS de verdad¶
flowchart LR
User(["Usuario"]) -->|HTTPS| CF["Cloudflare edge<br/>🔒 TLS termina acá"]
CF -->|túnel cifrado, HTTP/2| CFD["cloudflared"]
CFD -->|HTTP plano| NPM["Nginx Proxy Manager"]
NPM -->|HTTP plano| LB["k3d-proxy :90"]
LB -->|HTTP plano| TR["Traefik"]
TR -->|HTTP plano| SVC["Service interno"]
TLS termina en el edge de Cloudflare, no en Traefik ni en NPM. De
ahí hacia adentro (cloudflared → NPM → k3d-proxy → Traefik →
Service) todo el tráfico va en HTTP plano — seguro en este contexto
porque ese tramo entero vive dentro de la red local del NAS, nunca
sale a internet. Ningún componente interno necesita certificado propio
ni gestionar renovación de TLS.
Por qué HTTP/2 y no QUIC en el túnel¶
cloudflared puede usar QUIC (UDP) o HTTP/2 (TCP) para sus conexiones
salientes hacia el edge. Este lab fuerza HTTP/2 explícitamente — no es
el default. Un incidente real de 504 Gateway Timeout intermitente en
todos los subdominios (no solo uno) se rastreó hasta fallos
recurrentes del "control stream" de QUIC sobre la red doméstica del
NAS. Ver ADR 0003
para la decisión completa y el playbook del 504
para el diagnóstico paso a paso.
Patrón de diagnóstico: "interno sano, público roto"¶
Cuando un dominio público falla pero todo dentro del cluster responde
bien (pods Running, probes verdes, kubectl exec con curl al
Service funciona), la causa casi nunca está en Kubernetes — está en la
capa NPM. La forma rápida de confirmarlo es saltarse NPM a propósito:
curl -H "Host: <dominio>" http://192.168.68.61:90/ habla directo con
k3d-proxy/Traefik sin pasar por NPM. Si eso funciona pero el dominio
público no, el problema está específicamente en el forward_host/
forward_port del proxy host en NPM (ej.: un scheme o un path colado
en forward_host, que rompe todo el enrutamiento).
Este patrón se repitió dos veces en este lab con la misma causa raíz
exacta: el incidente de imágenes en media.cruzcloud.net
(playbook completo) y un incidente posterior de commerce.cruzcloud.net
devolviendo 400 por el mismo tipo de forward_host roto (sin playbook
propio todavía). Una lección adicional de ese segundo incidente:
editar el proxy_host a mano en el sqlite de NPM no regenera el
.conf de nginx automáticamente — el cambio tiene que pasar por la
propia UI/API de NPM, o el .conf hay que parchearlo a mano y
recargar nginx.