DevOps/ServerStack Journal

Cómo armamos nuestro stack de monitoreo: Prometheus, Loki, Grafana y GlitchTip self-hosted

Hace meses operamos un stack de monitoreo completo en un VPS de Contabo: métricas con Prometheus, logs con Loki, dashboards y alertas con Grafana, errores de aplicación con GlitchTip. Cero SaaS de pago. Cero datos saliendo. En este post te contamos qué corre, por qué cada servicio existe, qué fallamos en el camino y cuándo conviene self-hosted vs Datadog y similares.

Llevamos meses corriendo un stack de monitoreo completo en producción sobre nuestro VPS de Contabo. Sirve a varios productos a la vez (saas-auth, saas-billing, saas-notification, FlowOrdrV3, OrdenaAhora, ServerStack Solutions) y nos dio en su día la decisión más rentable que tomamos en infra: pasar de "se prendió fuego, alguien me avisó tarde" a "hay un panel que me dice qué se está raro antes de que se rompa".

Este post cuenta qué corre, por qué cada cosa existe, qué arreglamos en el camino, y cuándo conviene este enfoque vs un Datadog o New Relic.

Las tres capas de observabilidad (porque "monitoreo" no es una sola cosa)

Antes de nombrar herramientas, conviene separar conceptualmente lo que se monitorea:

  1. Métricas — números a lo largo del tiempo. CPU al 80%, RAM al 60%, requests por segundo, latencia p95, % de error. Son baratas de almacenar y muy útiles para alertas.
  2. Logs — texto. Lo que tu app y tu sistema escriben. Caros de almacenar, muy útiles para debuggear cuando algo se rompe.
  3. Errores de aplicación — excepciones, stack traces, contexto del usuario. Es un caso especial de logs pero merece tratamiento aparte porque tú quieres agruparlos por "este es el mismo error que ya viste".

A estas tres capas a veces se suma una cuarta: tracing distribuido (seguir una request entre microservicios). Para nuestra escala y la de la mayoría de PyME, no vale la pena todavía. La regla: empieza con métricas + logs + errores. Tracing cuando empieces a tener problemas que solo se entienden mirando entre servicios.

El stack que corremos

Cada servicio tiene una razón para existir. Es importante porque la pregunta "¿no es overkill?" es legítima — y la respuesta es "sí lo sería si tuvieras un solo servicio, no si tienes 10".

ServicioCapaPara qué sirve
PrometheusMétricasBase de datos de series de tiempo. Los servicios exponen endpoints /metrics que Prometheus scrappea cada 15-30s.
Node ExporterMétricasExpone métricas del sistema operativo: CPU, RAM, disco, red. Una pieza por host.
cAdvisorMétricasExpone métricas por contenedor Docker: cuánto consume cada uno.
LokiLogsBase de datos de logs (de Grafana Labs). Indexa por etiquetas, no por contenido — más barato que Elasticsearch.
PromtailLogsRecolector. Lee logs de los containers Docker y los manda a Loki.
GrafanaVisualizaciónDashboards, alertas, exploración. Habla con Prometheus, Loki y otras fuentes.
GlitchTipErroresSentry self-hosted (compatible con SDK Sentry). Recibe excepciones de aplicaciones .NET, Next.js, etc.
PortainerOperaciónUI para gestionar containers Docker. No es monitoreo en sentido estricto pero conecta.
GlancesOperaciónMonitor del sistema en tiempo real, vista CLI/web. Útil para diagnóstico interactivo.

Todos en Docker. Todos en 127.0.0.1 en sus puertos host (3000, 9090, 3100, etc.). El acceso público pasa por Nginx Proxy Manager con SSL — los puertos directos siguen cerrados a internet, alineado con el patrón que escribimos antes en Cloudflare Tunnel: cero puertos abiertos.

Por qué cada uno (sin marketing)

Prometheus, no InfluxDB ni TimescaleDB

Prometheus es el estándar de facto para métricas en infra moderna. Tres razones que pesaron:

  • Pull-based, no push: tu servicio expone /metrics, Prometheus va a buscarlo. Esto evita configurar credenciales en cada servicio para que escriba a un destino central.
  • Lenguaje de queries (PromQL) muy expresivo. rate(http_requests_total{status=~"5.."}[5m]) te da los 5xx por segundo en los últimos 5 minutos.
  • Ecosistema enorme: hay un exporter para casi cualquier cosa (Postgres, Redis, RabbitMQ, Nginx, etc.).

InfluxDB es más conocido por usuarios de Grafana viejos pero la tendencia clara es Prometheus. TimescaleDB es excelente para series de tiempo en Postgres pero te obliga a montar la infra de queries tú.

Loki, no Elasticsearch ni CloudWatch

Si nunca usaste Elasticsearch para logs, te lo vendieron como "el rey de los logs". Es potente. También es brutal de operar: nodos JVM con uso de RAM grande, indexación cara, disco que crece rápido. Para una PyME con un VPS, es overkill.

Loki es liviano y barato. Indexa solo etiquetas (servicio, container, level), no el contenido. Buscar logs por texto requiere escanear, no es tan rápido como Elastic — pero para volúmenes de PyME, es perfecto. La integración con Grafana es nativa.

CloudWatch (AWS) y servicios similares funcionan bien si ya estás 100% en cloud. Para infra mixta o on-prem, complicado.

GlitchTip, no Sentry SaaS

Sentry es el rey indiscutido del error tracking. Su SaaS arranca desde gratis pero crece rápido (~25 USD/mes por 50k events) y lo más importante: tus stack traces, payloads y contexto van a sus servidores. Para datos sensibles de clientes (LATAM con leyes locales de protección de datos), es un compromiso.

GlitchTip es API-compatible con Sentry (los SDKs de Sentry funcionan tal cual apuntando a tu GlitchTip). Es Django + Postgres. Lo levantas en Docker en 10 minutos. Tus errores se quedan en tu servidor.

Lo que no tiene: features avanzados de Sentry (Distributed Tracing, Profiling, Replay). Para nuestro uso, no son críticos.

Grafana — sin alternativa real

Grafana es el unificador. Conecta a todas las fuentes (Prometheus, Loki, Postgres, MySQL, lo que sea), pinta dashboards, manda alertas. La gran ventaja: cuando contratas a un dev con experiencia, ya sabe Grafana. No hay vendor lock-in real.

Lo que monitoreamos en concreto

Cinco dashboards que están vivos hoy en producción:

  1. Server Monitoring — el host: CPU, RAM, disco, red, uptime, carga.
  2. Docker Monitoring — por contenedor: CPU, RAM, red I/O. Útil para detectar cuál container está chupando recursos.
  3. HTTP Errors Monitoring — 4xx y 5xx en Nginx Proxy Manager. Los picos son la primera señal de algo raro.
  4. Fail2ban Monitoring — IPs baneadas, actividad de jails. Útil para ver intentos de brute force.
  5. Métricas de negocio — propias por producto (request rate, latency p95, error rate).

Y 15 uptime monitors HTTP (9 dominios públicos + 6 endpoints internos). Si alguno responde 502 dos veces seguidas, manda email vía SES.

Lo que nos costó aprender (y tú te ahorras)

1. SMTP de Grafana es trampa

Por defecto, Grafana no manda alertas por email. Hay que configurar SMTP en el container con variables de entorno. Si usas SES (como nosotros), las credenciales SMTP no son las mismas que las API keys. Hay que ir al panel de SES → SMTP credentials y generar específicamente esas.

Lo descubrimos cuando Grafana tenía 11 reglas de alerta provisionadas y ninguna llegaba. Las alertas decían "estado: alerting" en la UI pero no salían correos. Día 1: confusión. Día 2: revisar logs del container, encontrar errores SMTP. Día 3: entender que SES tiene credenciales SMTP separadas. Lección: probar el envío de email antes de configurar 11 reglas.

2. Promtail consume RAM si no le pones límites

Por defecto, Promtail puede crecer en uso de memoria conforme procesa más logs. En un VPS modesto, en un mes nos comió varios GB hasta que lo limitamos en docker-compose con mem_limit. Si vas a montar este stack, ponele límites a todos los containers desde el día uno.

3. Las redes Docker hay que conectarlas explícito

Prometheus corre en su propia red Docker. Tus servicios que quieres monitorear (microservicios .NET, FlowOrdr, etc.) corren en sus propias redes. Para que Prometheus pueda ver /metrics de cada uno, hay que conectar los containers a las redes correspondientes:

docker network connect saas_network prometheus
docker network connect flowordrv3_network prometheus

Si te olvidas, los targets aparecen "DOWN" en el panel y no entiendes por qué — el endpoint funciona desde el host pero no desde Prometheus. Cuando levantas un servicio nuevo, el primer paso después del compose es conectar Prometheus a su red.

4. Retention default de Prometheus es corta

Prometheus por default guarda 15 días de métricas. Para una PyME con poco disco, está OK. Para análisis de tendencias mensuales (¿el tráfico creció vs el mes pasado?), corto. Si quieres guardar 90 días, agregá la flag --storage.tsdb.retention.time=90d en el compose y dimensionar el disco. Loki es similar.

Cuándo conviene self-hosted vs Datadog/New Relic

Esta es la pregunta que más nos hacen, y nuestra respuesta cambia según el contexto. La regla:

Self-hosted gana cuando:

  • Tienes más de un servidor o más de 10-15 servicios.
  • Privacidad importa (LATAM, salud, finanzas).
  • Tu equipo tiene capacidad técnica de operar 6-7 containers más.
  • El costo de Datadog te empieza a doler (200+ USD/mes).
  • Quieres portabilidad — si mañana migras de cloud, tu stack viene contigo.

Self-hosted pierde cuando:

  • Eres uno solo y quieres algo que funcione en 30 minutos.
  • Tu infra es 100% serverless (AWS Lambda, Cloudflare Workers).
  • Necesitas features muy específicos: APM avanzado, real user monitoring, synthetics complejos.
  • No tienes tiempo o equipo para operarlo.

Para una PyME con un VPS y 5-10 servicios, self-hosted es casi siempre la respuesta. Para una startup en cloud creciendo rápido, suele empezar siendo Datadog y migrar después si el costo justifica.

Lo que NO te estamos vendiendo

Este stack tiene defectos honestos que vale la pena nombrar:

  • No es low-touch. Hay que actualizar containers, vigilar disco, ajustar dashboards. Si quieres "instálalo y olvidate", no es esto.
  • El primer setup toma su tiempo. Una persona experimentada se toma 2-3 días para dejarlo bien. Una sin experiencia, 1-2 semanas.
  • Las alertas mal calibradas son ruido. Empiezas con muchas reglas, te llegan emails toda la noche, el equipo aprende a ignorarlos. Calibrarlas para que solo suenen las que importan es un trabajo continuo.

Cómo se conecta con nuestro agente

Esto cierra un círculo que escribimos en SSH read-only + Tailscale: dejé que mi IA vigile el servidor. El agente local consulta endpoints específicos del stack (Grafana API, Prometheus query API) por una conexión read-only segura, y nos da una vigilancia narrativa: "el container forms-api se reinició dos veces en la última hora", "el dashboard HTTP Errors muestra un pico", etc.

El stack hace el trabajo pesado de recolectar y almacenar; el agente hace el de traducir lo que está pasando a lenguaje útil para el operador humano. Es la mejor combinación que probamos.

Si quieres esto en tu servidor

Lo armamos llave en mano. Lo que hacemos:

  • Instalar el stack completo en tu VPS (o el nuestro si nos contratas hosting).
  • Configurar 5-10 dashboards iniciales adaptados a tu negocio.
  • 5-10 reglas de alerta que tengan sentido para tu caso (no las default que generan ruido).
  • Documentación de cómo agregar nuevos servicios al monitoreo en el futuro.
  • 30 días de soporte para calibración fina post-instalación.

Hablemos. En 30 minutos identificamos qué te conviene — a veces no es este stack, es Datadog. Te decimos qué pensamos honestamente para tu caso.


Relacionado: SSH read-only + Tailscale: que la IA vigile el servidor · Cuando "healthy" miente: el container respondía sano · Auditamos nuestro propio servidor · Cloudflare Tunnel: cero puertos abiertos.

Contando…

Preguntas frecuentes

¿Cuánto disco consume este stack?

Depende del volumen de logs y métricas. Para nuestra infraestructura (10+ containers, ~5 dominios públicos), Prometheus usa ~3-5 GB por mes con 15 días de retención, Loki ~10-20 GB por mes según verbosidad de logs, GlitchTip ~1 GB por mes. Total razonable: 30-50 GB de disco por encima del que ya usas. En un VPS de 200 GB SSD no se nota, en uno de 50 GB hay que vigilarlo.

¿Necesito un servidor separado para el stack de monitoreo?

No, en absoluto para PyME. Lo corremos en el mismo VPS que produce datos. La razón típica para separarlo es "si el servidor cae, queremos que el monitoreo siga vivo para diagnosticar" — pero ese caso se resuelve mejor con un uptime monitor externo barato (incluso un monitor gratuito tipo UptimeRobot) que con un segundo servidor. Si tienes más de un servidor, sí conviene un Prometheus por host + un Grafana central, pero ese setup es para infra ya media.

¿GlitchTip es realmente compatible con los SDK de Sentry?

Sí, prácticamente al 100% para captura de errores básica. Los SDKs de Sentry de .NET, Node.js, Python, JavaScript funcionan tal cual apuntando a tu GlitchTip cambiando solo la DSN. Lo que GlitchTip NO soporta (todavía): performance monitoring profundo, profiling, session replay, tracing distribuido. Para 90% de PyME, eso no se usa. Si tu equipo depende de esos features, conviene Sentry SaaS.

¿Las alertas de Grafana son confiables?

Sí, una vez bien configuradas. Tres detalles que cuestan: (1) configurar SMTP correcto para que los correos salgan; (2) definir reglas que no generen falsos positivos (un pico de 1 minuto a las 3am en uso de CPU no es necesariamente una alerta); (3) calibrar quién recibe qué — alertas P0 a 3 personas, P1 a una, P2 a un canal de Slack. Sin esa calibración, el ruido vuelve inútil al sistema. Es un proceso continuo de las primeras 4-8 semanas.

¿Qué pasa si una pieza del stack se cae?

Cada pieza falla con consecuencias distintas: si Prometheus cae, pierdes visibilidad en métricas pero las alertas viejas siguen valiendo (Grafana las cachea brevemente); si Loki cae, pierdes ingreso de logs nuevos pero los viejos siguen consultables; si Grafana cae, pierdes visualización pero Prometheus y Loki siguen recolectando. Lo que es crítico: si SMTP falla, las alertas no salen. Por eso recomendamos un uptime monitor externo independiente sobre el servidor — es el "monitor del monitor" que sí funciona aunque todo lo interno se caiga.

Escrito por

Equipo ServerStack Solutions

Fundador, ServerStack Solutions. Fundador de ServerStack Solutions. Diseño infraestructura y automatización para negocios que quieren dormir tranquilos. Escribo sobre CI/CD, DevOps y herramientas que hacen la diferencia.