#!/usr/bin/env bash # setup_registry_api — Deploy completo de registry_api en VPS con Docker + Traefik (Coolify proxy) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REGISTRY_ROOT="$(cd "$SCRIPT_DIR/../../../../" && pwd)" source "$SCRIPT_DIR/rsync_deploy.sh" setup_registry_api() { local ssh_host="${1:-organic-machine.com}" local api_token="${2:-}" local basic_auth_user="${3:-lucas}" local basic_auth_pass="${4:-}" if [[ -z "$api_token" ]]; then echo "setup_registry_api: REGISTRY_API_TOKEN es obligatorio (parametro 2)" >&2 return 1 fi if [[ -z "$basic_auth_pass" ]]; then echo "setup_registry_api: basic_auth_pass es obligatorio (parametro 4)" >&2 return 1 fi local start_ts start_ts=$(date +%s) # 1. Verificar conectividad SSH echo "==> [1/7] Verificando conectividad SSH a '$ssh_host'..." >&2 if ! ssh -o BatchMode=yes -o ConnectTimeout=10 "$ssh_host" true 2>/dev/null; then echo "setup_registry_api: no se puede conectar a '$ssh_host' via SSH" >&2 return 1 fi echo " OK: SSH conectado." >&2 # 2. Generar hash bcrypt para basicAuth de Traefik echo "==> [2/7] Generando hash bcrypt para basicAuth..." >&2 if ! command -v htpasswd &>/dev/null; then echo "setup_registry_api: 'htpasswd' no encontrado. Instalar con: apt install apache2-utils" >&2 return 1 fi local traefik_hash traefik_hash=$(htpasswd -nbB "$basic_auth_user" "$basic_auth_pass" 2>/dev/null) if [[ -z "$traefik_hash" ]]; then echo "setup_registry_api: htpasswd no generó un hash válido" >&2 return 1 fi # For Traefik file provider, use single $ (NOT $$ — that's only for Docker labels) echo " OK: hash generado para usuario '$basic_auth_user'." >&2 # 3. Subir el repo completo al VPS via rsync (el Dockerfile necesita el contexto completo) local remote_build_dir="/opt/fn-registry-build" echo "==> [3/7] Sincronizando repo a '$ssh_host:$remote_build_dir' via rsync..." >&2 rsync_deploy "$REGISTRY_ROOT/" "$ssh_host" "$remote_build_dir" >/dev/null || { echo "setup_registry_api: rsync falló" >&2 return 1 } echo " OK: repo sincronizado." >&2 # 4. Subir traefik-dynamic.yml con el hash real a la ruta de Coolify local traefik_dynamic_path="/data/coolify/proxy/dynamic/registry-api-organic-machine-com.yml" echo "==> [4/7] Generando y subiendo traefik-dynamic.yml a '$ssh_host:$traefik_dynamic_path'..." >&2 # Leer el template local y sustituir el placeholder local traefik_template traefik_template=$(< "$REGISTRY_ROOT/apps/registry_api/traefik-dynamic.yml") # Reemplazar la línea del usuario placeholder con el hash real local traefik_rendered traefik_rendered=$(echo "$traefik_template" | sed "s|.*PLACEHOLDER_BASICAUTH_LINE.*| - \"${traefik_hash}\"|g") # Crear directorio si no existe y subir ssh "$ssh_host" "sudo mkdir -p /data/coolify/proxy/dynamic/" >&2 echo "$traefik_rendered" | ssh "$ssh_host" \ "sudo tee '$traefik_dynamic_path' > /dev/null" echo " OK: traefik-dynamic.yml desplegado en '$traefik_dynamic_path'." >&2 # 5. Crear .env en el VPS con el token de la API local remote_app_dir="$remote_build_dir/apps/registry_api" echo "==> [5/7] Creando .env en '$ssh_host:$remote_app_dir'..." >&2 ssh "$ssh_host" "cat > '$remote_app_dir/.env'" <&2 # 6. Verificar que la red coolify existe; si no, crearla echo "==> [6/7] Verificando red Docker 'coolify' y levantando el stack..." >&2 ssh "$ssh_host" bash <<'REMOTE' set -euo pipefail if ! docker network ls --format '{{.Name}}' | grep -q '^coolify$'; then echo " Creando red Docker 'coolify'..." docker network create coolify fi echo " Red 'coolify' disponible." REMOTE # docker compose build && up desde el directorio de la app (contexto es ../../ = remote_build_dir) ssh "$ssh_host" bash <&2 # 7. Health check local health_url="https://registry.organic-machine.com/api/status" echo "==> [7/7] Esperando health check en '$health_url'..." >&2 local attempts=0 local max_attempts=12 local status_code="" while [[ $attempts -lt $max_attempts ]]; do status_code=$(curl -sk -o /dev/null -w "%{http_code}" \ -u "${basic_auth_user}:${basic_auth_pass}" \ "$health_url" 2>/dev/null || echo "000") if [[ "$status_code" == "200" ]]; then break fi attempts=$((attempts + 1)) echo " Intento $attempts/$max_attempts — HTTP $status_code, esperando 10s..." >&2 sleep 10 done local end_ts end_ts=$(date +%s) local duration_ms=$(( (end_ts - start_ts) * 1000 )) if [[ "$status_code" != "200" ]]; then printf '{"status":"error","url":"%s","http_code":"%s","duration_ms":%d,"msg":"health check timeout tras %d intentos"}\n' \ "$health_url" "$status_code" "$duration_ms" "$max_attempts" return 1 fi echo " OK: servicio respondiendo HTTP 200." >&2 printf '{"status":"ok","url":"%s","http_code":"%s","duration_ms":%d,"ssh_host":"%s","remote_dir":"%s"}\n' \ "$health_url" "$status_code" "$duration_ms" "$ssh_host" "$remote_app_dir" } if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then # Uso: setup_registry_api.sh [ssh_host] [api_token] [basic_auth_user] [basic_auth_pass] # Variables de entorno alternativas: SSH_HOST, REGISTRY_API_TOKEN, BASIC_AUTH_USER, BASIC_AUTH_PASS setup_registry_api \ "${1:-${SSH_HOST:-organic-machine.com}}" \ "${2:-${REGISTRY_API_TOKEN:-}}" \ "${3:-${BASIC_AUTH_USER:-lucas}}" \ "${4:-${BASIC_AUTH_PASS:-}}" fi