# Déploiement XIP Production : **https://xip.kerboul.me** — déploiement continu sur push `main`. ## Architecture (pattern Vireli, cluster SENTINEL) ``` Cloudflare (*.kerboul.me) ─► VPS WireGuard ─► Traefik (CT102, Cerberus) │ Host(`xip.kerboul.me`) → http://192.168.1.242:80 ▼ CT502 « xip-app » (Echelon, Docker host) ┌───────────────────────────────────────┐ │ web (nginx:80) │ │ ├── / → SPA Vue (statique) │ │ ├── /api/ → backend:3000 │ │ └── /ws → backend:3000 (WS) │ │ backend (bun:3000, Hono + Prisma) │ │ postgres:16 redis:7 │ └───────────────────────────────────────┘ ``` Origine unique : le front (buildé avec `VITE_API_URL=https://xip.kerboul.me`) appelle `/api` et `wss://xip.kerboul.me/ws`, nginx proxifie vers le backend. Traefik termine le TLS (Let's Encrypt, DNS challenge Cloudflare). ## CI/CD (Gitea Actions) `.gitea/workflows/deploy.yml` se déclenche sur push `main` (+ `workflow_dispatch`). Le runner (CT121) se connecte en SSH au CT502 et exécute `scripts/deploy.sh` (`git reset --hard origin/main` + `docker compose up -d --build`). Migrations Prisma + seed (idempotent) tournent au démarrage du conteneur backend (`backend/docker-entrypoint.sh`). ### Secrets du repo (Gitea → Settings → Actions → Secrets) | Secret | Rôle | |--------|------| | `XIP_DEPLOY_HOST` | IP du CT502 (192.168.1.242) | | `XIP_DEPLOY_USER` | utilisateur de déploiement (`deploy`) | | `XIP_DEPLOY_KEY` | clé privée SSH autorisée sur le CT502 | ## Fichiers | Fichier | Rôle | |---------|------| | `docker-compose.prod.yml` | stack prod (postgres, redis, backend, web) | | `backend/Dockerfile` + `docker-entrypoint.sh` | image backend, migrate+seed au boot | | `frontend/Dockerfile` | build Vite → nginx | | `deploy/nginx.conf` | reverse proxy single-origin | | `scripts/deploy.sh` | script de (re)déploiement sur le CT | | `.env.prod` (non commité) | secrets : voir `.env.prod.example` | ## Paywall `XIP_OPEN_BAR=true` (dans `.env.prod`) = **open bar** : toutes les fonctionnalités payantes gratuites pour tout le monde. Mettre `false` pour réactiver le paywall (gratuit uniquement en localhost). Logique centralisée dans `backend/src/lib/ip.ts` (`isFree()`). ## Redéploiement manuel ```bash ssh deploy@192.168.1.242 'bash /opt/xip/scripts/deploy.sh' ```