Saltar al contenido principal

Infraestructura y Despliegue

Proveedores Cloud

ProveedorServicioPlanPropósito
GCPCloud RunPago por usoCompute serverless para backend y frontend
GCPArtifact RegistryPago por usoRegistro de imágenes Docker
CloudflareDNS, CDN, WAF, DDoSFree ($0)Proxy inverso, caché, seguridad, DNS
SupabasePostgreSQLProBase de datos gestionada
FirebaseAuth, FirestoreSpark (free)Autenticación, base de datos en tiempo real
GitHubRepos, Actions, RegistryFreeControl de versiones, CI/CD, registro de imágenes

Flujo de Despliegue

┌──────────────┐ ┌─────────────────────┐ ┌────────────────────┐ ┌───────────────┐
│ git push │────▶│ GitHub Actions │────▶│ GCP Artifact │────▶│ Cloud Run │
│ staging/test │ │ CI → build → push │ │ Registry │ │ gcloud run │
│ o tag │ │ + gcloud run deploy│ │ (us-west1) │ │ deploy │
└──────────────┘ └─────────────────────┘ └────────────────────┘ └───────┬───────┘

┌──────────────┐ ┌──────────────────┐ ┌─────────────────────────────────────▼──┐
│ Cloudflare │◀────│ Smoke test │◀────│ Cloud Run │
│ purge caché │ │ (health check) │ │ nueva revisión activa │
└──────────────┘ └──────────────────┘ └────────────────────────────────────────┘

Ramas y entornos

RepositorioRama de trabajoRama de staging/deployRama de producción
Backenddevelopmentstagingmain
Frontenddevtestmain

Flujo: feature branch → PR a development/dev → CI (test + build) → merge a staging/testdeploy automático a Cloud Run → smoke test → merge a main para producción.

CI/CD (GitHub Actions)

Ambos repos usan GitHub Actions con autenticación a GCP vía Workload Identity Federation (OIDC, sin JSON keys). Las variables sensibles del proyecto (GCP_PROJECT_ID, CF_API_TOKEN) se almacenan como secrets de GitHub.

Backend (gcp-deploy.yml):

DisparadorAcción
Push a stagingCI (test + build) → Docker build → push a Artifact Registry → gcloud run deploy → smoke test → purge cache Cloudflare
Push de tag v*Igual que arriba, pero con tag semántico en vez de SHA
  • Imagen: us-west1-docker.pkg.dev/<project>/backend-repo/monolitic-api:<sha>
  • Cloud Run: monolitic-api, 512 MiB, 1 CPU, timeout 150s, max 4 instancias, concurrencia 80
  • Smoke test: curl https://api.weloveboom.cloud/ib/api/status/health (5 reintentos, espera HTTP 200)

Frontend (main-pipeline.ymlgcp-deploy.yml):

DisparadorAcción
Push a devSolo CI (test + build). No despliega.
Push a testCI → Docker build → push a Artifact Registry → gcloud run deploy → smoke test → purge cache
Push de tag v*Igual que test
  • Imagen: us-west1-docker.pkg.dev/<project>/frontend-repo/web:<sha>
  • Cloud Run: frontend, 512 MiB, 1 CPU, timeout 60s, max 4 instancias, concurrencia 80
  • Smoke test: curl https://weloveboom.cloud/ (espera HTTP 200 o 307)

Ambos: el purge de caché Cloudflare es no-bloqueante (no revierte el deploy si falla). El escaneo de vulnerabilidades (Trivy) está configurado pero comentado — pendiente de activar.

Docker

Backend

# Build: node:20-slim + pnpm
# Runtime: gcr.io/distroless/nodejs20:nonroot
# Puerto: 8080
# Usuario: non-root
# CMD: dist/main.js
  • Multistage: separa build de runtime para minimizar tamaño
  • Distroless: sin shell, sin gestor de paquetes, superficie de ataque mínima
  • pnpm como gestor de paquetes

Frontend

# Build: node:22-alpine + npm
# Runtime: gcr.io/distroless/nodejs22:nonroot
# Puerto: 8080
# Output: standalone
  • Next.js output standalone: incluye solo lo necesario para producción
  • sharp para optimización de imágenes en producción

Dominios y DNS

Estado actual

  • Dominio principal: weloveboom.cloud
  • Subdominios: api.weloveboom.cloud, www.weloveboom.cloud
  • DNS: Cloudflare (nameservers: jobs.ns.cloudflare.com, lola.ns.cloudflare.com)
  • 15 registros DNS: A (Google IPs), CNAME (api, www), MX (Google Workspace), TXT (SPF, DKIM, Firebase, verificación)

Migración planificada: weloveboom.cloudilboom.cl

Plan de 10 pasos documentado en infra-ilboom/08-domain-migration/. Implica:

  • Aproximadamente 36 referencias a actualizar en código, variables de entorno y documentación
  • Recreación de certificados SSL
  • Actualización de URLs de webhook en Stripe, MercadoPago y Firebase
  • Coexistencia temporal de ambos dominios durante la transición

Caché (3 capas)

CapaProveedorQué cacheaTTL
EdgeCloudflare CDNArchivos estáticos, explore30d estáticos, 2h explore
AplicaciónGCP CDNCACHE_ALL_STATIC en Cloud RunConfigurable
FrameworkNext.js ISRPáginas públicas (explore, categorías)staleTimes: dynamic 30s, static 300s

Las rutas de API (/ib/api/*) no se cachean en Cloudflare.

Terraform (Infraestructura como Código)

Ubicación: infra-ilboom/09-iac-terraform/

# Proveedores
terraform {
required_providers {
google = { source = "hashicorp/google", version = "~> 6.0" }
cloudflare = { source = "cloudflare/cloudflare", version = "~> 5.0" }
}
}

Recursos gestionados

ArchivoRecursos
main.tfCloud Run IAM (permisos de invocación)
cloudflare.tf18 registros DNS, configuración de zona, reglas WAF, reglas de caché
providers.tfConfiguración de providers GCP y Cloudflare
variables.tfVariables parametrizadas para dominio, WAF toggle, caché toggle
outputs.tfOutputs útiles (URLs, nombres)

El estado de Terraform está versionado. Recrear el entorno completo desde cero es terraform apply.

Variables de Entorno

Backend — agrupadas por servicio

General: NODE_ENV, PORT, DATABASE_URL, SQLITE_DATABASE, DB_LOGGING, FRONTEND_BASE_URL, TIME_OUT, LOG_LEVEL

Firebase Auth: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY (o FIREBASE_PRIVATE_KEY_B64)

Cloudflare R2: R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ACCOUNT_ID, R2_BUCKET_NAME, R2_PUBLIC_URL

Cloudflare Stream: CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_STREAM_API_TOKEN, CLOUDFLARE_WEBHOOK_SECRET, CLOUDFLARE_STREAM_SIGNING_KEY_ID, CLOUDFLARE_STREAM_SIGNING_PRIVATE_KEY

Stripe: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_CONNECT_WEBHOOK_SECRET, STRIPE_NOTIFICATION_URL

MercadoPago: MP_ACCESS_TOKEN, MP_WEBHOOK_SECRET, PAYMENT_SUCCESS_URL, PAYMENT_FAILURE_URL, PAYMENT_NOTIFICATION_URL

dLocalGo: DLOCALGO_API_KEY, DLOCALGO_SECRET_KEY, DLOCALGO_API_URL, DLOCALGO_COUNTRY, DLOCALGO_NOTIFICATION_URL

Feature flags: PLATFORM_FEE_PERCENT, FEATURE_VIDEO_PRESIGNED_UPLOAD, VIDEO_MAX_FEED_DURATION_SECONDS, VIDEO_MAX_VOD_DURATION_SECONDS, VIDEO_MAX_UPLOAD_SIZE_BYTES, VIDEO_PRESIGNED_URL_TTL_SECONDS, VIDEO_OUTPUT_MAX_WIDTH, VIDEO_OUTPUT_MAX_HEIGHT, VIDEO_TRANSCODE_BITRATE

Proveedor de pago por defecto: PAYMENT_PROVIDER

Frontend

Públicas (accesibles desde el navegador, prefijo NEXT_PUBLIC_): NEXT_PUBLIC_API_URL, NEXT_PUBLIC_FIREBASE_API_KEY, NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, NEXT_PUBLIC_FIREBASE_PROJECT_ID, NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, NEXT_PUBLIC_FIREBASE_APP_ID, NEXT_PUBLIC_VIDEO_MAX_FEED_DURATION, NEXT_PUBLIC_VIDEO_MAX_VOD_DURATION, NEXT_PUBLIC_VIDEO_OUTPUT_MAX_WIDTH, NEXT_PUBLIC_VIDEO_OUTPUT_MAX_HEIGHT, NEXT_PUBLIC_VIDEO_TRANSCODE_BITRATE

Privadas (solo servidor): API_URL, FIREBASE_API_KEY, FIREBASE_AUTH_DOMAIN, FIREBASE_PROJECT_ID, FIREBASE_STORAGE_BUCKET, FIREBASE_MESSAGING_SENDER_ID, FIREBASE_APP_ID

Inyección de variables en runtime

El frontend expone /runtime-env.js (ruta force-dynamic) que inyecta window.__INBOOM_RUNTIME_ENV__ en el cliente desde process.env del servidor. Esto permite cambiar variables sin rebuild.

Costos Mensuales Estimados

ServicioCosto aproximadoNotas
GCP Cloud Run$20–502 servicios 512 MiB, tráfico moderado
GCP Artifact Registry$0–5Almacenamiento de imágenes Docker
Cloudflare$0Plan Free cubre DNS, CDN, WAF, DDoS
Supabase~$25PostgreSQL gestionado, plan Pro
Firebase Auth$0Spark plan (límites generosos: 50K MAU)
Firebase Firestore$0Spark plan (1 GiB almacenado, 50K lecturas/día)
GitHub$0Plan Free (repositorios privados ilimitados)
Stripe / MP / dLocalVariableSolo comisiones por transacción
Total fijo~$45–80/mesSin contar comisiones de pago