Files
XIP/DEPLOY.md
Kerboul 024909b162
Some checks failed
Deploy XIP / deploy (push) Failing after 21s
feat(deploy): CI/CD Gitea Actions + stack Docker prod pour xip.kerboul.me
- docker-compose.prod.yml: postgres + redis + backend (bun) + web (nginx single-origin)
- backend/Dockerfile + entrypoint: prisma migrate deploy + seed idempotent au boot
- frontend/Dockerfile: build Vite (VITE_API_URL=https://xip.kerboul.me) servi par nginx
- deploy/nginx.conf: proxy /api + /ws vers le backend, SPA fallback
- .gitea/workflows/deploy.yml: auto-deploy SSH sur push main (runner CT121 -> CT502)
- scripts/deploy.sh: pull + rebuild de la stack
- mode open-bar (XIP_OPEN_BAR): paywall off pour tous en prod, via isFree() centralise

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 15:14:53 +02:00

2.9 KiB

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

ssh deploy@192.168.1.242 'bash /opt/xip/scripts/deploy.sh'