# Visión general Este lab corre sobre un NAS ZimaOS doméstico, sin IP pública ni presupuesto de nube — cada capa del diagrama de abajo existe por una razón concreta de ese contexto, no por moda arquitectónica. Esta página explica el "por qué" de cada frontera; el "cómo" vive en las páginas enlazadas al final de cada sección. ## Flujo de una petición pública ```mermaid flowchart LR User(["Usuario"]) -->|HTTPS| CF["Cloudflare
(DNS proxied + túnel)"] CF -->|HTTP/2, red host| CFD["cloudflared
(app ZimaOS)"] CFD --> NPM["Nginx Proxy Manager
192.168.68.61:90"] NPM --> LB["k3d-lab-cluster-serverlb
(k3d-proxy, 90→80)"] LB --> TR["Traefik
(ingress del cluster)"] TR -->|Host: shop.cruzcloud.net| FE["frontend-svc
(Next.js)"] TR -->|Host: commerce.cruzcloud.net| MED["medusa-svc
(Medusa API)"] TR -->|Host: media.cruzcloud.net| MIN["minio-svc
(imágenes de producto)"] TR -->|Host: gitea.cruzcloud.net| GIT["Gitea"] TR -->|Host: docs.cruzcloud.net| DOCS["docs-portal-svc
(este sitio)"] subgraph GitOps["Control plane GitOps"] ARGO["Argo CD"] -->|sync| FE ARGO -->|sync| MED ARGO -->|sync| DOCS GIT -.->|watch repos| ARGO end ``` ## Componentes | Capa | Qué es | Dónde vive | |---|---|---| | Cloudflare Tunnel | Expone `*.cruzcloud.net` a internet sin abrir puertos en el NAS | Fuera del cluster, app nativa ZimaOS (`cloudflared`) | | Nginx Proxy Manager | Enruta por dominio hacia el cluster | Fuera del cluster, contenedor `nginxproxymanager` | | k3d | Cluster Kubernetes local (multi-nodo, Docker) | Host ZimaOS | | Traefik | Ingress controller del cluster | Dentro de k3d | | Argo CD | Sincroniza el estado del cluster con Git (patrón App of Apps) | Namespace `argocd` | | Gitea | Origen de verdad de los manifiestos y del código de las apps | Contenedor propio, expuesto vía túnel | ## Por qué cada frontera está donde está **Cloudflare Tunnel, no port-forwarding.** El NAS vive detrás de NAT residencial, sin IP pública fija. En vez de abrir puertos en el router (superficie de ataque directa contra el hogar), `cloudflared` abre una conexión **saliente** hacia Cloudflare y todo el tráfico público viaja hacia adentro por esa misma conexión — el origen nunca expone un puerto escuchando en internet. El transporte de esa conexión se fijó a HTTP/2 en vez del QUIC por defecto tras un incidente real de inestabilidad; ver [ADR 0003](../decisiones/0003-por-que-http2-sobre-quic-tunnel.md). **Nginx Proxy Manager, fuera del cluster.** No todo lo que sirve `*.cruzcloud.net` vive dentro de k3d — Gitea, por ejemplo, corre como contenedor Docker aparte. NPM es el único punto de enrutamiento por dominio que necesita conocer *ambos* mundos (cluster y no-cluster), así que vive fuera de Kubernetes a propósito, no por descuido. **`k3d-lab-cluster-serverlb`, la frontera de entrada al cluster.** Es el load balancer que el propio k3d monta automáticamente para publicar puertos del host hacia los nodos internos — no es un componente que este lab configuró a mano, viene con la topología multi-nodo elegida en [ADR 0001](../decisiones/0001-por-que-k3d.md). **Traefik, enrutamiento por `Host` dentro del cluster.** Una vez el tráfico entra al cluster por un único puerto (90/9443), Traefik es quien decide a qué Service mandarlo según el header `Host` de cada petición — así NPM solo necesita saber "todo `*.cruzcloud.net` va al puerto 90 del cluster", sin tener que aprender un forward_host nuevo cada vez que se agrega un servicio interno. Cuando esta capa falla en silencio (`forward_host`/`forward_port` mal apuntado en NPM), el síntoma es siempre el mismo: "internamente sano, públicamente roto" — ver [Red y exposición](red-y-exposicion.md). **Argo CD, el único escritor del cluster.** Ningún pipeline de CI ni ninguna persona corre `kubectl apply` contra producción — Argo CD es la única pieza con permisos de escritura, y reconstruye automáticamente cualquier diferencia entre Git y el cluster real (`selfHeal: true`). El porqué completo de esa elección está en [ADR 0002](../decisiones/0002-por-que-argocd-vs-manual.md); el paso a paso de un commit real hasta quedar corriendo, en [Flujo GitOps](gitops-flujo.md). **Gitea, autoalojado.** Además de alojar el código, Gitea corre el CI (Gitea Actions) y el registry de imágenes en el mismo lugar — un solo componente autoalojado en vez de depender de la disponibilidad y los límites de un servicio externo gratuito para un lab que ya de por sí no tiene presupuesto de nube. Ver también: [Red y exposición](red-y-exposicion.md) · [Flujo GitOps](gitops-flujo.md) · [Glosario](glosario.md)