chore(deploy): build locale + deploy no-clone, rimuovi CI Gitea
- scripts/build-push.sh: replica job CI in locale (8 image, cache buildx, tag :latest + :sha-X) - scripts/deploy-noclone.sh: deploy VPS senza clone (curl raw config + image pull) - rimossa .gitea/workflows/ci.yml - README + DEPLOYMENT aggiornati: laptop -> registry -> VPS, paths /docker/cerbero_mcp - ruff fix su 3 test (I001, SIM117, UP037, F821) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+107
-78
@@ -1,66 +1,71 @@
|
||||
# Deployment Cerbero_mcp
|
||||
|
||||
Guida operativa per il deploy della suite MCP su un VPS pubblico.
|
||||
L'architettura è: Gitea ospita codice + container registry; il VPS produzione
|
||||
non builda nulla, ma fa pull dei container già pronti dalla registry e usa
|
||||
Watchtower per il rollover automatico delle versioni.
|
||||
L'architettura è: Gitea ospita codice + container registry; le immagini
|
||||
vengono buildate e pushate dalla **macchina di sviluppo** (laptop) verso
|
||||
il registry; il VPS produzione non builda nulla, fa solo pull dei
|
||||
container già pronti e usa Watchtower per il rollover automatico.
|
||||
|
||||
```
|
||||
┌─────────────────────────┐ ┌──────────────────────────────────┐
|
||||
│ Gitea git.tielogic.xyz │ │ VPS produzione │
|
||||
│ │ │ cerbero-mcp.tielogic.xyz │
|
||||
│ ┌──────────────────┐ │ push │ │
|
||||
│ │ Cerbero-mcp repo │───┼─CI/CD──▶│ ┌────────────────────────────┐ │
|
||||
│ └──────────────────┘ │ image │ │ docker compose │ │
|
||||
│ ┌──────────────────┐ │ │ │ (docker-compose.prod.yml) │ │
|
||||
│ │ Container reg. │◀──┼─ pull ──┤ │ gateway, mcp-* │ │
|
||||
│ └──────────────────┘ │ │ │ watchtower (poll 5min) │ │
|
||||
│ ┌──────────────────┐ │ │ └────────────────────────────┘ │
|
||||
│ │ Actions runner │ │ │ │
|
||||
│ └──────────────────┘ │ │ │
|
||||
└─────────────────────────┘ └──────────────────────────────────┘
|
||||
┌──────────────────────────┐ ┌─────────────────────────┐ ┌──────────────────────────────────┐
|
||||
│ Laptop dev │ │ Gitea git.tielogic.xyz │ │ VPS produzione │
|
||||
│ │ │ │ │ cerbero-mcp.tielogic.xyz │
|
||||
│ build-push.sh ──push──▶ │───▶│ ┌────────────────────┐ │ │ │
|
||||
│ (8 image) │ │ │ Container registry │ │ │ ┌────────────────────────────┐ │
|
||||
│ git push ─────────────▶ │───▶│ └────────────────────┘ │◀──┼──┤ docker compose │ │
|
||||
│ │ │ ┌────────────────────┐ │ pull │ (docker-compose.prod.yml) │ │
|
||||
│ │ │ │ Cerbero-mcp repo │ │ │ │ gateway, mcp-* │ │
|
||||
│ │ │ └────────────────────┘ │ │ │ watchtower (poll 5min) │ │
|
||||
│ │ │ │ │ └────────────────────────────┘ │
|
||||
└──────────────────────────┘ └─────────────────────────┘ └──────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 1. Pipeline CI/CD (Gitea Actions)
|
||||
Niente CI/CD su Gitea — qualità e build sono responsabilità del laptop
|
||||
prima del push (lint/test in locale, poi `scripts/build-push.sh`).
|
||||
|
||||
`.gitea/workflows/ci.yml` ad ogni push su `main` esegue 5 job:
|
||||
## 1. Build & push image (dal laptop)
|
||||
|
||||
1. **lint** (`ruff check services/`) — gating, 0 violations.
|
||||
2. **typecheck** (`mypy services/common/src/mcp_common`) — gating sul
|
||||
modulo comune, warn-only sui servizi.
|
||||
3. **test** (`pytest services/`) — gating, 478 test verdi.
|
||||
4. **validate-config** — `docker compose config -q` su `docker-compose.yml`
|
||||
e `docker-compose.prod.yml` + `caddy validate --config Caddyfile`.
|
||||
5. **build-and-push** — solo su push a `main` (skip su PR):
|
||||
- `docker login git.tielogic.xyz` con `${{ secrets.REGISTRY_TOKEN }}`
|
||||
(PAT scope `write:package`, configurato user-level su Gitea).
|
||||
- Builda e pusha **8 image** al registry con tag `:latest` + `:sha-X`:
|
||||
- `git.tielogic.xyz/adriano/cerbero-mcp/base`
|
||||
- `git.tielogic.xyz/adriano/cerbero-mcp/gateway`
|
||||
- `git.tielogic.xyz/adriano/cerbero-mcp/mcp-{deribit,bybit,hyperliquid,alpaca,macro,sentiment}`
|
||||
- Cache Docker buildx via registry stesso (`buildcache:<name>` per ognuna)
|
||||
→ run successivi 5-10× più veloci.
|
||||
Lo script `scripts/build-push.sh` builda e pusha le 8 image al registry
|
||||
Gitea, replicando il vecchio job CI ma in locale. Pre-requisiti:
|
||||
|
||||
Le PR fanno girare solo `lint`+`typecheck`+`test`+`validate-config`,
|
||||
niente build/push (gating per merge).
|
||||
- `docker` + `buildx` sul laptop.
|
||||
- Personal Access Token Gitea con scope `write:package` (User Settings
|
||||
→ Applications → Generate Token).
|
||||
|
||||
### Setup runner Gitea
|
||||
```bash
|
||||
export GITEA_PAT='<PAT_write:package>'
|
||||
export GITEA_USER=adriano
|
||||
|
||||
Il runner act_runner deve girare:
|
||||
- Sulla stessa Docker network di Gitea (`gitea_gitea-internal` o equivalente)
|
||||
altrimenti `actions/checkout@v4` non risolve `gitea:3000` per il clone.
|
||||
- Con bind di `/var/run/docker.sock` per buildare image dai workflow.
|
||||
- Image dei job mappata a `docker.gitea.com/runner-images:ubuntu-22.04`
|
||||
(default Gitea, contiene docker CLI + buildx + git + curl + node).
|
||||
- Label: almeno `ubuntu-latest` (usato dal workflow). Altre label
|
||||
(`tielogic-ci`, `ubuntu-22.04`, ecc.) opzionali.
|
||||
# Tutte le 8 image (base + gateway + 6 mcp-*)
|
||||
./scripts/build-push.sh
|
||||
|
||||
### Setup secret REGISTRY_TOKEN
|
||||
# Solo specifiche (es. dopo modifica a un singolo servizio)
|
||||
./scripts/build-push.sh base mcp-bybit
|
||||
```
|
||||
|
||||
Crea un Personal Access Token Gitea con scope `write:package` (User
|
||||
Settings → Applications → Generate Token). Aggiungilo come secret a
|
||||
livello user (User Settings → Secrets → New Secret) con nome
|
||||
`REGISTRY_TOKEN`. Tutti i tuoi repo ereditano il secret automaticamente.
|
||||
Lo script:
|
||||
- Fa `docker login git.tielogic.xyz`.
|
||||
- Builda con `docker buildx build --push` (cache via registry stesso,
|
||||
`buildcache:<name>` per ognuna → build successivi 5-10× più veloci).
|
||||
- Tagga `:latest` + `:sha-<short_HEAD>`.
|
||||
- Per le mcp-* passa `BASE_IMAGE`/`BASE_TAG` come build-arg in modo da
|
||||
ereditare dall'image `base` appena pushata.
|
||||
|
||||
Ordine consigliato: builda `base` prima delle `mcp-*` (lo script lo fa
|
||||
di default se chiamato senza argomenti).
|
||||
|
||||
## 1b. Quality gate locale (consigliato prima del push)
|
||||
|
||||
Prima di `build-push.sh` esegui in locale i check che prima girava il CI:
|
||||
|
||||
```bash
|
||||
uv run ruff check services/
|
||||
uv run mypy services/common/src/mcp_common
|
||||
uv run pytest services/ --tb=short
|
||||
docker compose -f docker-compose.prod.yml config -q
|
||||
```
|
||||
|
||||
Tutti devono essere verdi prima di pushare image al registry.
|
||||
|
||||
## 2a. Topologia: standalone vs behind-Traefik
|
||||
|
||||
@@ -89,34 +94,47 @@ Caddy non bind su host, ascolta plain HTTP `:80` interno alla
|
||||
`traefik` network. Traefik fa routing per `Host(cerbero-mcp.tielogic.xyz)`,
|
||||
TLS, ACME. Adatto a VPS condiviso con altri servizi (Gitea, ecc.).
|
||||
|
||||
## 2. Deploy automatizzato (script)
|
||||
## 2. Deploy automatizzato (script no-clone)
|
||||
|
||||
Il modo più rapido è `scripts/deploy.sh`, idempotente. Esegui sul VPS:
|
||||
Il modo più rapido è `scripts/deploy-noclone.sh`, idempotente. Sul VPS
|
||||
**non** viene clonato il repo: lo script scarica via raw HTTP solo i
|
||||
file strettamente necessari al runtime (compose, Caddyfile, public
|
||||
assets). Esegui sul VPS:
|
||||
|
||||
```bash
|
||||
# Prerequisiti
|
||||
export GITEA_PAT="<PAT con scope read:package>"
|
||||
export GITEA_USER=adriano
|
||||
mkdir -p ~/cerbero-secrets
|
||||
# Copia (via scp dal posto sicuro) i secret in ~/cerbero-secrets/:
|
||||
# deribit.json bybit.json hyperliquid.json alpaca.json
|
||||
# macro.json sentiment.json core.token observer.token
|
||||
|
||||
# Clone temporaneo solo per lo script
|
||||
curl -sL -o /tmp/deploy.sh \
|
||||
https://git.tielogic.xyz/Adriano/Cerbero-mcp/raw/branch/main/scripts/deploy.sh
|
||||
chmod +x /tmp/deploy.sh
|
||||
# Crea la dir di deploy e mettici i secrets via scp dal posto sicuro
|
||||
sudo mkdir -p /docker/cerbero_mcp/secrets
|
||||
sudo chown -R "$USER" /docker/cerbero_mcp
|
||||
# scp deribit.json bybit.json hyperliquid.json alpaca.json \
|
||||
# macro.json sentiment.json core.token observer.token \
|
||||
# vps:/docker/cerbero_mcp/secrets/
|
||||
|
||||
# Run (richiede sudo per /opt/cerbero-mcp e /var/log/cerbero-mcp)
|
||||
/tmp/deploy.sh
|
||||
# Behind Traefik (opzionale, solo se VPS condiviso con Gitea o altri)
|
||||
# export BEHIND_TRAEFIK=true
|
||||
# export TRAEFIK_NETWORK=gitea_traefik-public
|
||||
|
||||
curl -sL -o /tmp/deploy-noclone.sh \
|
||||
https://git.tielogic.xyz/Adriano/Cerbero-mcp/raw/branch/main/scripts/deploy-noclone.sh
|
||||
chmod +x /tmp/deploy-noclone.sh
|
||||
/tmp/deploy-noclone.sh
|
||||
```
|
||||
|
||||
Lo script esegue: docker login registry → clone/pull repo in
|
||||
`/opt/cerbero-mcp` → copia secrets con `chmod 600` → genera `.env`
|
||||
iniziale (testnet) → crea `/var/log/cerbero-mcp` con permessi `1000:1000`
|
||||
→ pull image dal registry → `docker compose up -d` → smoke test pubblico.
|
||||
Lo script esegue: docker login registry → scarica `docker-compose.prod.yml`,
|
||||
`docker-compose.traefik.yml`, `gateway/Caddyfile`, `gateway/public/*` in
|
||||
`/docker/cerbero_mcp/` → chmod 600 sui secrets → genera `.env` iniziale
|
||||
(testnet) → crea `/var/log/cerbero-mcp` con permessi `1000:1000` → pull
|
||||
image dal registry → `docker compose up -d` → smoke test pubblico.
|
||||
|
||||
Per aggiornare in seguito: ri-esegui lo stesso script (preserva `.env`).
|
||||
Per aggiornare in seguito: ri-esegui lo stesso script (preserva `.env`
|
||||
e secrets, ricarica config dal branch `main` aggiornato).
|
||||
|
||||
**Override paths**: `DEPLOY_DIR` (default `/docker/cerbero_mcp`),
|
||||
`SECRETS_SRC` (default `$DEPLOY_DIR/secrets`), `AUDIT_LOG_DIR` (default
|
||||
`/var/log/cerbero-mcp`).
|
||||
|
||||
### Modalità behind-Traefik
|
||||
|
||||
@@ -234,12 +252,23 @@ echo "$GITEA_PAT" | docker login git.tielogic.xyz -u <gitea-username> --password
|
||||
Le credenziali vengono salvate in `~/.docker/config.json`. Watchtower lo
|
||||
bind-monta in sola lettura per fare i pull autenticati.
|
||||
|
||||
### b) Clona repository (solo per i file di compose, secret e Caddyfile)
|
||||
### b) Crea dir di deploy e scarica i file di config
|
||||
|
||||
Sul VPS NON serve clonare il repo. Bastano i file di compose, il
|
||||
`Caddyfile` e i public assets del gateway:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/cerbero-mcp && sudo chown $USER /opt/cerbero-mcp
|
||||
cd /opt/cerbero-mcp
|
||||
git clone ssh://git@git.tielogic.xyz:222/Adriano/Cerbero-mcp.git .
|
||||
sudo mkdir -p /docker/cerbero_mcp/{secrets,gateway/public}
|
||||
sudo chown -R "$USER" /docker/cerbero_mcp
|
||||
cd /docker/cerbero_mcp
|
||||
|
||||
BASE=https://git.tielogic.xyz/Adriano/Cerbero-mcp/raw/branch/main
|
||||
curl -fsSL -o docker-compose.prod.yml $BASE/docker-compose.prod.yml
|
||||
curl -fsSL -o docker-compose.traefik.yml $BASE/docker-compose.traefik.yml
|
||||
curl -fsSL -o gateway/Caddyfile $BASE/gateway/Caddyfile
|
||||
curl -fsSL -o gateway/public/index.html $BASE/gateway/public/index.html
|
||||
curl -fsSL -o gateway/public/status.js $BASE/gateway/public/status.js
|
||||
curl -fsSL -o gateway/public/style.css $BASE/gateway/public/style.css
|
||||
```
|
||||
|
||||
Il VPS NON ha bisogno di buildare; usa `docker-compose.prod.yml` che fa solo
|
||||
@@ -258,7 +287,7 @@ chmod 600 secrets/*
|
||||
|
||||
### d) `.env` con configurazione runtime
|
||||
|
||||
Crea `/opt/cerbero-mcp/.env`:
|
||||
Crea `/docker/cerbero_mcp/.env`:
|
||||
|
||||
```bash
|
||||
# Gateway
|
||||
@@ -390,14 +419,14 @@ Applicalo come middleware al router Gitea.
|
||||
|
||||
## 11. Aggiornamento del compose stesso (file YAML)
|
||||
|
||||
Watchtower aggiorna le **image**, non il `docker-compose.prod.yml`. Se cambi
|
||||
struttura (nuovi servizi, nuove env var) devi:
|
||||
Watchtower aggiorna le **image**, non `docker-compose.prod.yml` né
|
||||
`Caddyfile`. Se cambi struttura (nuovi servizi, nuove env var, modifiche
|
||||
al gateway), ri-esegui sul VPS lo script no-clone, che ri-scarica i file
|
||||
di config dal branch `main` di Gitea e applica:
|
||||
|
||||
```bash
|
||||
cd /opt/cerbero-mcp
|
||||
git pull
|
||||
docker compose -f docker-compose.prod.yml --env-file .env up -d
|
||||
/tmp/deploy-noclone.sh
|
||||
```
|
||||
|
||||
Per automatizzare anche questo serve un cron job o uno step CD push-based
|
||||
(vedi backlog).
|
||||
Lo script è idempotente: preserva `.env` e `secrets/`, aggiorna solo i
|
||||
file di config + fa `pull` + `up -d`.
|
||||
|
||||
Reference in New Issue
Block a user