El manual de SaaS de $5 VPS: Una configuración práctica de Next.js 15 (Sin Vercel, Sin Supabase, Sin Clerk)
publicado originalmente por @the_nortern_dev
(detalles de contacto y repositorio git abajo)
Un manual práctico de un servidor para ejecutar un SaaS de aspecto productivo en un VPS económico: autenticación, suscripciones de Stripe, webhooks, copias de seguridad y un flujo de despliegue aburrido.
Hace unos días escribí sobre el impuesto en la nube que hemos normalizado — pagando $50–$100/mes antes de validar una idea u obtener tu primer cliente.
Este es el seguimiento que la gente pidió: la configuración práctica.
Sin filosofía. Sin “solo usa Kubernetes”. Solo una forma aburrida y de aspecto productivo de ejecutar un SaaS en una máquina.
Si quieres discutir la premisa, adelante, hazlo en los comentarios.
Pero al menos ahora estamos discutiendo algo concreto.
El objetivo
Una línea base de producción en un único VPS:
- los usuarios pueden iniciar sesión (enlace mágico + Google OAuth)
- los usuarios pueden pagar (suscripciones de Stripe)
- tu aplicación sobrevive a los errores (copias de seguridad automatizadas + restauración simple)
- los despliegues son aburridos (Docker Compose)
- los costos se mantienen alrededor de $5–$10/mes hasta que tengas una razón real para escalar
Lo que cubre esta guía
- Configuración de VPS (mínima)
- Un diseño simple de Docker Compose (aplicación + proxy + copias de seguridad)
- SQLite en producción (WAL + copias de seguridad seguras)
- Suscripciones de Stripe + webhooks (lo que realmente importa)
- Una breve “lista de verificación de producción” antes de lanzar
Atajo (si quieres saltarte el cableado): Empaqué esta línea base exacta (autenticación + Stripe + Docker + copias de seguridad) en un kit de inicio:
Obtén el kit de inicio
Si prefieres hacerlo tú mismo, sigue leyendo, los pasos a continuación son el plano.
1) El VPS: mantenlo aburrido
Cualquier proveedor funciona. Una máquina de $5–$10 es suficiente para empezar.
Mínimo que me gusta:
- 1 vCPU, 2GB RAM
- almacenamiento SSD/NVMe
- Ubuntu LTS
En el servidor:
- crear un usuario sin privilegios de root
- habilitar un firewall (permitir 22, 80, 443)
- instalar Docker + Docker Compose
- apuntar tu dominio (registro A) al VPS
Eso es todo. No necesitas una malla de servicios. Necesitas una máquina que funcione.
2) La arquitectura: un servidor, tres responsabilidades
Lo mantengo en tres partes móviles:
A) Contenedor de aplicación
Tu aplicación Next.js + rutas API para autenticación + webhooks de Stripe.
B) Proxy inverso
Nginx (o Caddy) termina TLS y reenvía el tráfico a la aplicación.
C) Copias de seguridad
Un pequeño trabajo programado que captura una instantánea de tu base de datos SQLite y mantiene la retención.
Esta es la parte que la gente subestima: la producción se trata principalmente de recuperación.
3) SQLite en producción: WAL + copias de seguridad que realmente se restauran
SQLite se descarta porque la gente imagina “base de datos de juguete”.
En realidad, para muchas cargas de trabajo de SaaS en etapa inicial, es un código de trucos:
- cero dependencia externa
- un archivo para mover/respaldar
- baja latencia (misma máquina)
Modo WAL
WAL mejora las características de concurrencia y reduce la contención de escritura.
Copias de seguridad: no seas ingenioso
Mi enfoque de línea base es intencionalmente aburrido:
- usar el comando
.backupintegrado de SQLite (instantáneas seguras) - comprimir copias de seguridad
- mantener 30 días de historial
- tener pasos de restauración que tomen 2 minutos
Conceptualmente:
- instantánea:
sqlite3 db.sqlite ".backup 'backup_YYYYMMDD_HHMMSS.db'" - comprimirla con gzip
- eliminar copias de seguridad antiguas
Importante: prueba una restauración una vez. La mayoría de las “estrategias de copia de seguridad” fallan en el paso de restauración, no en el paso de copia de seguridad.
4) Suscripciones de Stripe: la parte que te muerde después
Si has integrado Stripe antes, ya conoces los puntos débiles:
- los webhooks se reintentan
- los eventos pueden llegar fuera de orden
- “funcionó en modo de prueba” no significa nada sin idempotencia
Aquí está lo que trato como no negociable en una línea base de producción:
A) Verificar firmas de webhook
Si aceptas solicitudes de webhook sin firmar, no tienes webhooks — tienes un punto final de administrador público.
B) Hacer webhooks idempotentes
Stripe reintenta. Las redes fallan. Verás duplicados.
Tus controladores deben manejar de forma segura:
- “mismo evento nuevamente”
- “misma actualización de suscripción nuevamente”
El patrón más fácil:
- almacenar IDs de Stripe (cliente/suscripción)
- upsert estado de suscripción
- no asumir que los eventos de checkout solo se disparan una vez
C) Usar metadatos para mapear usuarios
No confíes en la coincidencia de correo electrónico como tu clave de unión principal.
Adjunta tu userId interno como metadatos al crear la sesión de checkout.
5) La lista de verificación de producción (antes de lanzar)
Esto es lo que previene el desastre de las 2am:
- HTTPS habilitado + renovación automática (Let’s Encrypt)
- los secretos son variables de entorno (no comprometidos)
- la verificación de firma de webhook está activada
- los controladores de webhook son idempotentes (reproducciones seguras)
- las copias de seguridad se están ejecutando + retención configurada
- probaste una restauración una vez
- los registros son accesibles (
docker compose logs -f) - los contenedores se ejecutan como no root (donde sea posible)
Por qué esto importa (y dónde se rompe)
No estoy afirmando que un servidor sea el final del juego.
Estoy afirmando que es la forma más rápida de:
- validar el producto
- cobrar pagos
- mantener la pista
- evitar bloqueos tempranos
¿Cuándo esto deja de ser suficiente?
- contención de escritura pesada
- requisitos de múltiples regiones
- requisitos estrictos de HA
- restricciones de cumplimiento empresarial
Ese es el punto: actualiza cuando la realidad lo obliga, no porque un tutorial te lo dijo.
Si quieres la configuración exacta (sin reconstruirla)
Empaqué esta “línea base de SaaS de un servidor” como un kit de inicio:
- estructura de aplicación Next.js 15
- autenticación de enlace mágico + Google OAuth
- suscripciones de Stripe + página de facturación + portal de cliente + webhooks
- SQLite + migraciones
- despliegue de Docker + copias de seguridad diarias automatizadas + pasos de restauración
Discusión (genuinamente quiero opiniones)
- ¿Cuál es tu límite para cuándo SQLite deja de ser aceptable?
- Si auto-alojas, ¿qué tiende a fallar primero: SSL, despliegues, copias de seguridad o webhooks?
- ¿Preferirías pagar el impuesto de servicio administrado temprano, o mantener la infraestructura mínima hasta tener ingresos?
Si no estás de acuerdo con nada de lo anterior, estoy feliz de debatirlo — con números o modos de fallo reales.
Contacto: nordicsecures@proton.me

