Saltar al contenido
cloud-webv0.1.0
Documentación

Tu primer deploy

1. Configurar GitLab (una vez)

cloud-web funciona con gitlab.com o con una instancia self-hosted.

  1. En GitLab: Preferences → Applications → Add new application. Scope api. Redirect URI: la que muestra Ajustes en el dashboard (http://<host>:8080/api/auth/callback).
  2. En el dashboard entrá con el token de administrador (/var/lib/cloudweb/admin.token): en una instancia nueva el formulario ya está a la vista; si ya hay un proveedor configurado, está oculto y se muestra escribiendo admin en la pantalla de acceso (o abriendo /?admin). Abrí Ajustes y completá la URL de GitLab, el Application ID y el Secret. Para una instancia self-hosted con TLS interno pegá también su CA (PEM). El servidor valida que la URL sea alcanzable antes de guardar.
  3. Abrí el enlace de setup que imprimió el instalador (/var/lib/cloudweb/setup.link) y entrá con GitLab: esa cuenta es la administradora. El enlace es de un solo uso y las demás cuentas no pueden registrarse.

Tu instancia de GitLab debe poder alcanzar el dashboard para entregar los webhooks de push.

2. Desplegar un proyecto

  1. Apps → Nueva app: buscá el proyecto (sólo aparecen los que tienen rol Developer o superior), elegí el branch y, si hace falta, el directorio raíz.
  2. cloud-web construye la imagen con el Dockerfile del proyecto; si no hay, primero mira si es un sitio estático (ver abajo) y, si no, detecta el lenguaje (Node.js, Python, Go, Java, Ruby, PHP, .NET) y usa Cloud Native Buildpacks. Si no puede decidir, el despliegue falla con un mensaje que explica las opciones.
  3. La app queda en https://<app>.<dominio-base> con certificado automático.

Cada push al branch configurado crea un despliegue nuevo, y el estado (pending, running, success, failed) aparece en el commit de GitLab. Si el nuevo despliegue falla, la versión anterior sigue sirviendo.

Sitios estáticos (Vite, React, Vue, Angular, Astro, Gatsby, HTML…)

Un sitio que se compila a archivos estáticos no necesita Dockerfile ni servidor. Se detecta solo cuando, sin Dockerfile:

  • el package.json tiene un script build, no tiene script start (ni hay Procfile) y depende de un framework conocido: vite, react-scripts, @vue/cli-service, @angular/cli, astro, gatsby, @docusaurus/core, @11ty/eleventy, parcel o vuepress; o
  • hay un index.html en la raíz y no hay package.json (se sirve tal cual).

Lo que se hace: se instalan las dependencias respetando tu lockfile (npm ci, pnpm install --frozen-lockfile, yarn install --immutable), se compila con la versión de Node que pidas en .nvmrc, .node-version o engines.node (por omisión, la 22) y se sirve el resultado (la carpeta dist, build, public… según el framework) con un servidor que escucha en PORT, comprime, no lista directorios y no cachea el HTML (un despliegue nuevo se ve enseguida; solo los archivos con huella en el nombre se cachean un año). En una SPA, una ruta como /perfil/ana devuelve tu index.html; un archivo que no existe devuelve 404 y no esconde la referencia rota.

  • Un servidor Node (con script start o Procfile, o con server.js) no se confunde con un sitio: sigue por buildpacks. Un Dockerfile siempre manda.
  • Variables de entorno: al compilar solo se usan las que empiezan con VITE_, REACT_APP_, NEXT_PUBLIC_, PUBLIC_ o GATSBY_. Terminan dentro del sitio publicado, visible para cualquier visitante: no pongas secretos ahí. El resto de tus variables no entra al build.
  • Ajustes avanzados (al crear la app o en su detalle, Cómo se construye): comando de instalación, comando de build, directorio de salida y tipo de sitio (SPA o varias páginas). Solo hacen falta si la detección no alcanza, por ejemplo con un framework que no está en la lista: declarar un comando de build y un directorio de salida lo trata como estático.
  • Si falla, el log y el mensaje dicen qué pasó: sin script build, lockfile desactualizado, comando de build fallido, sin carpeta de salida (con las que se buscaron), o límite de memoria o de tiempo.
  • El detalle de la app muestra con qué se construyó el último despliegue (Dockerfile, sitio estático o buildpacks).

Los nodos necesitan un agente 0.3 o posterior para construir un sitio con ajustes explícitos; con un agente anterior el despliegue falla diciendo qué nodos actualizar.

3. Variables de entorno, logs y rollback

  • Variables: se guardan cifradas y no se muestran nunca; se aplican en el próximo despliegue. Tu app debe escuchar en $PORT (se detecta el puerto del EXPOSE, o 8080).
  • Logs: Logs en la app abre su pantalla de logs: el build y la ejecución en vivo (con pausa), filtro por tipo, buscador y descarga. Los valores de tus variables se enmascaran como ***. Se conservan las últimas 5.000 líneas de cada despliegue y los logs de despliegues terminados se borran a los 14 días (descargalos si los necesitás más tiempo).
  • Monitoreo: Monitoreo en el menú muestra tu cuenta contra sus límites y, por app, su estado, CPU, memoria y tráfico (pedidos, errores y tiempos de respuesta; nunca direcciones ni rutas de tus visitantes).
  • Rollback: en cualquier despliegue anterior exitoso, sin recompilar.
  • Ramas: una app despliega su rama principal y, si querés, otras. En la app, Ramas → Vincular otra rama (se elige entre las del repositorio). Cada rama vinculada tiene su propio despliegue en ejecución, su historial, sus logs, su redeploy y su rollback, y se sirve en https://<app>--<rama>.<dominio base> (la principal sigue en <app>.<dominio base>). Un push a una rama que no vinculaste no despliega nada. El nombre de la rama se normaliza para la dirección (feature/Login → feature-login); si dos ramas darían la misma dirección, la segunda se rechaza. Las variables de entorno y los ajustes de build son de la app y se comparten entre ramas. Desvincular detiene el despliegue de esa rama y deja de servirla, pero conserva el historial y sus dominios; la rama principal no se desvincula. Una cuenta común puede vincular hasta 3 ramas por app (contando la principal; lo ajusta el operador).
  • Dominio propio: en la app, Dominios → Agregar dominio; el dashboard muestra los registros DNS a crear y el dominio se activa cuando el DNS apunta al clúster.
    • Subdominio (www.tudominio.com): un CNAME al nombre que muestra el dashboard (el de ingress de la plataforma, p. ej. ingress.zondacloud.com, o el host de la app si el operador no configuró uno).
    • Dominio raíz (tudominio.com): un CNAME no es válido en la raíz de una zona. Usá un registro A a las IPs que muestra el dashboard, o un ALIAS/ANAME al mismo nombre si tu proveedor lo ofrece.
    • Una rama por dominio: con varias ramas vinculadas, al agregar el dominio elegís cuál lo sirve (por omisión la principal) y podés moverlo después sin volver a verificarlo. Si la rama se desvincula, el dominio queda marcado y no se sirve hasta que la vincules de nuevo o lo muevas a otra.
    • No se pueden usar nombres que ya usa la plataforma: nada bajo el dominio base (apps ni infraestructura) ni el nombre de ingress. El formulario lo explica antes de enviar.
    • Si una dirección de ingress no es alcanzable desde internet (IP privada o de CGNAT), el dashboard lo avisa: sin eso no se puede emitir el certificado.