diff --git a/scripts/build-push.sh b/scripts/build-push.sh index 72fcd4e..2d44470 100755 --- a/scripts/build-push.sh +++ b/scripts/build-push.sh @@ -1,35 +1,26 @@ #!/usr/bin/env bash -# Cerbero_mcp — build & push image al registry Gitea da macchina locale. -# -# Sostituisce il job CI `build-and-push` di .gitea/workflows/ci.yml. -# Usalo dopo `git push` (o senza, se vuoi pushare un build "dirty"). -# Watchtower sul VPS pulla automaticamente entro WATCHTOWER_POLL_INTERVAL. +# Cerbero MCP — build & push immagine unica V2.0.0 al registry Gitea. # # Pre-requisiti: -# - docker + buildx +# - docker # - PAT Gitea con scope `write:package` in env $GITEA_PAT # - $GITEA_USER (default: adriano) # # Uso: -# ./scripts/build-push.sh # tutte le image -# ./scripts/build-push.sh base gateway # solo specifiche +# ./scripts/build-push.sh +# VERSION=2.0.1 ./scripts/build-push.sh set -euo pipefail REGISTRY="${REGISTRY:-git.tielogic.xyz}" IMAGE_PREFIX="${IMAGE_PREFIX:-$REGISTRY/adriano/cerbero-mcp}" GITEA_USER="${GITEA_USER:-adriano}" +VERSION="${VERSION:-2.0.0}" SHA="$(git rev-parse --short HEAD)" -# Ordine di build: base prima (parent delle mcp-*), poi le altre. -ALL_TARGETS=(base gateway mcp-deribit mcp-bybit mcp-hyperliquid mcp-alpaca mcp-macro mcp-sentiment) -TARGETS=("${@:-${ALL_TARGETS[@]}}") - command -v docker >/dev/null || { echo "FATAL: docker non installato"; exit 1; } -docker buildx version >/dev/null || { echo "FATAL: docker buildx non disponibile"; exit 1; } -# Login solo se non già autenticato sul registry. Per primo login fai: -# echo "" | docker login $REGISTRY -u $GITEA_USER --password-stdin +# Login solo se non già autenticato sul registry. if grep -q "\"$REGISTRY\"" ~/.docker/config.json 2>/dev/null; then echo "=== docker già loggato su $REGISTRY (skip login) ===" elif [ -n "${GITEA_PAT:-}" ]; then @@ -41,50 +32,19 @@ else exit 1 fi -build_one() { - local name="$1" - local context file - case "$name" in - base) - context="."; file="docker/base.Dockerfile" ;; - gateway) - context="./gateway"; file="gateway/Dockerfile" ;; - mcp-*) - context="."; file="docker/${name}.Dockerfile" ;; - *) - echo "FATAL: target sconosciuto '$name'"; exit 1 ;; - esac +TAG_VERSION="$IMAGE_PREFIX:$VERSION" +TAG_LATEST="$IMAGE_PREFIX:latest" +TAG_SHA="$IMAGE_PREFIX:sha-$SHA" - if [ ! -f "$file" ]; then - echo "FATAL: Dockerfile non trovato: $file"; exit 1 - fi +echo "=== build cerbero-mcp:$VERSION ===" +docker build -t "$TAG_VERSION" -t "$TAG_LATEST" -t "$TAG_SHA" . - local tag_latest="$IMAGE_PREFIX/$name:latest" - local tag_sha="$IMAGE_PREFIX/$name:sha-$SHA" - - echo "=== [$name] build & push ===" - local args=(buildx build --push - -f "$file" - -t "$tag_latest" - -t "$tag_sha" - ) - if [[ "$name" == mcp-* ]]; then - args+=(--build-arg "BASE_IMAGE=$IMAGE_PREFIX/base" - --build-arg "BASE_TAG=latest") - fi - args+=("$context") - - docker "${args[@]}" - echo " pushed: $tag_latest" - echo " pushed: $tag_sha" -} - -for t in "${TARGETS[@]}"; do - build_one "$t" +echo "=== push ===" +for tag in "$TAG_VERSION" "$TAG_LATEST" "$TAG_SHA"; do + docker push "$tag" + echo " pushed: $tag" done echo -echo "=== Tutto pushato (commit $SHA) ===" +echo "=== Done (commit $SHA, version $VERSION) ===" echo "VPS Watchtower farà pull entro WATCHTOWER_POLL_INTERVAL (default 5min)." -echo "Per forzare subito:" -echo " ssh 'cd /docker/cerbero_mcp && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d'" diff --git a/scripts/deploy-noclone.sh b/scripts/deploy-noclone.sh deleted file mode 100755 index 22db68b..0000000 --- a/scripts/deploy-noclone.sh +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env bash -# Cerbero_mcp — deploy script per VPS produzione. -# -# Sul VPS NON viene clonato il repo: lo script scarica solo i file -# strettamente necessari al runtime (compose, Caddyfile, public assets) -# via raw HTTP da Gitea. Le image vengono pullate pre-built dal registry -# Gitea (buildate dal laptop dev con scripts/build-push.sh). -# -# Pre-requisiti sul VPS (NON gestiti da questo script): -# 1. Docker Engine ≥ 24 + plugin docker compose installati. -# 2. DNS A record `cerbero-mcp.tielogic.xyz` → IP del VPS (warn-only). -# 3. Porte 80 e 443 aperte sul firewall (per ACME + traffico HTTPS). -# 4. PAT Gitea con scope `read:package`, salvato in env `$GITEA_PAT`. -# 5. Username Gitea in env `$GITEA_USER` (default: adriano). -# 6. Secret JSON exchange + token bearer disponibili in $SECRETS_SRC -# (default: $DEPLOY_DIR/secrets/), che lo script copierà in -# $DEPLOY_DIR/secrets/ con permessi 600 (ignorato se SECRETS_SRC == DEPLOY_DIR/secrets). -# -# Idempotente: rieseguibile per aggiornamenti (riscarica i file di config -# dal branch corrente, NON tocca .env esistente). - -set -euo pipefail - -DEPLOY_DIR="${DEPLOY_DIR:-/docker/cerbero_mcp}" -SECRETS_SRC="${SECRETS_SRC:-$DEPLOY_DIR/secrets}" -GITEA_USER="${GITEA_USER:-adriano}" -GITEA_RAW_BASE="${GITEA_RAW_BASE:-https://git.tielogic.xyz/Adriano/Cerbero-mcp/raw/branch/main}" -REGISTRY="${REGISTRY:-git.tielogic.xyz}" -DOMAIN="${DOMAIN:-cerbero-mcp.tielogic.xyz}" -AUDIT_LOG_DIR="${AUDIT_LOG_DIR:-/var/log/cerbero-mcp}" - -echo "=== Cerbero_mcp deploy (no-clone) → $DEPLOY_DIR (domain $DOMAIN) ===" - -# ────────────────────────────────────────────────────────────── -# 1. Verifica pre-requisiti -# ────────────────────────────────────────────────────────────── -command -v docker >/dev/null || { echo "FATAL: docker non installato"; exit 1; } -command -v curl >/dev/null || { echo "FATAL: curl non installato"; exit 1; } -docker compose version >/dev/null || { echo "FATAL: docker compose plugin assente"; exit 1; } - -if [ -z "${GITEA_PAT:-}" ]; then - echo "FATAL: env GITEA_PAT non settata. Export del PAT con scope read:package prima." - exit 1 -fi - -# Check DNS resolution (warning only, non blocca) -ip_resolved=$(getent hosts "$DOMAIN" | awk '{print $1}' | head -1 || true) -if [ -z "$ip_resolved" ]; then - echo "WARN: $DOMAIN non risolve via DNS — TLS Let's Encrypt fallirà finché DNS non propaga." -else - echo "DNS $DOMAIN → $ip_resolved" -fi - -# ────────────────────────────────────────────────────────────── -# 2. Login al container registry -# ────────────────────────────────────────────────────────────── -echo "=== docker login $REGISTRY ===" -echo "$GITEA_PAT" | docker login "$REGISTRY" -u "$GITEA_USER" --password-stdin - -# ────────────────────────────────────────────────────────────── -# 3. Setup dir + scarica i file di config dal repo (no clone) -# ────────────────────────────────────────────────────────────── -sudo mkdir -p "$DEPLOY_DIR" -sudo chown "$USER:$USER" "$DEPLOY_DIR" -mkdir -p "$DEPLOY_DIR/secrets" "$DEPLOY_DIR/gateway/public" - -# File di config necessari al runtime. Scaricati come raw da Gitea. -# Idempotente: ricarica sempre la versione di main. -download() { - local rel="$1" - local dst="$DEPLOY_DIR/$rel" - echo " fetch: $rel" - curl -fsSL -o "$dst" "$GITEA_RAW_BASE/$rel" \ - || { echo "FATAL: download $rel fallito"; exit 1; } -} - -echo "=== Download config da $GITEA_RAW_BASE ===" -download docker-compose.prod.yml -download docker-compose.traefik.yml -download gateway/Caddyfile -download gateway/public/index.html -download gateway/public/status.js -download gateway/public/style.css - -cd "$DEPLOY_DIR" - -# ────────────────────────────────────────────────────────────── -# 4. Copia secrets con permessi 600 -# ────────────────────────────────────────────────────────────── -if [ "$(realpath "$SECRETS_SRC")" != "$(realpath "$DEPLOY_DIR/secrets")" ]; then - if [ ! -d "$SECRETS_SRC" ]; then - echo "FATAL: secrets src dir $SECRETS_SRC non esiste." - echo " Atteso contenere: deribit.json bybit.json hyperliquid.json alpaca.json" - echo " macro.json sentiment.json core.token observer.token" - exit 1 - fi - echo "=== Copia secrets da $SECRETS_SRC ===" - for f in deribit.json bybit.json hyperliquid.json alpaca.json macro.json sentiment.json core.token observer.token; do - if [ -f "$SECRETS_SRC/$f" ]; then - cp "$SECRETS_SRC/$f" "secrets/$f" - chmod 600 "secrets/$f" - echo " ok: secrets/$f" - else - echo " WARN: $SECRETS_SRC/$f assente — il servizio relativo fallirà al boot." - fi - done -else - echo "=== Secrets già in $DEPLOY_DIR/secrets — solo chmod 600 ===" - for f in deribit.json bybit.json hyperliquid.json alpaca.json macro.json sentiment.json core.token observer.token; do - [ -f "secrets/$f" ] && chmod 600 "secrets/$f" && echo " ok: secrets/$f" \ - || echo " WARN: secrets/$f assente — il servizio relativo fallirà al boot." - done -fi - -# ────────────────────────────────────────────────────────────── -# 5. Crea/aggiorna .env (preserva esistente) -# ────────────────────────────────────────────────────────────── -if [ ! -f .env ]; then - echo "=== Creazione .env iniziale (testnet di default) ===" - cat > .env <" -echo " Audit: tail -f $AUDIT_LOG_DIR/*.audit.jsonl" -echo " Restart: docker compose ${COMPOSE_FILES[*]} --env-file .env restart " -echo " Stop: docker compose ${COMPOSE_FILES[*]} --env-file .env down" -echo " Update: ri-esegui questo script (riscarica config + pull image)"