diff --git a/INFRA.md b/INFRA.md new file mode 100644 index 00000000..986efb1b --- /dev/null +++ b/INFRA.md @@ -0,0 +1,329 @@ +# 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.uber-stup.club\nwazuh.uber-stup.club"] + 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"] + 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 + + %% ─── Monitoring ───────────────────────────────────────────── + MNGINX --> DOZZLE + MNGINX --> WAZUH_D + WAZUH_D --> WAZUH_I + WAZUH_M --> WAZUH_I + 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 | + +### Réseau Docker + +Tous les conteneurs partagent le bridge `gestion-network` (`gestion-br0`). Seul le WAF expose des ports publics. + +### Flux de trafic + +``` +Internet + │ + ▼ :443 (TLS 1.2/1.3) +┌─────────────────────────────────────┐ +│ WAF nginx + ModSecurity CRS L2 │ +│ • Rate limit : 20 req/s/IP │ +│ • HSTS 2 ans │ +│ • CSP / X-Frame / Permissions │ +│ • Ban auto sur SQLi / XSS / LFI │ +└──────┬──────────────┬───────────────┘ + │ /api/* │ /* + ▼ ▼ + Backend Frontend + Go/Gin nginx SPA + │ + ├──► PostgreSQL (persistance) + └──► Redis (cache / queues) +``` + +### Volumes persistants + +| Volume | Usage | +|---|---| +| `postgres_data` | Données PostgreSQL | +| `redis_data` | Persistance Redis (AOF) | +| `backend_uploads` | Fichiers uploadés (images, vidéos) — monté en `:ro` dans le WAF pour `/uploads/` | + +### Variables d'environnement requises + +```env +# Base de données +DB_PASSWORD= +DB_NAME=gestion_db + +# JWT +SESSION_SECRET= +USER_JWT_SECRET= +USER_JWT_SECRET_OLD= +ADMIN_JWT_SECRET= +ADMIN_JWT_SECRET_OLD= + +# Redis +REDIS_PASSWORD= + +# Services externes +TOMTOM_API_KEY= +TELEGRAM_WEBHOOK_URL= +TELEGRAM_WEBHOOK_SECRET= +NOWPAYMENTS_IPN_SECRET= +``` + +--- + +## VPS Monitoring + +**Domaine** : `uber-stup.club` + +### Services + +| Conteneur | Image | Ports | Rôle | +|---|---|---|---| +| `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.9.2` | 1514, 1515, 514/udp | SIEM — collecte agents | +| `wazuh.indexer` | `wazuh/wazuh-indexer:4.9.2` | 9200 (interne) | OpenSearch (stockage events) | +| `wazuh.dashboard` | `wazuh/wazuh-dashboard:4.9.2` | 5601 (interne) | Kibana (visualisation) | + +### Accès publics + +| URL | Service | +|---|---| +| `https://dozzle.uber-stup.club` | Interface logs Docker | +| `https://wazuh.uber-stup.club` | Dashboard SIEM Wazuh | + +### Dozzle — agents distants + +Dozzle agrège les logs de plusieurs serveurs via des agents distants : + +| Adresse | Usage | +|---|---| +| `5.181.0.112:7007` | Agent VPS 1 | +| `185.234.9.102:7007` | Agent VPS 2 | + +--- + +## CI/CD + +### Pipelines + +#### `backend-build.yml` — branche `main` + +``` +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` + +``` +push main/frontend-prep/** ou docker/frontend/** + │ + ▼ + lint-typecheck (tsc + eslint) + │ + ▼ + build (npm run build) + └─ artifact: frontend-web-dist (7j) + │ [push only] + ▼ + 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` + +``` +push main/frontend-admin/** (ou mobile/**) + │ + ▼ + typecheck (tsc --noEmit) + │ [push only] + ▼ + build-apk-prod (EAS) + ├─ eas build --platform android --profile production + └─ artifact: admin-panel-android-prod-apk (14j) +``` + +### Secrets GitHub requis + +| Secret | Usage | +|---|---| +| `DOCKERHUB_USERNAME` | Login Docker Hub | +| `DOCKERHUB_TOKEN` | Token Docker Hub | +| `SERVER_HOST` / `SERVER_HOST_PROD` | IP/hostname VPS | +| `SERVER_USER` | Utilisateur SSH | +| `SERVER_SSH_KEY` / `SERVER_SSH_KEY_PROD` | Clé privée SSH ED25519 | +| `COMPOSE_PATH` | Chemin absolu du docker-compose-prod.yml | +| `EXPO_TOKEN` | Token Expo EAS | +| `EXPO_PROJECT_ID` / `EXPO_PROJECT_ID_CLIENT` | IDs projets EAS | +| `VITE_TOMTOM_API_KEY` | Clé TomTom pour le build frontend | + +--- + +## Backend — architecture interne + +``` +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ô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 |