Despliegue
Al terminar esta página tendrás el sitio corriendo en Cloudflare contra la D1 y el R2 remotos, con el
/admin accesible y el correo saliendo de verdad, y cada push desplegando solo.
Antes de empezar
Sección titulada «Antes de empezar»cms deploy crea el repositorio en GitHub por ti, así que tu máquina necesita tres cosas. Las
comprueba él antes de tocar nada, pero llegar preparado ahorra un viaje:
ghygitinstalados.brew install gh(macOS),winget install --id GitHub.cli(Windows), o el resto en cli/cli.- Sesión de GitHub iniciada:
gh auth login, ygh auth statuspara confirmarlo. - Lanzarlo sin
GITHUB_TOKENen el entorno. La instalación te hizo exportar esa variable para que npm bajara el paquete del registro privado, yghla prefiere sobre su propio llavero: mientras esté puesta,ghno se autentica aunque tu sesión esté perfecta. De ahí elenv -u GITHUB_TOKENde abajo — o unGH_TOKENcon permisorepo, si prefieres. La salida larga está en Solución de problemas.
env -u GITHUB_TOKEN pnpm cms deployQué hace cms deploy
Sección titulada «Qué hace cms deploy»En este orden, y el orden es media página:
-
El diagnóstico de
cms doctorcomo puerta. Los avisos no paran nada; un solo check en rojo sí, porque desplegar con él solo llevaría el problema a producción. -
Comprueba que ningún binding se haya quedado sin id —ausente, vacío o el marcador de posición—. Si alguno lo está, manda a
cms resources:createy no toca nada. -
Comprueba el
.npmrc, antes de tocar git. Es lectura de fichero pura: si falta el registro o si lleva un token escrito dentro, aborta sin haber lanzado ni un proceso. -
Comprueba que
ghygitestén y que haya sesión de GitHub iniciada. También aquí, antes de migrar nada. -
Aplica las migraciones remotas (
cms db:apply --remote), desde tu máquina. -
Crea el repositorio en GitHub con
gh, commitea lo que haya suelto y empuja. Justo después delgit init, y solo ahí, comprueba que el.npmrcno esté ignorado por git: es lo único que git no puede contestar antes de que el repositorio exista. -
Abre el dashboard y escribe en la terminal los cuatro clics que quedan.
Los cuatro clics
Sección titulada «Los cuatro clics»Es lo que el comando imprime al terminar, y hay que hacerlo una sola vez por proyecto:
-
Abre el dashboard y pulsa «Create» → «Import a repository». Elige el repositorio que se acaba de crear.
-
Build command:
pnpm build— Deploy command:npx wrangler deploy. -
En «Build variables and secrets» añade
GITHUB_TOKENcomo secret de build, con permisoread:packages: sin él el build falla con un401al instalar@kevolution-co/cms. -
El Worker en Cloudflare tiene que llamarse exactamente como el
namede tuwrangler.jsonc. Con otro nombre, Cloudflare crea un Worker distinto y los bindings de ese fichero no apuntan a nada.
Por qué ese paso es manual
Sección titulada «Por qué ese paso es manual»Conectar un repositorio con Workers Builds es una GitHub App con OAuth: no hay API ni CLI que lo
haga, así que no se puede automatizar y no tiene sentido disimularlo. Está pedido en
cloudflare/workers-sdk#12058. Lo que sí se
puede hacer por ti —el repositorio, el push, las migraciones, el diagnóstico— lo hace cms deploy.
El .npmrc va commiteado
Sección titulada «El .npmrc va commiteado»Este es el fichero que sí entra en el repositorio, al revés que casi todo lo que se le parece. El
builder de Cloudflare instala @kevolution-co/cms desde un registro privado, en una máquina que no es
la tuya, y sin ese fichero no sabe a dónde ir:
@kevolution-co:registry=https://npm.pkg.github.com//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}${GITHUB_TOKEN} es texto literal: lo expande npm al leer el fichero, y el valor sale del secret de
build del paso 3. El token nunca se escribe ahí.
Y el fallo simétrico: si tu .gitignore ignora el .npmrc, nunca llegará al repositorio y el build
caerá con un 401. cms doctor lo avisa con el check npmrc-ignored —en amarillo, así que no
bloquea nada por su cuenta— y cms deploy para.
Pero para más tarde que los otros dos casos, y conviene saberlo: git no sabe contestar
check-ignore hasta que el repositorio existe, así que esa comprobación vive después del git init,
con las migraciones remotas ya aplicadas. Si te sale este error, tu D1 de producción ya está
migrada y tienes un .git/ recién creado en el directorio; quita la línea .npmrc del .gitignore
y vuelve a ejecutar cms deploy, que a partir de ahí es idempotente.
El secreto de sesión
Sección titulada «El secreto de sesión».dev.vars es solo local: wrangler no lo sube en el deploy y el fichero está en tu .gitignore.
En producción, BETTER_AUTH_SECRET se guarda como secreto del Worker:
pnpm cms secret:set --remoteGenera uno nuevo con randomBytes(32) y se lo entrega a wrangler por la entrada estándar, así que
no queda en la tabla de procesos ni en el historial del shell, y el valor no se imprime. Lo cifra
la cuenta de Cloudflare; no queda en ningún fichero del repositorio.
Rotarlo invalida todas las sesiones abiertas —hay que volver a entrar en /admin—, que es
exactamente lo que quieres si sospechas que se filtró.
Sin ese secreto el Worker despliega, pero la autenticación no funciona: /admin responde 500. Los
detalles, en Autenticación.
La regla de orden
Sección titulada «La regla de orden»cms db:apply --remote desde tu máquina, antes de empujar — que es justo lo que cms deploy hace
por ti— y nunca en el build command de Cloudflare.
Con Workers Builds el despliegue lo dispara el push, así que no hay un «antes del deploy» que ejecutar desde el builder: lo que hay es un antes del push. Y meterlo en el build command por comodidad tiene tres problemas, cada uno suficiente:
- No está verificado que el token que Cloudflare inyecta en el builder pueda editar D1.
- Un fallo a mitad de build deja el Worker desplegado contra un esquema que no existe, y cada
lectura de esa colección responde
500hasta que alguien se da cuenta. - El build es exactamente el sitio donde una confirmación sin TTY se acepta sin que nadie mire:
db:apply --remoteno pregunta cuando no hay terminal. Ver CLI.
La consecuencia operativa es la que se olvida: cada cambio de esquema es un cms db:apply --remote
antes del push siguiente, o un cms deploy otra vez.
Qué cambia respecto a local
Sección titulada «Qué cambia respecto a local»-
D1 y R2 son otros. La base y el bucket con los que trabaja
wrangler devson copias locales que viven en.wrangler/, no los recursos quecms init --cloud—ocms resources:create— creó en tu cuenta. El contenido que escribiste probando no viaja: la instalación remota arranca vacía y/adminte enseña otra vez el asistente de configuración, con su primera cuenta y sus ajustes del sitio.Por eso
db:applytiene dos modos: sin flag toca la copia local, con--remotela de verdad. -
El correo sale de verdad. En local,
wrangler devsimula el envío y vuelca el mensaje a un fichero temporal cuya ruta imprime; no hace falta dominio ni plan de pago. Desplegado no hay simulación que valga, así que los tres requisitos de plataforma tienen que estar cumplidos —plan Workers de pago, dominio con DNS de Cloudflare dado de alta en Email Sending, y unfromde ese dominio— o el envío falla.El flag
"remote": truedel bindingsend_emailno es para producción: es lo que hace que tu máquina deje de simular y mande correo real desdewrangler dev, con esos mismos tres requisitos ya cumplidos. Sirve para ver cómo queda el mensaje en clientes reales; déjalo fuera mientras desarrolles. -
La URL pública cambia. El ajuste
siteUrlque guardaste desde local apunta alocalhost:4321, y es de ahí de donde salen los enlaces de verificación y restablecimiento de los correos. En la instalación remota lo pone el asistente; si lo cambias después, se edita desde/admin/settingssin desplegar. Si te deja fuera del panel,cms settings:reset-site-url --remotelo borra.
Si algo falla
Sección titulada «Si algo falla»Los fallos de un primer despliegue —el 401 del builder, el Worker que no es el tuyo, /admin
respondiendo 500, nodejs_compat que falta, migraciones que wrangler no encuentra— están recogidos
por síntoma en Solución de problemas.