Tres incidentes resueltos en la sesión del 2026-08-12/13: 504 intermitente por QUIC inestable en cloudflared, precios null por falta de region_id en el Store API de Medusa v2 (se descarta la hipótesis inicial de regiones COP duplicadas con evidencia directa en Postgres), e imágenes en blanco por un proxy host mal configurado en Nginx Proxy Manager para media.cruzcloud.net. Se agregan también dos notas de referencia en known-issues.md: la topología Cloudflare Tunnel -> NPM -> k3d, y el requisito de region_id explícito en StoreGetProductsParams.
4.7 KiB
Incidente: imágenes de producto en blanco en el storefront (proxy host de media.cruzcloud.net mal configurado en NPM) (2026-08)
Ventana del incidente: 2026-08-13, resuelto el mismo día
Servicio afectado: media.cruzcloud.net (Nginx Proxy Manager → MinIO, minio-svc en namespace ecommerce)
Impacto: las imágenes subidas a productos desde el Admin de Medusa no se visualizaban en el detalle de producto del storefront (shop.cruzcloud.net) — el resto del producto (título, precio, subtítulo, botón añadir al carrito) se renderizaba bien.
Síntoma
Al agregar imágenes a un producto desde el Admin de Medusa (sección Media), estas se veían correctamente cargadas en el Admin, pero en la página de detalle de producto del frontend los thumbnails aparecían vacíos/en blanco.
Diagnóstico
- Storage: confirmado que Medusa usa el provider
@medusajs/medusa/file-s3apuntando a MinIO interno (S3_ENDPOINT=http://minio-svc:9000, bucketari-products), con URLs públicas construidas sobreS3_FILE_URL=https://media.cruzcloud.net/ari-products(env en configmapcommerce-config, namespaceecommerce). - API: el producto traía URLs absolutas válidas, ej.
https://media.cruzcloud.net/ari-products/<archivo>.jpg. - Prueba directa de la URL:
- Contra el ingress interno del cluster (bypaseando el proxy externo,
Host: media.cruzcloud.netdirecto a la IP delk3d-proxy) →200 OK, MinIO sirve el JPEG correctamente. - Contra
https://media.cruzcloud.net/...(la ruta real que usa el navegador del cliente, vía Cloudflare) →500 Internal Server Error,Server: openresty.
- Contra el ingress interno del cluster (bypaseando el proxy externo,
Ese contraste (funciona interno, falla público, con Server: openresty — el motor de Nginx Proxy Manager) aisló el problema al proxy externo, no a Medusa/MinIO/frontend.
Causa raíz
En Nginx Proxy Manager (/DATA/AppData/nginxproxymanager/, contenedor nginxproxymanager), el proxy host de media.cruzcloud.net (id=13 en la tabla proxy_host de database.sqlite) estaba mal configurado:
forward_host = "http://192.168.68.61/" -- esquema y barra final metidos dentro del campo (formato inválido)
forward_port = 5005 -- puerto donde no escucha ningún proceso en el host
Los proxy hosts que sí funcionan (shop.cruzcloud.net id 23, commerce.cruzcloud.net id 28) apuntan correctamente a:
forward_host = "192.168.68.61"
forward_port = 90 -- puerto publicado por k3d-lab-cluster-serverlb hacia Traefik
Se confirmó con ss/docker ps en el host que nada escuchaba en el puerto 5005 — este proxy host nunca estuvo apuntando correctamente al cluster, muy probablemente un typo desde que se creó.
Fix aplicado
- Backups previos:
database.sqlite.bak-pre-media-fixy13.conf.bak-pre-media-fix. - Corrección directa en la base SQLite de NPM:
UPDATE proxy_host SET forward_host='192.168.68.61', forward_port=90 WHERE id=13; - NPM regeneró automáticamente
nginx/proxy_host/13.confcon los valores correctos (la app Node de NPM detecta el cambio en la base y reescribe el.conf; no hace falta editarlo a mano). - Recarga de nginx dentro del contenedor:
docker exec nginxproxymanager nginx -t docker exec nginxproxymanager nginx -s reload
Adicionalmente, se seteó el campo thumbnail del producto de prueba desde el Admin (estaba en null) — Medusa no lo autocompleta a partir del array images, y el frontend lo usa como imagen hero en listados/tarjetas de catálogo.
Validación
Confirmado visualmente en shop.cruzcloud.net/product/cybertron-sentinel-figura-de-coleccion-test-revalidate que tanto la galería del detalle como el thumbnail en listados/tarjetas se renderizan correctamente. También se validó que ediciones de descripción/título/precio desde el Admin se reflejan automáticamente en el storefront sin necesidad de restart ni intervención manual, vía el subscriber revalidate-storefront.ts (workloads/commerce-backend/src/subscribers/) que procesa el evento product.updated de Medusa.
Lecciones aprendidas
Aislar interno vs. público antes de sospechar de la app. Medusa, MinIO y el frontend estaban sanos todo el tiempo — la falla estaba en una capa de infraestructura fuera de los repos de GitOps (Nginx Proxy Manager, gestionado por fuera de apps-registry/platform-infra, sin versionar). Comparar la misma petición por la ruta interna del cluster contra la ruta pública real fue lo que aisló la causa en minutos, sin necesidad de tocar Medusa ni el frontend.
Ver docs/known-issues.md para la topología completa Cloudflare Tunnel → Nginx Proxy Manager → k3d y el patrón a seguir si otro subdominio (*.cruzcloud.net) presenta el mismo síntoma (500/Server: openresty público pero sano internamente).