# 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 |