chore: add INFRA doc

This commit is contained in:
2026-05-02 19:15:07 +02:00
parent cfe1d49da9
commit 56d651f01c
+108 -131
View File
@@ -69,9 +69,9 @@ graph TB
ADM -->|HTTPS| WAF ADM -->|HTTPS| WAF
%% ─── Routage WAF ──────────────────────────────────────────── %% ─── Routage WAF ────────────────────────────────────────────
WAF -->|"/api/*"| BACK WAF -->|"/api/*"| BACK
WAF -->|"/* SPA"| FRONT WAF -->|"/* SPA"| FRONT
WAF -->|"/uploads/*"| BACK WAF -->|"/uploads/*"| BACK
%% ─── Backend ↔ données ────────────────────────────────────── %% ─── Backend ↔ données ──────────────────────────────────────
BACK --> PG BACK --> PG
@@ -125,30 +125,24 @@ graph TB
| `gestion-postgres` | `postgres:16-alpine` | 5432 (interne) | Base de données principale | | `gestion-postgres` | `postgres:16-alpine` | 5432 (interne) | Base de données principale |
| `gestion-redis` | `redis:7-alpine` | 6379 (interne) | Cache · Sessions · File livreurs | | `gestion-redis` | `redis:7-alpine` | 6379 (interne) | Cache · Sessions · File livreurs |
### Réseau Docker
Tous les conteneurs partagent le bridge `gestion-network` (`gestion-br0`). Seul le WAF expose des ports publics.
### Flux de trafic ### Flux de trafic
``` ```mermaid
Internet flowchart TD
INET["🌐 Internet"] -->|":443 TLS 1.2/1.3"| WAF
▼ :443 (TLS 1.2/1.3)
┌─────────────────────────────────────┐ subgraph WAF["🛡️ WAF — nginx + ModSecurity CRS L2"]
│ WAF nginx + ModSecurity CRS L2 │ W1["Rate limit : 20 req/s/IP"]
│ • Rate limit : 20 req/s/IP │ W2["HSTS 2 ans · CSP · X-Frame"]
│ • HSTS 2 ans │ W3["Ban auto : SQLi / XSS / LFI / RCE"]
│ • CSP / X-Frame / Permissions │ end
│ • Ban auto sur SQLi / XSS / LFI │
└──────┬──────────────┬───────────────┘ WAF -->|"/api/*"| BACK["⚙️ Backend\nGo / Gin :8080"]
│ /api/* │ /* WAF -->|"/* SPA"| FRONT["🖥️ Frontend\nnginx :80"]
▼ ▼ WAF -->|"/uploads/*\n(fichiers statiques)"| BACK
Backend Frontend
Go/Gin nginx SPA BACK --> PG["🗄️ PostgreSQL 16"]
BACK --> REDIS["⚡ Redis 7\nSessions · Queue · Cache"]
├──► PostgreSQL (persistance)
└──► Redis (cache / queues)
``` ```
### Volumes persistants ### Volumes persistants
@@ -157,31 +151,40 @@ Internet
|---|---| |---|---|
| `postgres_data` | Données PostgreSQL | | `postgres_data` | Données PostgreSQL |
| `redis_data` | Persistance Redis (AOF) | | `redis_data` | Persistance Redis (AOF) |
| `backend_uploads` | Fichiers uploadés (images, vidéos) — monté en `:ro` dans le WAF pour `/uploads/` | | `backend_uploads` | Fichiers uploadés — monté en `:ro` dans le WAF pour `/uploads/` |
### Variables d'environnement requises ### Variables d'environnement requises
```env | Variable | Valeur par défaut | Description |
# Base de données |---|---|---|
DB_PASSWORD= | `DB_PASSWORD` | — | Mot de passe PostgreSQL |
DB_NAME=gestion_db | `DB_NAME` | `gestion_db` | Nom de la base |
| `SESSION_SECRET` | — | Secret session Gin |
| `USER_JWT_SECRET` | — | JWT clients |
| `USER_JWT_SECRET_OLD` | — | JWT clients (rotation) |
| `ADMIN_JWT_SECRET` | — | JWT admin/cabine |
| `ADMIN_JWT_SECRET_OLD` | — | JWT admin (rotation) |
| `REDIS_PASSWORD` | — | Mot de passe Redis |
| `TOMTOM_API_KEY` | — | Clé TomTom Maps |
| `TELEGRAM_WEBHOOK_URL` | — | URL webhook Telegram |
| `TELEGRAM_WEBHOOK_SECRET` | — | Secret webhook Telegram |
| `NOWPAYMENTS_IPN_SECRET` | — | Secret IPN NowPayments |
# JWT ---
SESSION_SECRET=
USER_JWT_SECRET=
USER_JWT_SECRET_OLD=
ADMIN_JWT_SECRET=
ADMIN_JWT_SECRET_OLD=
# Redis ## VPS Pre-prod
REDIS_PASSWORD=
# Services externes Même stack que la production, déployé depuis la branche `pre-prod` via `SERVER_HOST` / `SERVER_SSH_KEY`.
TOMTOM_API_KEY=
TELEGRAM_WEBHOOK_URL= ### Services
TELEGRAM_WEBHOOK_SECRET=
NOWPAYMENTS_IPN_SECRET= | Conteneur | Image | Ports | Rôle |
``` |---|---|---|---|
| `gestion-waf` | `xor1234/backend-mln:waf` | **80, 443** (public) | WAF ModSecurity |
| `gestion-backend` | `xor1234/backend-mln:latest` | 8080 (interne) | API Go/Gin |
| `gestion-frontend` | `xor1234/frontend-mln:latest` | 80 (interne) | SPA React/Vite |
| `gestion-postgres` | `postgres:16-alpine` | 5432 (interne) | Base de données |
| `gestion-redis` | `redis:7-alpine` | 6379 (interne) | Cache · Sessions |
--- ---
@@ -208,116 +211,90 @@ NOWPAYMENTS_IPN_SECRET=
### Dozzle — agents distants ### Dozzle — agents distants
Dozzle agrège les logs de plusieurs serveurs via des agents distants : ```mermaid
graph LR
| Adresse | Usage | DOZZLE["📋 Dozzle\nuber-stup.club"] -->|":7007"| A1["VPS Production\n5.181.0.112"]
|---|---| DOZZLE -->|":7007"| A2["VPS Pre-prod\n185.234.9.102"]
| `5.181.0.112:7007` | Agent VPS 1 | ```
| `185.234.9.102:7007` | Agent VPS 2 |
--- ---
## CI/CD ## CI/CD
### Pipelines ### Pipeline backend (pre-prod & main)
#### `backend-build.yml` — branche `main` ```mermaid
flowchart TD
PUSH["push backend/**"] --> LINT["lint\ngolangci-lint"]
LINT --> BUILD["build\ngo build ./..."]
BUILD --> ARTIFACT["artifact\nbackend-binary 7j"]
BUILD --> DOCKER{"push only?"}
DOCKER -->|oui| D1["docker build runtime\n→ xor1234/backend-mln:latest"]
DOCKER -->|oui| D2["docker build waf\n→ xor1234/backend-mln:waf"]
D1 --> DEPLOY["SSH deploy\ndocker compose pull backend waf\ndocker compose up -d --no-deps backend waf"]
D2 --> DEPLOY
``` style DOCKER fill:#f0f0f0
push main/backend/**
lint (golangci-lint)
build (go build ./...)
└─ artifact: backend-binary (7j)
│ [push only]
docker
├─ build --target runtime → xor1234/backend-mln:latest
└─ build --target waf → xor1234/backend-mln:waf
│ [push only]
deploy (SSH)
├─ docker compose pull backend waf
└─ docker compose up -d --no-deps backend waf
``` ```
#### `frontend-web-build.yml` — branche `main` ### Pipeline frontend web (pre-prod & main)
``` ```mermaid
push main/frontend-prep/** ou docker/frontend/** flowchart TD
PUSH["push frontend-prep/**\nou docker/frontend/**"] --> LINT["lint-typecheck\ntsc + eslint"]
LINT --> BUILD["build\nnpm run build"]
lint-typecheck (tsc + eslint) BUILD --> ARTIFACT["artifact\nfrontend-web-dist 7j"]
BUILD --> DOCKER{"push only?"}
DOCKER -->|oui| D1["docker build\n→ xor1234/frontend-mln:latest"]
build (npm run build) D1 --> DEPLOY["SSH deploy\ndocker compose pull frontend\ndocker compose up -d --no-deps frontend"]
└─ artifact: frontend-web-dist (7j)
│ [push only] style DOCKER fill:#f0f0f0
docker
└─ build → xor1234/frontend-mln:latest
│ [push only]
deploy (SSH)
├─ docker compose pull frontend
└─ docker compose up -d --no-deps frontend
``` ```
#### `frontend-admin-build.yml` / `frontend-client-build.yml` — branche `main` ### Pipeline mobile (main uniquement)
``` ```mermaid
push main/frontend-admin/** (ou mobile/**) flowchart TD
PUSH_A["push frontend-admin/**"] --> TC_A["typecheck\ntsc --noEmit"]
TC_A --> EAS_A["EAS build android\n--profile production"]
typecheck (tsc --noEmit) EAS_A --> APK_A["artifact\nadmin-panel-android-prod-apk 14j"]
│ [push only]
PUSH_C["push mobile/**"] --> TC_C["typecheck\ntsc --noEmit"]
build-apk-prod (EAS) TC_C --> EAS_C["EAS build android\n--profile production"]
├─ eas build --platform android --profile production EAS_C --> APK_C["artifact\nclient-android-prod-apk 14j"]
└─ artifact: admin-panel-android-prod-apk (14j)
``` ```
### Secrets GitHub requis ### Secrets GitHub requis
| Secret | Usage | | Secret | Branche | Usage |
|---|---| |---|---|---|
| `DOCKERHUB_USERNAME` | Login Docker Hub | | `DOCKERHUB_USERNAME` | main + pre-prod | Login Docker Hub |
| `DOCKERHUB_TOKEN` | Token Docker Hub | | `DOCKERHUB_TOKEN` | main + pre-prod | Token Docker Hub |
| `SERVER_HOST` / `SERVER_HOST_PROD` | IP/hostname VPS | | `SERVER_HOST` | pre-prod | IP/hostname VPS pre-prod |
| `SERVER_USER` | Utilisateur SSH | | `SERVER_HOST_PROD` | main | IP/hostname VPS production |
| `SERVER_SSH_KEY` / `SERVER_SSH_KEY_PROD` | Clé privée SSH ED25519 | | `SERVER_USER` | main + pre-prod | Utilisateur SSH |
| `COMPOSE_PATH` | Chemin absolu du docker-compose-prod.yml | | `SERVER_SSH_KEY` | pre-prod | Clé privée SSH ED25519 pre-prod |
| `EXPO_TOKEN` | Token Expo EAS | | `SERVER_SSH_KEY_PROD` | main | Clé privée SSH ED25519 prod |
| `EXPO_PROJECT_ID` / `EXPO_PROJECT_ID_CLIENT` | IDs projets EAS | | `COMPOSE_PATH` | main + pre-prod | Chemin absolu docker-compose-prod.yml |
| `VITE_TOMTOM_API_KEY` | Clé TomTom pour le build frontend | | `EXPO_TOKEN` | main | Token Expo EAS |
| `EXPO_PROJECT_ID` | main | ID projet EAS admin |
| `EXPO_PROJECT_ID_CLIENT` | main | ID projet EAS client |
| `VITE_TOMTOM_API_KEY` | main + pre-prod | Clé TomTom pour build frontend |
--- ---
## Backend — architecture interne ## Backend — architecture interne
```mermaid
graph TD
MAIN["main.go\ninit DB · Redis · services · Gin"] --> ROUTES["routes/routes.go\npublic · client · admin · cabine · livreur"]
ROUTES --> HANDLERS["handlers/\nauth · commands · delivery\npanier · notifications · payments"]
HANDLERS --> MODELS["models/\nstructs GORM"]
HANDLERS --> DB["db/\nconnexion · migrations · queries"]
HANDLERS --> SERVICES["services/\nTomTom · Telegram · NowPayments"]
MAIN --> WORKERS["workers/\ncron_auto_assign 5min\npayment_checker 2min\nqueue_cleanup 5min"]
MAIN --> MW["middleware/\nsession · block · clock"]
``` ```
backend/gestion/
├── main.go ← init DB, Redis, services, workers, Gin router
├── routes/routes.go ← toutes les routes (public / client / admin / cabine / livreur)
├── handlers/ ← logique HTTP (auth, commands, delivery, payments…)
├── models/ ← structs Go (GORM)
├── db/ ← connexion, migrations, queries
├── services/ ← TomTom, Telegram, NowPayments
├── middleware/ ← session, block, clock
├── workers/ ← cron auto-assign (5 min), payment checker (2 min)
└── uploads/ ← fichiers statiques servis via /uploads/
```
### Workers background
| Worker | Intervalle | Rôle |
|---|---|---|
| `cron_auto_assign` | 5 min | Assigne automatiquement les commandes `pending` aux livreurs disponibles via la queue Redis |
| `payment_checker` | 2 min | Vérifie le statut des paiements crypto NowPayments en attente |
| Queue cleanup | 5 min | Nettoie les entrées expirées dans les queues Redis |
### Rôles utilisateurs ### Rôles utilisateurs