$200 USD al Mes: Lo Que Cuesta Correr 35+ Apps en Producción
Cuando mencionas que corres 35 aplicaciones web en producción en un solo servidor, la primera pregunta siempre es: “¿Cuánto pagas de hosting?”. Y cuando respondo $200 USD al mes (unos $3,800 MXN), la reacción es de incredulidad absoluta.
La industria ha creado una narrativa donde necesitas AWS, GCP o Azure para ser “profesional”. Donde un Load Balancer es obligatorio, donde Kubernetes es el estándar, donde menos de $1,000 USD/mes en infraestructura significa que no te tomas en serio tu negocio.
Esa narrativa es una mentira para el 95% de los negocios de software en México.
En iAmanos llevamos más de un año corriendo toda nuestra operación — 35+ apps con IA, bases de datos PostgreSQL, reverse proxy, SSL automático, backups — en un solo VPS de Hostinger. Y no es un demo. Son apps con usuarios reales, datos reales, transacciones reales.
Este artículo es el tutorial que hubiera querido tener cuando empecé. Cada comando, cada archivo de configuración, cada decisión arquitectónica. Sin teoría, sin abstracciones innecesarias. La infraestructura exacta que usamos en producción.
Por Qué un VPS y No AWS: La Decisión Que Nos Ahorró $30,000 USD al Año
Antes de meternos en la configuración, necesitas entender POR QUÉ elegimos un VPS en vez de un cloud provider “serio”.
El costo real de AWS para nuestro caso de uso
Hicimos el cálculo real de lo que costaría nuestra infraestructura en AWS:
- EC2 t3.xlarge (equivalente a nuestro VPS): ~$120 USD/mes
- RDS PostgreSQL x15 instancias (una por app principal): ~$600 USD/mes (db.t3.micro cada una)
- ALB (Application Load Balancer): ~$25 USD/mes base + tráfico
- Route 53 DNS: ~$10 USD/mes
- ACM (certificados SSL): gratis, pero requiere ALB que sí cobra
- EBS storage: ~$50 USD/mes (200 GB gp3)
- Data transfer: ~$50-100 USD/mes
- CloudWatch: ~$30 USD/mes para logs y métricas
- Total estimado: $1,000-1,200 USD/mes MÍNIMO
Y eso es la versión conservadora. Con auto-scaling, WAF, y ElastiCache que la gente suele agregar, fácilmente llegas a $2,000-3,000 USD/mes.
Nosotros pagamos $200. La diferencia: $800-2,800 USD/mes que van directo a la utilidad en lugar de subsidiar la infraestructura de Amazon.
¿Cuándo SÍ necesitas cloud?
El VPS no es para todos. Necesitas cloud cuando:
- Tienes picos de tráfico impredecibles (Black Friday, campañas virales)
- Necesitas distribución global con latencia <50ms en múltiples regiones
- Tu empresa tiene requisitos de compliance (HIPAA, SOC2, PCI) que exigen certificaciones del proveedor
- Necesitas managed services específicos (Lambda, SQS, DynamoDB sin equivalente simple)
- Tu tráfico excede 10,000 usuarios concurrentes
Para el 95% de los SaaS mexicanos en etapa temprana, ninguna de estas condiciones aplica. Si tienes menos de 1,000 usuarios activos diarios, un VPS bien configurado te sobra.
El VPS: Hostinger KVM 2 — Especificaciones y Setup Inicial
Nuestro servidor es un Hostinger KVM 2 con estas especificaciones:
- CPU: 4 vCPUs (AMD EPYC)
- RAM: 8 GB
- Storage: 200 GB NVMe SSD
- Bandwidth: 8 TB/mes
- IP: 168.231.64.157 (IP estática dedicada)
- OS: Ubuntu 22.04 LTS
- Costo: ~$200 USD/mes (con plan anual es menos)
- Ubicación: Datacenter en EE.UU. (no hay datacenter Hostinger en México todavía)
Setup inicial del VPS
Después de provisionar el VPS, estos son los pasos que ejecutamos una sola vez:
# 1. Acceso SSH con llave (NUNCA password)
ssh root@168.231.64.157
# 2. Actualizar el sistema
apt update && apt upgrade -y
# 3. Instalar Docker
curl -fsSL https://get.docker.com | sh
# 4. Instalar Docker Compose
apt install docker-compose-plugin -y
# 5. Configurar firewall
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP (Traefik)
ufw allow 443/tcp # HTTPS (Traefik)
ufw enable
# 6. Configurar SSH key auth (deshabilitar password)
# En /etc/ssh/sshd_config:
# PasswordAuthentication no
# PubkeyAuthentication yes
systemctl restart sshd
Total de setup: 15 minutos. Después de esto, el VPS está listo para recibir apps.
Traefik: El Reverse Proxy Que Maneja SSL Automático Para 35+ Dominios
Aquí está la pieza clave de toda la arquitectura: Traefik. Es un reverse proxy moderno que:
- Detecta automáticamente nuevos contenedores Docker y les asigna rutas
- Genera certificados SSL con Let’s Encrypt sin intervención manual
- Renueva certificados automáticamente antes de que expiren
- Balancea carga entre réplicas si las necesitas
- Dashboard web para monitorear el estado de todos los servicios
Configuración real de Traefik
Nuestro archivo docker-compose.yml principal en /root/docker-compose.yml tiene Traefik como servicio central. La configuración real (simplificada para este tutorial):
version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: always
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedByDefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=admin@iamanos.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks:
- traefik-net
networks:
traefik-net:
external: true
La red compartida: traefik-net
El secreto para que todas las apps se comuniquen con Traefik es una red Docker compartida:
docker network create traefik-net
Cada app se conecta a esta red. Traefik descubre las apps a través de labels de Docker. No necesitas tocar la configuración de Traefik cuando agregas una app nueva — solo las labels del contenedor.
Cómo una app se conecta a Traefik
Cada app tiene su propio docker-compose.yml en su directorio. La parte relevante es las labels:
services:
wouwou:
build: .
container_name: wouwou
restart: always
labels:
- "traefik.enable=true"
- "traefik.http.routers.wouwou.rule=Host(`wouwou.iamanos.com`)"
- "traefik.http.routers.wouwou.entrypoints=websecure"
- "traefik.http.routers.wouwou.tls.certresolver=letsencrypt"
- "traefik.http.services.wouwou.loadbalancer.server.port=3000"
networks:
- traefik-net
- wouwou-internal
postgres-wouwou:
image: postgres:16-alpine
container_name: postgres-wouwou
restart: always
environment:
POSTGRES_USER: wouwou
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: wouwou_db
volumes:
- wouwou-pgdata:/var/lib/postgresql/data
networks:
- wouwou-internal
networks:
traefik-net:
external: true
wouwou-internal:
driver: bridge
volumes:
wouwou-pgdata:
Observa el patrón:
- La app se conecta a
traefik-net(para que Traefik la descubra) Y a una red interna propia - PostgreSQL SOLO está en la red interna — no es accesible desde fuera
- Las labels le dicen a Traefik: “cuando alguien pida wouwou.iamanos.com, mándalo al puerto 3000 de este contenedor”
- Traefik automáticamente genera el certificado SSL para wouwou.iamanos.com
Agregar una app nueva toma literalmente 2 minutos: copias el docker-compose, cambias el nombre, el dominio y el puerto. Traefik hace el resto.
El Script de Deploy: rsync + docker build + compose up
Cada app tiene un archivo deploy.sh en su raíz. Este es el patrón estándar que usamos en las 35+ apps:
#!/bin/bash
# deploy.sh — Deploy de [app] al VPS
set -e
VPS="root@168.231.64.157"
REMOTE_DIR="/root/mi-app"
echo "=== Sincronizando código ==="
rsync -avz --delete \
--exclude 'node_modules' \
--exclude '.next' \
--exclude '.git' \
--exclude '.env.local' \
./ $VPS:$REMOTE_DIR/
echo "=== Construyendo imagen Docker ==="
ssh $VPS "cd $REMOTE_DIR && docker build -t mi-app:latest ."
echo "=== Levantando contenedor ==="
ssh $VPS "cd $REMOTE_DIR && docker compose up -d mi-app"
echo "=== Deploy completo ==="
Desglose del proceso
- rsync: Sincroniza el código local al VPS. El flag
--deleteelimina archivos remotos que ya no existen localmente. Excluimosnode_modulesy.nextporque se regeneran en el build. - docker build: Construye la imagen Docker en el VPS usando el Dockerfile multi-stage.
- docker compose up -d: Levanta (o recrea) el contenedor con la nueva imagen. Traefik detecta el cambio automáticamente.
Tiempo total de deploy: 2-5 minutos dependiendo del tamaño de la app y la velocidad de upload.
El Dockerfile multi-stage
Para apps Next.js, usamos un Dockerfile multi-stage que produce imágenes de ~150-200 MB:
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["npm", "start"]
La clave del multi-stage: la imagen final solo tiene lo necesario para correr la app, no las herramientas de build. Esto reduce el tamaño y la superficie de ataque.
DNS y Dominios: Cómo Apuntar Todos los Subdominios al VPS
Cada app tiene su propio subdominio: wouwou.iamanos.com, glambook.iamanos.com, leads.iamanos.com, coti.iamanos.com, etc.
Configuración DNS
En nuestro registrador de dominio (donde tenemos iamanos.com), la configuración es simple:
# Records A que apuntan al VPS
*.iamanos.com A 168.231.64.157 TTL: 3600
iamanos.com A 168.231.64.157 TTL: 3600
El record wildcard (*) significa que cualquier subdominio apunta al VPS automáticamente. No necesitas crear un record DNS nuevo para cada app — solo el Docker label con el dominio y Traefik se encarga.
Proceso para agregar un dominio nuevo
- Si es subdominio de iamanos.com: no hacer nada en DNS (el wildcard ya lo cubre)
- Si es dominio externo: crear un A record apuntando a 168.231.64.157
- Agregar la label de Traefik en el docker-compose de la app
- Hacer deploy — Traefik genera el certificado SSL en 30 segundos
El certificado SSL es gratuito (Let’s Encrypt) y se renueva automáticamente cada 60 días. Cero mantenimiento.
Monitoreo y Backups: Lo Mínimo Necesario Que Funciona
No tenemos Grafana, ni Prometheus, ni DataDog. ¿Por qué? Porque para 35 apps con ~500 usuarios activos diarios totales, es overkill.
Lo que sí monitoreamos
- docker stats: Uso de CPU y RAM por contenedor. Lo revisamos cuando algo se siente lento.
- docker logs [container]: Logs de cada app. Los revisamos cuando algo falla.
- df -h: Espacio en disco. Lo revisamos semanalmente.
- Traefik dashboard: Estado de todos los servicios y certificados SSL.
- Uptime manual: Visitamos las apps principales diariamente como parte de la rutina.
Estrategia de backups
Para las bases de datos PostgreSQL:
# Backup de una base de datos específica
docker exec postgres-wouwou pg_dump -U wouwou wouwou_db > backup_wouwou_$(date +%Y%m%d).sql
# Backup de TODAS las bases
for container in $(docker ps --filter name=postgres -q); do
name=$(docker inspect --format='{{.Name}}' $container | sed 's/\///')
docker exec $container pg_dumpall -U postgres > backup_${name}_$(date +%Y%m%d).sql
done
Los backups se ejecutan con un cron job diario y se guardan en un directorio /root/backups/ con retención de 7 días. Para desastre total, podríamos restaurar todo en un VPS nuevo en menos de 2 horas.
¿Es esto la infraestructura más robusta del mundo? No. ¿Es suficiente para nuestro volumen de tráfico y nivel de criticidad? Absolutamente.
Arquitectura Completa: Cómo Conviven 35+ Apps en un Solo Servidor
Para que visualices cómo se ve todo junto, aquí está el mapa de nuestra infraestructura:
Internet
│
├── DNS (*.iamanos.com → 168.231.64.157)
│
▼
┌─────────────────────────────────┐
│ VPS Hostinger KVM 2 │
│ 8 GB RAM │ 4 vCPUs │ 200 GB │
│ │
│ ┌─────────┐ │
│ │ Traefik │ ←── :80, :443 │
│ └────┬────┘ │
│ │ traefik-net │
│ ├──→ iamanos-site (:3000) │
│ ├──→ wouwou (:3000) │
│ ├──→ glambook (:3000) │
│ ├──→ lead-desk (:3000) │
│ ├──→ cotizador (:3000) │
│ ├──→ fay-optimizer (:3000) │
│ ├──→ wouwou-crm (:3000) │
│ └──→ ... (35+ apps) │
│ │
│ Cada app tiene: │
│ ├── contenedor app (Next.js) │
│ ├── contenedor PostgreSQL │
│ └── red interna aislada │
└──────────────────────────────────┘
Uso de recursos
Con 35+ contenedores corriendo, el uso típico del servidor es:
- RAM: ~5.5 GB de 8 GB (70%). Cada app Next.js usa ~100-200 MB, cada PostgreSQL ~50-100 MB.
- CPU: ~15-30% en promedio. Picos del 60-70% durante deploys o generación de imágenes IA.
- Disco: ~80 GB de 200 GB usados. Las bases de datos más grandes tienen ~2-5 GB (WouWou con 206 razas + imágenes).
- Bandwidth: ~200 GB/mes de 8 TB disponibles (apenas el 2.5%).
Tenemos margen de sobra. Podríamos duplicar el número de apps sin tocar los límites del servidor.
Comparativa de Costos: VPS vs. Cloud vs. PaaS
Para que tomes la mejor decisión según tu contexto, aquí está la comparativa real:
Opción 1: VPS (nuestro modelo)
- Costo por 35 apps: $200 USD/mes
- Costo por app: ~$5.7 USD/mes
- SSL: Gratis (Let’s Encrypt + Traefik automático)
- Control: Total (root access, configuras todo)
- Mantenimiento: Tú (actualizaciones OS, Docker, backups)
- Escalamiento: Vertical (upgrade VPS) o agregar segundo VPS
Opción 2: AWS/GCP/Azure
- Costo por 35 apps: $1,000-3,000 USD/mes
- Costo por app: $28-85 USD/mes
- SSL: Gratis (ACM) pero requiere ALB ($25/mes)
- Control: Alto (pero complejidad de 50+ servicios)
- Mantenimiento: Parcial (managed services reducen trabajo)
- Escalamiento: Horizontal automático (auto-scaling groups)
Opción 3: PaaS (Vercel, Railway, Render)
- Costo por 35 apps: $700-1,750 USD/mes ($20-50 por app)
- Costo por app: $20-50 USD/mes
- SSL: Gratis e incluido
- Control: Limitado (no root, restricciones de runtime)
- Mantenimiento: Mínimo (el PaaS maneja todo)
- Escalamiento: Automático (pero caro)
Para startups y agencias mexicanas construyendo SaaS, el VPS es la opción más inteligente hasta que tengas tráfico que justifique los costos de cloud. Y ese punto llega mucho más tarde de lo que la industria quiere hacerte creer.
Errores Comunes Que Cometimos (Y Cómo Evitarlos)
Error 1: docker-compose up sin especificar servicio
Si tienes un docker-compose.yml principal con Traefik y haces docker-compose up -d sin especificar servicio, puede recrear contenedores que no quieres tocar. Siempre especifica: docker compose up -d mi-app.
Error 2: No usar –delete en rsync (o usarlo mal)
Sin --delete, archivos que borraste localmente siguen existiendo en el VPS. Con --delete en el directorio equivocado, puedes borrar el .env de producción. Solución: siempre excluir .env del rsync y mantener el .env solo en el VPS.
Error 3: PostgreSQL expuesto a la red pública
NUNCA pongas tu contenedor PostgreSQL en la red de Traefik. Debe estar en una red interna propia. Si accidentalmente expones el puerto 5432, cualquiera puede intentar conectarse a tu base de datos.
Error 4: No separar redes por app
Cada app debe tener su red interna propia para que su PostgreSQL no sea accesible desde otros contenedores. Esto es aislamiento básico que muchos tutoriales se saltan.
Error 5: Olvidar los volúmenes de PostgreSQL
Si no defines un volumen para los datos de PostgreSQL, un docker compose down borra TODA tu base de datos. Los volúmenes nombrados (mi-app-pgdata) persisten aunque el contenedor se destruya.
Error 6: No tener strategy de rebuild
Importante: si tu app usa output: 'standalone' en Next.js, necesitas rebuild completo para aplicar cambios. Un docker compose restart NO aplica cambios del código nuevo. Siempre haz docker build + docker compose up -d.
Estrategia de Escalamiento: Cuándo y Cómo Crecer
Nuestro plan de escalamiento tiene 3 fases:
Fase actual: Un solo VPS (35+ apps, ~500 DAU)
Funciona perfecto. 30% de capacidad utilizada. Sin problemas de performance.
Fase 2: Separar apps de alto tráfico (1,000+ DAU por app)
Cuando una app específica (por ejemplo, WouWou) alcance 1,000+ usuarios activos diarios, la moveremos a su propio VPS dedicado. El proceso es simple: rsync al nuevo VPS, apuntar DNS, done.
Fase 3: Cloud para apps que lo necesiten (10,000+ DAU)
Si alguna app necesita auto-scaling real, la migraremos a AWS/GCP. Pero solo esa app — las demás siguen en VPS. No hay razón para mover todo al cloud porque una app lo necesite.
La belleza de Docker es que la migración es transparente. La app que corre en nuestro VPS corre exactamente igual en AWS ECS, GCP Cloud Run, o cualquier otro servicio que soporte Docker. No hay vendor lock-in.
Tutorial Paso a Paso: De Cero a Deploy en 30 Minutos
Si quieres replicar nuestra infraestructura desde cero, estos son los pasos exactos:
Paso 1: Contrata el VPS (5 minutos)
Hostinger, DigitalOcean, Hetzner — cualquier VPS con mínimo 4 GB RAM y 2 vCPUs. Instala Ubuntu 22.04.
Paso 2: Instala Docker y crea la red (5 minutos)
curl -fsSL https://get.docker.com | sh
apt install docker-compose-plugin -y
docker network create traefik-net
Paso 3: Configura Traefik (5 minutos)
Crea /root/docker-compose.yml con la configuración de Traefik que mostramos arriba. Ejecuta docker compose up -d.
Paso 4: Apunta tu dominio (5 minutos)
Crea un A record wildcard (*.tudominio.com) apuntando a la IP de tu VPS.
Paso 5: Despliega tu primera app (10 minutos)
Crea el docker-compose.yml de tu app con las labels de Traefik, sube con rsync, build y up.
En 30 minutos tienes una infraestructura de producción con SSL automático, reverse proxy, y capacidad para decenas de apps. Todo por $200 USD/mes.
En iAmanos hemos refinado este setup durante más de un año con 35+ apps en producción. Si necesitas una app con IA desplegada en esta infraestructura, cotiza aquí y la tendrás corriendo en días.
Preguntas Frecuentes
¿Un VPS de $200 USD/mes realmente aguanta 35 apps?
Sí. Con 8 GB de RAM y Docker optimizado, cada app Next.js consume ~100-200 MB y cada PostgreSQL ~50-100 MB. Con 35 apps usamos ~70% de la RAM. El CPU rara vez pasa del 30% en uso normal.
¿Qué pasa si el VPS se cae?
Hostinger garantiza 99.9% uptime. En un año hemos tenido menos de 2 horas de downtime total. Los contenedores Docker tienen restart:always, así que se levantan solos después de un reinicio del servidor.
¿Traefik es mejor que Nginx como reverse proxy?
Para nuestra configuración con Docker, sí. Traefik descubre contenedores automáticamente y genera SSL sin intervención. Con Nginx tendrías que editar la configuración manualmente para cada app nueva y correr certbot para cada dominio.
¿Puedo usar este setup para apps que no son Next.js?
Absolutamente. Cualquier app que corra en Docker funciona con este setup. Python, Go, Ruby, PHP — solo necesitas el Dockerfile y las labels de Traefik. El framework no importa.
¿Este setup cumple con estándares de seguridad para producción?
Para SaaS pequeño y mediano en México, sí. Tenemos SSL en todo, bases de datos aisladas en redes internas, SSH por llave, firewall UFW. Para compliance tipo SOC2 o HIPAA necesitarías infraestructura certificada en cloud.



