Skip to main content

Deploy

El backend se deploya en Dokploy; el frontend en Cloudflare Pages. Mismo código, un deploy por entorno.

Backend (Dokploy)

El servicio de pre usa el mismo provider/repo, build type y Dockerfile (auth-panel/dokploy/Dockerfile) que prod. Por entorno solo cambian:

  • Environment variables — ver la matriz de entornos y las de auth.
  • Dominiopupo-pre.anfibia.io (pre) vs pupo.anfibia.io (prod).
  • Branchdev (pre) vs master (prod).

Dominio

  1. Crear un record A para pupo-pre.anfibia.io apuntando a la misma IP del servidor de Dokploy que prod.
  2. En Dokploy → servicio de pre → Domains → agregar pupo-pre.anfibia.io, HTTPS on (Let's Encrypt), Container Port 4700 (el EXPOSE del Dockerfile — el mismo que prod; contenedores separados no colisionan).

Migraciones

El entrypoint corre pnpm migration:up al arrancar → crea/actualiza schemas y tablas en la DB del entorno automáticamente.

GITHUB_TOKEN (build secret)

El Dockerfile instala paquetes privados @cuatro-quinas y lee el token como build secret (--mount=type=secret,id=GITHUB_TOKEN). Tiene que estar cargado en Dokploy como secret de build. El token debe ser un classic PAT con scope read:packages y, si el org usa SSO, autorizado para @cuatro-quinas.

Frontend (Cloudflare Pages)

Un solo proyecto de Pages con el split nativo Production / Preview:

SettingValor
Build commandpnpm build
Build output directorydist
Production branchmaster
Framework presetNone / Vite

Variables de entorno (por environment)

Se cargan por separado para Production y Preview. Las dos VITE_* apuntan al dominio del backend del entorno (en pre, el backend proxya /api/auth):

Preview (dev):

VITE_API_URL = https://pupo-pre.anfibia.io
VITE_AUTH_URL = https://pupo-pre.anfibia.io

Production (master):

VITE_API_URL = https://pupo.anfibia.io
VITE_AUTH_URL = <URL pública del ajolote de prod>

Las VITE_* se hornean en build-time; Cloudflare las inyecta durante el build de cada environment.

Build vars obligatorias (en Production Y Preview)

  • GITHUB_TOKEN — para instalar los paquetes privados @cuatro-quinas (el .npmrc lo pide). Sin esto el build falla en pnpm install.
  • NODE_VERSION=20 — no hay .nvmrc; React 19 + Vite necesitan Node 20+.

Dominios

  • Prod: https://pupo-panel.pages.dev
  • Pre: https://dev.pupo-panel.pages.dev (alias estable de la rama dev)

Troubleshooting

Problemas reales que aparecieron al montar el entorno de pre:

SíntomaCausaSolución
Build Docker: ERR_PNPM_FETCH_401 ... @cuatro-quinasGITHUB_TOKEN inválido/ausente/sin read:packages o SSO no autorizadoRegenerar classic PAT con read:packages (+ autorizar SSO), cargarlo en Dokploy, rebuild sin cache
getaddrinfo ENOTFOUND postgresqldb-rw2aopDB_HOST incompletoUsar el host interno completo: databases-postgresqldb-rw2aop
Cannot find module 'express' (runtime)express era transitiva; pnpm no la resuelve en el node_modules de prodDeclararla como dep directa en package.json
TypeError: cors_1.default is not a functionDefault import de un módulo CJS sin esModuleInteropImportar con import cors = require("cors")
OPTIONS /api/auth/... → 502 + "CORS Missing Allow Origin"El backend estaba caído (crash al boot) → Traefik devuelve 502 sin headers CORSEl 502 es el problema real, no CORS: arreglar el crash del backend (ver filas de arriba)
New Relic requires that you name this applicationFalta NEW_RELIC_APP_NAMESetear NEW_RELIC_APP_NAME=Pupo-pre o NEW_RELIC_ENABLED=false (no es fatal)
tRPC: El proyecto no tiene una URL de afiliado configuradaDB de pre vacía; falta el Project con su affiliateUrlLoguearse como superuser y crear el proyecto con su URL de afiliado (dato local por entorno)
tip

Un 502 en un endpoint casi siempre significa que el contenedor no le dio una respuesta válida a Traefik (caído, puerto mal, o el proxy no alcanza a ajolote). Verificar primero curl -i https://pupo-pre.anfibia.io/health.