Zaroz
Tokens de API

Despliega con GitLab CI y reinicia un servicio

Este ejemplo compila un proyecto Node.js, sube el resultado por SFTP con contraseña y reinicia un servicio de Zaroz Cloud mediante la API. La contraseña SFTP transfiere archivos; un token de API granular e independiente solo controla el reinicio.

Las llamadas usadas son POST /service-instances/{id}/restart y GET /service-instances/{id}/resources de la referencia de la API. Para desplegar una imagen de contenedor en lugar de subir archivos, consulta Despliega desde CI/CD.

Qué necesitas

Desde la página del servicio en la consola, obtén el host, puerto, usuario, contraseña y ruta de destino SFTP.

Crea un token dedicado con estos dos permisos, ambos limitados al servicio exacto (su id de instancia de servicio, como en la URL de la consola). Consulta Tokens de API para ver cómo limitar un token:

  • services.read: permite esperar a que el servidor vuelva.
  • services.power: permite reiniciarlo.

No le des acceso a terminal, facturación, bases de datos ni a todos los servicios.

Añade variables CI/CD protegidas

En GitLab, abre Settings → CI/CD → Variables y añade:

VariableTipoOpciones recomendadas
ZAROZ_API_TOKENVariableMasked, protected
ZAROZ_SERVICE_IDVariableProtected
ZAROZ_SFTP_HOSTVariableProtected
ZAROZ_SFTP_PORTVariableProtected
ZAROZ_SFTP_USERVariableProtected
ZAROZ_SFTP_PATHVariableProtected
ZAROZ_SFTP_PASSWORDVariableMasked, protected
ZAROZ_SFTP_KNOWN_HOSTSFileProtected

Genera ZAROZ_SFTP_KNOWN_HOSTS desde un equipo de confianza y comprueba la huella del host antes de guardarlo. No uses StrictHostKeyChecking=no en producción.

Protege el entorno de despliegue

Las variables protegidas solo se entregan a ramas o tags protegidos. Protege también el entorno de producción para que un merge request no fiable no pueda extraer las credenciales.

Añade .gitlab-ci.yml

El ejemplo espera que npm run build genere dist/. Adapta ambos a tu proyecto.

YAMLCode
stages: - build - deploy build: stage: build image: node:22-alpine script: - npm ci - npm run build artifacts: paths: - dist/ expire_in: 1 hour deploy-production: stage: deploy image: alpine:3.22 needs: - job: build artifacts: true environment: name: production rules: - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' before_script: - apk add --no-cache curl jq lftp openssh-client - install -d -m 700 ~/.ssh - cp "$ZAROZ_SFTP_KNOWN_HOSTS" ~/.ssh/known_hosts - chmod 600 ~/.ssh/known_hosts script: - | export LFTP_PASSWORD="$ZAROZ_SFTP_PASSWORD" lftp -e " set cmd:fail-exit true; set sftp:connect-program \"ssh -a -x -o StrictHostKeyChecking=yes\"; open --env-password --user \"$ZAROZ_SFTP_USER\" -p \"$ZAROZ_SFTP_PORT\" \"sftp://$ZAROZ_SFTP_HOST\"; mirror --reverse --verbose --no-perms dist/ \"$ZAROZ_SFTP_PATH\"; bye " unset LFTP_PASSWORD - | api() { curl --fail-with-body --silent --show-error \ -H "Authorization: Bearer $ZAROZ_API_TOKEN" \ -H 'Accept: application/json' \ "$@" } API="https://kernel.zaroz.cloud/api/v2/service-instances/$ZAROZ_SERVICE_ID" # A restart in place: no stopped state to race against. api -X POST "$API/restart" > /dev/null sleep 5 ready=false for attempt in $(seq 1 30); do state="$(api "$API/resources" | jq -r '.data[] | select(.is_declared_primary) | .status')" echo "Waiting for the server: $state" case "$state" in running) ready=true break ;; failed|crash_looping) echo "The service is $state after the restart" exit 1 ;; esac sleep 2 done if [ "$ready" != true ]; then echo "The service did not come back within about 65 seconds" exit 1 fi echo "Deployment uploaded and service restarted"

Por qué reinicia en el sitio y después espera

restart reinicia el servidor sin pasar por un estado detenido que tu script tendría que observar, así que no hay carrera entre parada y arranque. El reinicio tarda en terminar, por lo que el job lee el estado del recurso principal hasta que es running, y deja un error útil en GitLab si pasa a failed o crash_looping.

Si tu software admite una recarga gradual, prefiérela. Un ciclo de parada y arranque interrumpe a jugadores o usuarios activos.

Adapta la subida

El lote SFTP sobrescribe archivos coincidentes, pero no elimina archivos remotos que ya no estén en dist/. Si necesitas una copia exacta, despliega en directorios versionados y cambia la versión activa desde el script de arranque de tu aplicación.

No subas secretos desde el repositorio. Guárdalos en el panel de Zaroz o como variables CI/CD protegidas.

Solución de problemas

La API devuelve 403

Comprueba que ambos permisos están limitados al UUID de ZAROZ_SERVICE_ID y que el propietario del token aún puede controlar el servicio.

SFTP muestra un error de clave de host

Actualiza ZAROZ_SFTP_KNOWN_HOSTS solo después de verificar la nueva huella por un canal de confianza.

La subida funciona pero el reinicio no

Comprueba que elegiste services.power, además de services.read, y que el token no ha caducado.

El servidor no vuelve a running en aproximadamente un minuto

Deja que el job falle en lugar de reiniciarlo repetidamente. Revisa el servicio en la consola (y sus logs) y reintenta cuando se haya corregido la causa.

Last modified on