For AI agents: fetch the complete documentation index at /llms.txt, the full documentation corpus at /llms-full.txt, the agent skill at /skill.md, or this page as Markdown at /es/docs/web/deploy-google-cloud.md (or send Accept: text/markdown).
Desplegar en Google Cloud
Construye la imagen Docker del kit en Cloud Build, ejecútala en Cloud Run con secretos gestionados y ponla en tu dominio.
Guía paso a paso para principiantes
Prerrequisitos: la app funcionando en local, una base de datos real alcanzable desde internet (Configurar la base de datos) y las cuentas de proveedores de las funciones que lanzas. Necesitas una cuenta de Google; la configuración de facturación pide una tarjeta aunque el uso ligero se mantenga dentro del free tier.
Términos rápidos: una imagen de contenedor es una copia empaquetada de tu app que cualquier host puede ejecutar. Artifact Registry es el almacén de imágenes de Google. Cloud Build construye la imagen en las máquinas de Google — no hace falta Docker local. Cloud Run ejecuta la imagen como un servicio HTTPS y la escala. Secret Manager guarda contraseñas y claves. Una revisión es una versión desplegada del servicio.
Lo que vas a construir: un proyecto de Google Cloud, un repositorio de Artifact Registry con tu imagen, un servicio de Cloud Run que sirve la app por HTTPS, secretos en Secret Manager y un Postgres gestionado. El Dockerfile de la raíz del kit ya produce un servidor Next.js standalone escuchando en el puerto 8080 — exactamente lo que Cloud Run espera.
Nota honesta de costes: el free tier de Cloud Run cubre tráfico ligero, pero Cloud SQL — el Postgres gestionado de Google — no tiene free tier. Una base de datos Supabase o Neon en free tier es la forma más barata de empezar; esta guía usa ese camino. Considera añadir una alerta de presupuesto en Billing → Budgets & alerts antes de experimentar.
Crear la cuenta e instalar la CLI
1. Abre console.cloud.google.com, inicia sesión con tu cuenta de Google y acepta los términos.
2. Vincula la facturación cuando se te pida: Billing → Link a billing account → Create billing account. Se requiere una tarjeta para activar la cuenta; el crédito de prueba cubre los primeros experimentos.
3. Haz clic en el desplegable de proyecto → New Project, ponle nombre y Create — o reutiliza el proyecto que hiciste para el inicio de sesión con Google; un solo proyecto vale.
4. Instala la Google Cloud CLI desde cloud.google.com/sdk: descarga el instalador para tu sistema operativo, complétalo y abre un terminal nuevo para que el comando gcloud esté disponible.
5. Ejecuta los dos comandos de abajo. El primero abre un navegador para autorizar la CLI; el segundo selecciona tu proyecto — usa el ID de proyecto que muestra el panel de la consola, que no siempre coincide con el nombre.
Esperado: gcloud config list muestra tu cuenta y proyecto. Si gcloud no se reconoce, reabre el terminal o termina primero el instalador.
gcloud auth login
gcloud config set project YOUR_PROJECT_IDCrear la base de datos de producción
Camino para principiantes — Postgres gestionado fuera de Google. En supabase.com: New project → elige nombre, contraseña de base de datos y región → espera el aprovisionamiento → Project Settings → Database. Supabase ofrece dos cadenas de conexión: el session pooler / conexión directa en el puerto 5432 y el transaction pooler en el puerto 6543 — la cadena 5432 es para migraciones y clientes long-lived, la 6543 para la app serverless. En neon.tech: New project → copia la cadena de conexión que muestra. Cualquiera sirve; deja intacta la parte de la contraseña.
Pon la cadena direct/session en DATABASE_URL del .env de la raíz — la herramienta de migración lee el archivo de la raíz y necesita una conexión de sesión — y en apps/web/.env.local para el servidor de desarrollo local. Después ejecuta el comando de migración una vez desde la raíz del repositorio para crear las tablas del kit en la nueva base de datos. El secreto DATABASE_URL que usa la app desplegada puede ser en cambio la cadena pooled 6543.
La alternativa nativa de Google es Cloud SQL, un Postgres gestionado dentro del mismo proyecto. No tiene free tier y las conexiones por IP privada requieren un conector VPC — trátalo como una mejora posterior, no como punto de partida.
# DATABASE_URL=<the direct/session Postgres string, port 5432> in .env + apps/web/.env.local, then:
corepack pnpm --filter @supastack/db db:migrateHabilitar servicios y subir la imagen
Ejecuta los comandos de abajo desde la raíz del repositorio. Habilitan los cuatro servicios de Google que usa este despliegue, crean un repositorio Docker en Artifact Registry y envían el repositorio a Cloud Build — que construye el Dockerfile de la raíz en remoto, así que Docker Desktop no hace falta.
Sustituye YOUR_PROJECT_ID y elige una región — us-central1 abajo — y reutilízala para el repositorio y el servicio. Esperado: el log de build se desplaza varios minutos y termina con DONE / STATUS: SUCCESS. La imagen aparece luego en la consola en Artifact Registry → supastack → web.
gcloud services enable run.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com secretmanager.googleapis.com
gcloud artifacts repositories create supastack --repository-format=docker --location=us-central1
gcloud builds submit --tag us-central1-docker.pkg.dev/YOUR_PROJECT_ID/supastack/web:latestGuardar los secretos en Secret Manager
Los secretos nunca van en --set-env-vars ni en la imagen — ambos se guardan en texto plano y son visibles para cualquiera que pueda leer la configuración del servicio. Secret Manager los mantiene cifrados y los inyecta en tiempo de ejecución.
1. En la consola abre Security → Secret Manager → Create Secret.
2. Crea DATABASE_URL con la cadena de conexión Postgres completa — la cadena serverless pooled vale para la app — AUTH_SECRET con al menos 32 caracteres aleatorios (openssl rand -hex 32 genera uno) y CREDENTIAL_ENCRYPTION_KEY con una clave de 32 bytes codificada en Base64 (openssl rand -base64 32); cifra las claves de proveedores que los workspaces guardan en la app.
3. Crea un secreto por proveedor habilitado — por ejemplo STRIPE_SECRET_KEY más STRIPE_WEBHOOK_SECRET, RESEND_API_KEY, GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_SECRET. Ajustes no secretos como EMAIL_PROVIDER=resend quedan como variables de entorno normales, no secretos.
La primera vez que un servicio referencia un secreto, su cuenta de servicio de ejecución necesita permiso para leerlo — cuando adjuntas secretos desde el editor de servicio de la consola, Google ofrece ese permiso automáticamente; en la CLI el error de despliegue nombra el rol de Secret Manager que hay que conceder.
# Secrets to create in Secret Manager:
DATABASE_URL # Postgres connection string — the pooled serverless string is fine
AUTH_SECRET # openssl rand -hex 32
CREDENTIAL_ENCRYPTION_KEY # openssl rand -base64 32
# plus one per enabled provider, e.g.:
STRIPE_SECRET_KEY
STRIPE_WEBHOOK_SECRET
RESEND_API_KEY
GOOGLE_CLIENT_SECRET
GITHUB_CLIENT_SECRETDesplegar el servicio de Cloud Run
Camino por consola: Cloud Run → Create service → Deploy one revision from an existing container image → selecciona la imagen …/supastack/web:latest subida → elige la misma región → en Authentication elige Allow unauthenticated invocations (es una app pública) → Create.
El equivalente CLI de abajo añade el cableado de entorno en el mismo paso. La configuración en texto plano va en --set-env-vars; los secretos se referencian por su nombre de Secret Manager en --set-secrets. Añade tus flags de proveedor (EMAIL_PROVIDER, BILLING_PROVIDER, AI_PROVIDER, JOB_PROVIDER) como variables de entorno normales junto a APP_URL.
APP_ENV=production es obligatorio — sin él la app arranca en modo local: se salta la validación de configuración de producción, los prefijos de cookies seguros quedan desactivados y la página solo-dev /mail-preview sigue siendo accesible públicamente (filtrando la bandeja de salida de correo local cuando EMAIL_PROVIDER=local). La producción exige luego cuatro valores más al arranque: EXPO_PUBLIC_API_URL es la URL https pública que la app móvil usa para llegar a la API — ponla a la URL del servicio (igual que APP_URL en un despliegue solo web); EXPO_PUBLIC_APP_SCHEME es el esquema deep-link de la app móvil — cualquier valor válido como supastack sirve cuando no lanzas app móvil; MOBILE_ALLOWED_ORIGINS es la lista separada por comas de orígenes https exactos en los que el servidor confía — la URL de tu app es el buen comienzo, y los comodines se rechazan; CREDENTIAL_ENCRYPTION_KEY cifra las credenciales de proveedor guardadas y se queda en Secret Manager.
Cloud Run asigna una URL https://….run.app en el primer despliegue, y la APP_URL de la app debe igualar su URL pública real para que los callbacks de autenticación y los enlaces funcionen. Así que despliega una vez con el placeholder, copia la URL *.run.app de la página del servicio y luego actualiza el servicio (consola: Edit & deploy new revision, o vuelve a ejecutar el comando) con APP_URL — y los valores EXPO_PUBLIC_API_URL / MOBILE_ALLOWED_ORIGINS correspondientes — apuntando a ella. El puerto del contenedor sigue siendo 8080 — el valor por defecto de Cloud Run ya coincide con el PORT del Dockerfile.
gcloud run deploy supastack --image us-central1-docker.pkg.dev/YOUR_PROJECT_ID/supastack/web:latest --region us-central1 --allow-unauthenticated --set-env-vars "APP_ENV=production,APP_URL=https://YOUR_SERVICE_URL,EXPO_PUBLIC_API_URL=https://YOUR_SERVICE_URL,EXPO_PUBLIC_APP_SCHEME=supastack,MOBILE_ALLOWED_ORIGINS=https://YOUR_SERVICE_URL" --set-secrets "DATABASE_URL=DATABASE_URL:latest,AUTH_SECRET=AUTH_SECRET:latest,CREDENTIAL_ENCRYPTION_KEY=CREDENTIAL_ENCRYPTION_KEY:latest"Asignar tu propio dominio (opcional)
Sáltate esto mientras pruebas — la URL *.run.app ya sirve HTTPS. Cuando estés listo: Cloud Run → tu servicio → Custom Domains / Domain Mappings → Add mapping → elige el servicio y escribe tu dominio.
Verifica la propiedad del dominio si se te pide (Google te guía), luego crea los registros DNS que la pantalla de asignación lista en tu registrador. El certificado HTTPS gestionado se emite automáticamente cuando los registros se propagan — normalmente minutos, hasta un día.
Cuando el dominio sirva tráfico, actualiza APP_URL a https://yourdomain.com y registra las URI de redirección OAuth correspondientes (https://yourdomain.com/api/auth/callback/…) — las guías de inicio de sesión indican dónde.
Verificar el despliegue
Abre https://YOUR_SERVICE_URL/api/health — espera ok. Luego ejercita la app de punta a punta: abre la URL, regístrate, pide un código de correo, confirma que llega a la bandeja de entrada (eso necesita EMAIL_PROVIDER=resend, RESEND_API_KEY y un remitente verificado — el adaptador local nunca llega a bandejas reales), inicia sesión y usa una función habilitada.
Cloud Run → tu servicio → Logs muestra la salida de peticiones y errores. La pestaña Revisions ofrece rollback con un clic a la revisión anterior si un despliegue sale mal.
Los clientes móvil y escritorio deben apuntar a este backend HTTPS: EXPO_PUBLIC_API_URL en apps/mobile/.env.local para Expo, SUPASTACK_APP_URL para el shell de escritorio.