Files
projet_gestion_commande/INFRA.md
T

340 lines
14 KiB
Markdown

# Infrastructure — Projet Gestion Commande
## Schéma global
```mermaid
graph TB
%% ─── Clients ───────────────────────────────────────────────
subgraph Clients["Clients"]
WEB["🌐 Web\nReact / Vite\n(frontend-prep)"]
MOB["📱 Mobile client\nReact Native / Expo\n(mobile/)"]
ADM["📱 Mobile admin\nReact Native / Expo\n(frontend-admin/)"]
end
%% ─── Services externes ──────────────────────────────────────
subgraph External["Services externes"]
TOMTOM["TomTom API\nMaps & routing"]
TELEGRAM["Telegram\nBot / Webhooks"]
NOWPAY["NowPayments\nCrypto IPN"]
DOCKERHUB["Docker Hub\nxor1234/backend-mln\nxor1234/frontend-mln"]
EAS["Expo EAS\nAPK builds"]
end
%% ─── CI/CD ──────────────────────────────────────────────────
subgraph CICD["CI/CD — GitHub Actions"]
GHA_B_PP["backend-build.yml (pre-prod)\nlint → build → docker → SSH deploy"]
GHA_F_PP["frontend-web-build.yml (pre-prod)\nlint → build → docker → SSH deploy"]
GHA_B["backend-build.yml (main)\nlint → build → docker → SSH deploy"]
GHA_F["frontend-web-build.yml (main)\nlint → build → docker → SSH deploy"]
GHA_A["frontend-admin-build.yml\ntypecheck → EAS APK"]
GHA_C["frontend-client-build.yml\ntypecheck → EAS APK"]
end
%% ─── VPS Pre-prod ───────────────────────────────────────────
subgraph PreProdVPS["VPS Pre-prod"]
subgraph GestionNetPP["Docker network : gestion-network"]
WAF_PP["🛡️ WAF\nnginx + ModSecurity CRS\n:80 / :443 ← public"]
BACK_PP["⚙️ Backend\nGo 1.24 + Gin\n:8080 ← interne"]
FRONT_PP["🖥️ Frontend\nReact SPA — nginx\n:80 ← interne"]
PG_PP["🗄️ PostgreSQL 16\n← interne"]
REDIS_PP["⚡ Redis 7\n← interne"]
end
end
%% ─── VPS Production ─────────────────────────────────────────
subgraph ProdVPS["VPS Production — mln-uber.club"]
subgraph GestionNet["Docker network : gestion-network"]
WAF["🛡️ WAF\nnginx + ModSecurity CRS\nParanoia L2\n:80 / :443 ← public"]
BACK["⚙️ Backend\nGo 1.24 + Gin\n:8080 ← interne"]
FRONT["🖥️ Frontend\nReact SPA — nginx\n:80 ← interne"]
PG["🗄️ PostgreSQL 16\ngestion_db\n← interne"]
REDIS["⚡ Redis 7\nSessions · Queue · Cache\n256 MB LRU ← interne"]
end
end
%% ─── VPS Monitoring ─────────────────────────────────────────
subgraph MonVPS["VPS Monitoring — uber-stup.club"]
subgraph MonNet["Docker network : monitoring_net"]
MNGINX["🔀 Nginx RP\n:80 / :443 ← public\ndozzle / wazuh\nrustfs / s3 / ota"]
DOZZLE["📋 Dozzle\nLogs temps réel\n:8080 ← interne"]
WAZUH_M["🔍 Wazuh Manager\n:1514 agents\n:1515 enroll\n:514 syslog"]
WAZUH_I["🗂️ Wazuh Indexer\nOpenSearch :9200"]
WAZUH_D["📊 Wazuh Dashboard\nKibana :5601"]
RUSTFS["🗃️ RustFS\nS3-compatible :9000\nConsole :9001"]
XAVIA["🚀 Xavia OTA\nNext.js :3000"]
XAVIA_DB["🗄️ PostgreSQL 16\nxavia_db ← interne"]
end
end
%% ─── Flux clients ───────────────────────────────────────────
WEB -->|HTTPS| WAF
MOB -->|HTTPS| WAF
ADM -->|HTTPS| WAF
%% ─── Routage WAF ────────────────────────────────────────────
WAF -->|"/api/*"| BACK
WAF -->|"/* SPA"| FRONT
WAF -->|"/uploads/*"| BACK
%% ─── Backend ↔ données ──────────────────────────────────────
BACK --> PG
BACK --> REDIS
%% ─── Backend ↔ services externes ────────────────────────────
BACK -->|"Geocoding / ETA"| TOMTOM
BACK -->|"Webhook"| TELEGRAM
BACK -->|"IPN callback"| NOWPAY
%% ─── CI/CD ──────────────────────────────────────────────────
GHA_B_PP -->|"push :latest + :waf"| DOCKERHUB
GHA_F_PP -->|"push :latest"| DOCKERHUB
GHA_B_PP -->|"SSH deploy (SERVER_HOST)"| PreProdVPS
GHA_F_PP -->|"SSH deploy (SERVER_HOST)"| PreProdVPS
GHA_B -->|"push :latest + :waf"| DOCKERHUB
GHA_F -->|"push :latest"| DOCKERHUB
GHA_B -->|"SSH deploy (SERVER_HOST_PROD)"| ProdVPS
GHA_F -->|"SSH deploy (SERVER_HOST_PROD)"| ProdVPS
GHA_A -->|"eas build android"| EAS
GHA_C -->|"eas build android"| EAS
DOCKERHUB -->|"docker pull"| WAF_PP
DOCKERHUB -->|"docker pull"| BACK_PP
DOCKERHUB -->|"docker pull"| FRONT_PP
DOCKERHUB -->|"docker pull"| WAF
DOCKERHUB -->|"docker pull"| BACK
DOCKERHUB -->|"docker pull"| FRONT
%% ─── CI/CD mobile → OTA ────────────────────────────────────
GHA_A -->|"eas build pre-prod"| XAVIA
GHA_C -->|"eas build pre-prod"| XAVIA
%% ─── Monitoring ─────────────────────────────────────────────
MNGINX --> DOZZLE
MNGINX --> WAZUH_D
MNGINX -->|"rustfs.uber-stup.club"| RUSTFS
MNGINX -->|"s3.uber-stup.club"| RUSTFS
MNGINX -->|"ota.uber-stup.club"| XAVIA
WAZUH_D --> WAZUH_I
WAZUH_M --> WAZUH_I
XAVIA --> XAVIA_DB
DOZZLE -->|"remote agent :7007"| ProdVPS
DOZZLE -->|"remote agent :7007"| PreProdVPS
```
---
## VPS Production
**Domaine** : `mln-uber.club`
### Services
| Conteneur | Image | Ports | Rôle |
|---|---|---|---|
| `gestion-waf` | `xor1234/backend-mln:waf` | **80, 443** (public) | Reverse proxy + 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 principale |
| `gestion-redis` | `redis:7-alpine` | 6379 (interne) | Cache · Sessions · File livreurs |
### Flux de trafic
```mermaid
flowchart TD
INET["🌐 Internet"] -->|":443 TLS 1.2/1.3"| WAF
subgraph WAF["🛡️ WAF — nginx + ModSecurity CRS L2"]
W1["Rate limit : 20 req/s/IP"]
W2["HSTS 2 ans · CSP · X-Frame"]
W3["Ban auto : SQLi / XSS / LFI / RCE"]
end
WAF -->|"/api/*"| BACK["⚙️ Backend\nGo / Gin :8080"]
WAF -->|"/* SPA"| FRONT["🖥️ Frontend\nnginx :80"]
WAF -->|"/uploads/*\n(fichiers statiques)"| BACK
BACK --> PG["🗄️ PostgreSQL 16"]
BACK --> REDIS["⚡ Redis 7\nSessions · Queue · Cache"]
```
### Volumes persistants
| Volume | Usage |
|---|---|
| `postgres_data` | Données PostgreSQL |
| `redis_data` | Persistance Redis (AOF) |
| `backend_uploads` | Fichiers uploadés — monté en `:ro` dans le WAF pour `/uploads/` |
### Variables d'environnement requises
| Variable | Valeur par défaut | Description |
|---|---|---|
| `DB_PASSWORD` | — | Mot de passe PostgreSQL |
| `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 |
---
## VPS Pre-prod
Même stack que la production, déployé depuis la branche `pre-prod` via `SERVER_HOST` / `SERVER_SSH_KEY`.
### Services
| 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 |
---
## VPS Monitoring
**Domaine** : `uber-stup.club`
### Services
| Conteneur | Image | Ports | Rôle |
|---|---|---|---|
| `monitoring_nginx` | `nginx:alpine` | **80, 443** (public) | Reverse proxy monitoring |
| `dozzle` | `amir20/dozzle:latest` | 8080 (interne) | Logs Docker temps réel |
| `wazuh.manager` | `wazuh/wazuh-manager:4.14.5` | 1514, 1515, 514/udp | SIEM — collecte agents |
| `wazuh.indexer` | `wazuh/wazuh-indexer:4.14.5` | 9200 (interne) | OpenSearch (stockage events) |
| `wazuh.dashboard` | `wazuh/wazuh-dashboard:4.14.5` | 5601 (interne) | Kibana (visualisation) |
| `rustfs` | `rustfs/rustfs:latest` | 9000 S3, 9001 console (internes) | Stockage objet S3-compatible (APKs) |
| `xavia` | `xaviaio/xavia-ota:latest` | 3000 (interne) | Serveur OTA Expo (Next.js) |
| `xavia_db` | `postgres:16-alpine` | 5432 (interne) | Base de données Xavia |
### Accès publics
| URL | Service |
|---|---|
| `https://dozzle.uber-stup.club` | Interface logs Docker |
| `https://wazuh.uber-stup.club` | Dashboard SIEM Wazuh |
| `https://rustfs.uber-stup.club` | Console RustFS (stockage APKs) |
| `https://s3.uber-stup.club` | API S3 RustFS |
| `https://ota.uber-stup.club` | Dashboard & API Xavia OTA |
### Xavia OTA — configuration app Expo
```json
"updates": {
"url": "https://ota.uber-stup.club/api/manifest",
"codeSigningCertificate": "./certs/certificate.pem",
"codeSigningMetadata": {
"keyid": "main",
"algorithm": "rsa-v1_5-sha256"
}
}
```
Clé privée RSA 4096 stockée sur le serveur dans `/home/ubuntu/xavia-keys/private-key.pem`.
Le `certificate.pem` doit être commité dans le repo mobile sous `mobile/certs/certificate.pem`.
### Dozzle — agents distants
```mermaid
graph LR
DOZZLE["📋 Dozzle\nuber-stup.club"] -->|":7007"| A1["VPS Production\n5.181.0.112"]
DOZZLE -->|":7007"| A2["VPS Pre-prod\n185.234.9.102"]
```
---
## CI/CD
### Pipeline backend (pre-prod & 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
```
### Pipeline frontend web (pre-prod & main)
```mermaid
flowchart TD
PUSH["push frontend-prep/**\nou docker/frontend/**"] --> LINT["lint-typecheck\ntsc + eslint"]
LINT --> BUILD["build\nnpm run build"]
BUILD --> ARTIFACT["artifact\nfrontend-web-dist 7j"]
BUILD --> DOCKER{"push only?"}
DOCKER -->|oui| D1["docker build\n→ xor1234/frontend-mln:latest"]
D1 --> DEPLOY["SSH deploy\ndocker compose pull frontend\ndocker compose up -d --no-deps frontend"]
style DOCKER fill:#f0f0f0
```
### Pipeline mobile (main uniquement)
```mermaid
flowchart TD
PUSH_A["push frontend-admin/**"] --> TC_A["typecheck\ntsc --noEmit"]
TC_A --> EAS_A["EAS build android\n--profile production"]
EAS_A --> APK_A["artifact\nadmin-panel-android-prod-apk 14j"]
PUSH_C["push mobile/**"] --> TC_C["typecheck\ntsc --noEmit"]
TC_C --> EAS_C["EAS build android\n--profile production"]
EAS_C --> APK_C["artifact\nclient-android-prod-apk 14j"]
```
### Secrets GitHub requis
| Secret | Branche | Usage |
|---|---|---|
| `DOCKERHUB_USERNAME` | main + pre-prod | Login Docker Hub |
| `DOCKERHUB_TOKEN` | main + pre-prod | Token Docker Hub |
| `SERVER_HOST` | pre-prod | IP/hostname VPS pre-prod |
| `SERVER_HOST_PROD` | main | IP/hostname VPS production |
| `SERVER_USER` | main + pre-prod | Utilisateur SSH |
| `SERVER_SSH_KEY` | pre-prod | Clé privée SSH ED25519 pre-prod |
| `SERVER_SSH_KEY_PROD` | main | Clé privée SSH ED25519 prod |
| `COMPOSE_PATH` | main + pre-prod | Chemin absolu docker-compose-prod.yml |
| `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
```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"]
```
### Rôles utilisateurs
| Rôle | Accès |
|---|---|
| `client` | Panier, commandes, profil, suivi |
| `admin` | Gestion complète (commandes, produits, livreurs, stats) |
| `cabine` | Mise à jour statut commandes + notification client |
| `livreur` | Tableau de bord livraisons, GPS, statut |