# Guide de Déploiement Portainer - Xpeditis

Ce guide explique comment déployer l'application Xpeditis sur un serveur Docker Swarm avec Portainer et Traefik.

## Prérequis

- Docker Swarm initialisé sur votre serveur
- Traefik configuré et déployé avec le réseau `traefik_network`
- Portainer installé et accessible
- Noms de domaine configurés avec DNS pointant vers votre serveur :
  - `app.xpeditis.com` - Frontend
  - `api.xpeditis.com` - Backend API
  - `s3.xpeditis.com` - MinIO API
  - `minio.xpeditis.com` - MinIO Console

## Configuration DNS Requise

Configurez les enregistrements DNS suivants (type A) pour pointer vers l'IP de votre serveur :

```
app.xpeditis.com      → IP_DU_SERVEUR
www.xpeditis.com      → IP_DU_SERVEUR
api.xpeditis.com      → IP_DU_SERVEUR
s3.xpeditis.com       → IP_DU_SERVEUR
minio.xpeditis.com    → IP_DU_SERVEUR
```

## Étape 1 : Préparer les Images Docker

### 1.1 Construire l'image Backend

```bash
cd /chemin/vers/xpeditis2.0

# Construire l'image backend
docker build -t xpeditis/backend:latest -f apps/backend/Dockerfile .

# Tag et push vers votre registre (optionnel)
docker tag xpeditis/backend:latest registry.xpeditis.com/xpeditis/backend:latest
docker push registry.xpeditis.com/xpeditis/backend:latest
```

### 1.2 Construire l'image Frontend

```bash
# Construire l'image frontend
docker build -t xpeditis/frontend:latest -f apps/frontend/Dockerfile .

# Tag et push vers votre registre (optionnel)
docker tag xpeditis/frontend:latest registry.xpeditis.com/xpeditis/frontend:latest
docker push registry.xpeditis.com/xpeditis/frontend:latest
```

### 1.3 Sauvegarder les Images (Alternative sans registre)

Si vous n'avez pas de registre Docker privé :

```bash
# Sauvegarder les images
docker save xpeditis/backend:latest | gzip > xpeditis-backend.tar.gz
docker save xpeditis/frontend:latest | gzip > xpeditis-frontend.tar.gz

# Transférer vers le serveur
scp xpeditis-backend.tar.gz user@server:/tmp/
scp xpeditis-frontend.tar.gz user@server:/tmp/

# Sur le serveur, charger les images
ssh user@server
docker load < /tmp/xpeditis-backend.tar.gz
docker load < /tmp/xpeditis-frontend.tar.gz
```

## Étape 2 : Vérifier Traefik

Assurez-vous que Traefik est correctement configuré avec :

- Network `traefik_network` externe
- Entrypoints `web` (port 80) et `websecure` (port 443)
- Certificat resolver `letsencrypt` configuré

Exemple de vérification :

```bash
# Vérifier le réseau Traefik
docker network inspect traefik_network

# Vérifier que Traefik fonctionne
docker service ls | grep traefik
```

## Étape 3 : Configurer les Variables d'Environnement

Avant de déployer, **CHANGEZ TOUS LES MOTS DE PASSE** dans le fichier `portainer-stack.yml` :

### Variables à modifier :

```yaml
# Database
POSTGRES_PASSWORD: xpeditis_prod_password_CHANGE_ME → Votre_Mot_De_Passe_Fort_DB

# Redis
REDIS_PASSWORD: xpeditis_redis_password_CHANGE_ME → Votre_Mot_De_Passe_Fort_Redis

# MinIO
MINIO_ROOT_USER: minioadmin_CHANGE_ME → Votre_Utilisateur_MinIO
MINIO_ROOT_PASSWORD: minioadmin_password_CHANGE_ME → Votre_Mot_De_Passe_Fort_MinIO

# JWT
JWT_SECRET: your-super-secret-jwt-key-CHANGE_ME-min-32-characters → Votre_Secret_JWT_32_Caracteres_Min

# Email (selon votre fournisseur)
EMAIL_HOST: smtp.example.com → smtp.votre-fournisseur.com
EMAIL_PORT: 587
EMAIL_USER: noreply@xpeditis.com → Votre_Email
EMAIL_PASSWORD: email_password_CHANGE_ME → Votre_Mot_De_Passe_Email
```

### Générer des mots de passe forts :

```bash
# Générer un mot de passe aléatoire de 32 caractères
openssl rand -base64 32

# Générer un secret JWT de 64 caractères
openssl rand -base64 64 | tr -d '\n'
```

## Étape 4 : Déployer avec Portainer

### 4.1 Accéder à Portainer

1. Ouvrez votre navigateur et accédez à Portainer (ex: `https://portainer.votre-domaine.com`)
2. Connectez-vous avec vos identifiants
3. Sélectionnez votre environnement Docker Swarm

### 4.2 Créer la Stack

1. Dans le menu latéral, cliquez sur **"Stacks"**
2. Cliquez sur **"+ Add stack"**
3. Donnez un nom à la stack : `xpeditis`
4. Choisissez **"Web editor"**
5. Copiez le contenu du fichier `portainer-stack.yml` (avec vos modifications)
6. Collez le contenu dans l'éditeur Portainer
7. Cliquez sur **"Deploy the stack"**

### 4.3 Vérifier le Déploiement

1. Attendez que tous les services soient déployés (statut vert)
2. Vérifiez les logs de chaque service :
   - Cliquez sur **"Stacks"** → **"xpeditis"**
   - Sélectionnez un service et consultez ses logs

## Étape 5 : Initialiser la Base de Données

### 5.1 Attendre que la DB soit prête

```bash
# Vérifier que PostgreSQL est prêt
docker service logs xpeditis_xpeditis-db --tail 50

# Vous devriez voir : "database system is ready to accept connections"
```

### 5.2 Exécuter les Migrations

```bash
# Trouver le conteneur backend
BACKEND_CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-backend" --format "{{.ID}}" | head -n 1)

# Exécuter les migrations
docker exec -it $BACKEND_CONTAINER npm run migration:run

# Vérifier que les migrations sont appliquées
docker exec -it $BACKEND_CONTAINER npm run migration:show
```

### 5.3 Créer un Bucket MinIO

```bash
# Accéder au conteneur MinIO
MINIO_CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-minio" --format "{{.ID}}" | head -n 1)

# Créer le bucket
docker exec -it $MINIO_CONTAINER mc mb local/xpeditis-documents

# Définir la politique publique en lecture pour les documents
docker exec -it $MINIO_CONTAINER mc anonymous set download local/xpeditis-documents
```

Ou via la console MinIO :
1. Accédez à `https://minio.xpeditis.com`
2. Connectez-vous avec vos identifiants MinIO
3. Créez un bucket nommé `xpeditis-documents`

## Étape 6 : Créer un Utilisateur Admin

### 6.1 Via l'API (avec curl)

```bash
# Créer une organisation
curl -X POST https://api.xpeditis.com/api/v1/organizations \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Xpeditis Admin",
    "type": "FREIGHT_FORWARDER",
    "address": {
      "street": "123 Rue Exemple",
      "city": "Paris",
      "postalCode": "75001",
      "country": "FR"
    }
  }'

# Récupérer l'ID de l'organisation dans la réponse (ex: org-id-123)

# Créer un utilisateur admin
curl -X POST https://api.xpeditis.com/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@xpeditis.com",
    "password": "VotreMotDePasseAdmin123!",
    "firstName": "Admin",
    "lastName": "Xpeditis",
    "organizationId": "org-id-123"
  }'
```

### 6.2 Via la Base de Données (Direct SQL)

```bash
# Accéder à PostgreSQL
POSTGRES_CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-db" --format "{{.ID}}" | head -n 1)

docker exec -it $POSTGRES_CONTAINER psql -U xpeditis -d xpeditis_prod

# Dans psql, exécuter :
INSERT INTO organizations (id, name, type, address_street, address_city, address_postal_code, address_country, is_active)
VALUES (
  gen_random_uuid(),
  'Xpeditis Admin',
  'FREIGHT_FORWARDER',
  '123 Rue Exemple',
  'Paris',
  '75001',
  'FR',
  true
);

-- Récupérer l'ID de l'organisation
SELECT id, name FROM organizations;

-- Créer un utilisateur (remplacez ORG_ID_ICI par l'UUID réel)
INSERT INTO users (id, email, password, first_name, last_name, role, organization_id, is_active)
VALUES (
  gen_random_uuid(),
  'admin@xpeditis.com',
  '$argon2id$v=19$m=65536,t=3,p=4$VOTRE_HASH_ARGON2',
  'Admin',
  'Xpeditis',
  'ADMIN',
  'ORG_ID_ICI',
  true
);

\q
```

## Étape 7 : Tester l'Application

### 7.1 Vérifier les Services

```bash
# Vérifier que tous les services sont en cours d'exécution
docker service ls | grep xpeditis

# Vérifier les endpoints
curl -I https://api.xpeditis.com/health
curl -I https://app.xpeditis.com
curl -I https://minio.xpeditis.com
```

### 7.2 Tester l'Application Web

1. Ouvrez votre navigateur et accédez à `https://app.xpeditis.com`
2. Connectez-vous avec les identifiants admin créés
3. Testez les fonctionnalités principales :
   - Recherche de tarifs
   - Création de réservation CSV
   - Upload de documents

### 7.3 Vérifier les Certificats SSL

```bash
# Vérifier le certificat SSL
curl -vI https://api.xpeditis.com 2>&1 | grep -i "SSL certificate"
curl -vI https://app.xpeditis.com 2>&1 | grep -i "SSL certificate"
```

## Étape 8 : Monitoring et Logs

### 8.1 Voir les Logs dans Portainer

1. **Stacks** → **xpeditis** → Sélectionnez un service
2. Cliquez sur **"Logs"**
3. Ajustez le nombre de lignes (ex: 500 dernières lignes)

### 8.2 Logs en Ligne de Commande

```bash
# Logs du backend
docker service logs xpeditis_xpeditis-backend -f --tail 100

# Logs du frontend
docker service logs xpeditis_xpeditis-frontend -f --tail 100

# Logs de la base de données
docker service logs xpeditis_xpeditis-db -f --tail 100

# Logs de Redis
docker service logs xpeditis_xpeditis-redis -f --tail 100

# Logs de MinIO
docker service logs xpeditis_xpeditis-minio -f --tail 100
```

### 8.3 Vérifier les Ressources

```bash
# Statistiques des conteneurs
docker stats

# État des services
docker service ls

# Détails d'un service
docker service inspect xpeditis_xpeditis-backend --pretty
```

## Étape 9 : Scaling (Optionnel)

### 9.1 Scaler le Backend

```bash
# Augmenter le nombre de répliques backend à 4
docker service scale xpeditis_xpeditis-backend=4

# Vérifier
docker service ps xpeditis_xpeditis-backend
```

### 9.2 Scaler le Frontend

```bash
# Augmenter le nombre de répliques frontend à 3
docker service scale xpeditis_xpeditis-frontend=3
```

### 9.3 Via Portainer

1. **Stacks** → **xpeditis** → Sélectionnez un service
2. Cliquez sur **"Scale"**
3. Ajustez le nombre de répliques
4. Cliquez sur **"Apply"**

## Étape 10 : Sauvegarde

### 10.1 Sauvegarde PostgreSQL

```bash
# Créer un script de sauvegarde
cat > /opt/backups/backup-xpeditis-db.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/opt/backups/xpeditis"
DATE=$(date +%Y%m%d_%H%M%S)
CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-db" --format "{{.ID}}" | head -n 1)

mkdir -p $BACKUP_DIR

docker exec $CONTAINER pg_dump -U xpeditis xpeditis_prod | gzip > $BACKUP_DIR/xpeditis_db_$DATE.sql.gz

# Garder seulement les 7 dernières sauvegardes
find $BACKUP_DIR -name "xpeditis_db_*.sql.gz" -mtime +7 -delete

echo "Backup completed: xpeditis_db_$DATE.sql.gz"
EOF

chmod +x /opt/backups/backup-xpeditis-db.sh

# Ajouter à crontab (sauvegarde quotidienne à 2h du matin)
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/backups/backup-xpeditis-db.sh") | crontab -
```

### 10.2 Sauvegarde MinIO

```bash
# Créer un script de sauvegarde
cat > /opt/backups/backup-xpeditis-minio.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/opt/backups/xpeditis"
DATE=$(date +%Y%m%d_%H%M%S)
CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-minio" --format "{{.ID}}" | head -n 1)

mkdir -p $BACKUP_DIR

docker exec $CONTAINER tar czf - /data | cat > $BACKUP_DIR/xpeditis_minio_$DATE.tar.gz

# Garder seulement les 7 dernières sauvegardes
find $BACKUP_DIR -name "xpeditis_minio_*.tar.gz" -mtime +7 -delete

echo "Backup completed: xpeditis_minio_$DATE.tar.gz"
EOF

chmod +x /opt/backups/backup-xpeditis-minio.sh

# Ajouter à crontab (sauvegarde quotidienne à 3h du matin)
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/backups/backup-xpeditis-minio.sh") | crontab -
```

## Mise à Jour de l'Application

### 1. Construire les Nouvelles Images

```bash
# Sur votre machine locale
cd /chemin/vers/xpeditis2.0

# Mettre à jour le code (git pull, etc.)
git pull origin main

# Construire les nouvelles images avec un nouveau tag
docker build -t xpeditis/backend:v1.1.0 -f apps/backend/Dockerfile .
docker build -t xpeditis/frontend:v1.1.0 -f apps/frontend/Dockerfile .

# Tag comme latest
docker tag xpeditis/backend:v1.1.0 xpeditis/backend:latest
docker tag xpeditis/frontend:v1.1.0 xpeditis/frontend:latest

# Push vers le registre ou sauvegarder et transférer
```

### 2. Mettre à Jour la Stack dans Portainer

1. **Stacks** → **xpeditis** → **"Editor"**
2. Modifiez les tags d'images si nécessaire
3. Cliquez sur **"Update the stack"**
4. Cochez **"Re-pull image and redeploy"**
5. Cliquez sur **"Update"**

Docker Swarm effectuera un rolling update sans downtime.

## Dépannage

### Le service ne démarre pas

```bash
# Vérifier les logs d'erreur
docker service logs xpeditis_xpeditis-backend --tail 100

# Vérifier les tâches échouées
docker service ps xpeditis_xpeditis-backend --no-trunc

# Inspecter le service
docker service inspect xpeditis_xpeditis-backend --pretty
```

### Certificat SSL non généré

```bash
# Vérifier les logs Traefik
docker service logs traefik --tail 200

# Vérifier que les DNS pointent bien vers le serveur
dig app.xpeditis.com
dig api.xpeditis.com

# Vérifier que le port 80 est accessible (Let's Encrypt challenge)
curl http://app.xpeditis.com
```

### Base de données ne se connecte pas

```bash
# Vérifier que PostgreSQL est prêt
docker service logs xpeditis_xpeditis-db --tail 50

# Tester la connexion depuis le backend
BACKEND_CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-backend" --format "{{.ID}}" | head -n 1)
docker exec -it $BACKEND_CONTAINER nc -zv xpeditis-db 5432
```

### MinIO ne fonctionne pas

```bash
# Vérifier les logs MinIO
docker service logs xpeditis_xpeditis-minio --tail 50

# Vérifier que le bucket existe
MINIO_CONTAINER=$(docker ps --filter "name=xpeditis_xpeditis-minio" --format "{{.ID}}" | head -n 1)
docker exec -it $MINIO_CONTAINER mc ls local/
```

## URLs de l'Application

Une fois déployée, l'application sera accessible via :

- **Frontend** : https://app.xpeditis.com
- **API** : https://api.xpeditis.com
- **API Docs (Swagger)** : https://api.xpeditis.com/api/docs
- **MinIO Console** : https://minio.xpeditis.com
- **MinIO API** : https://s3.xpeditis.com

## Sécurité

### Recommandations

1. **Changez tous les mots de passe** par défaut
2. **Utilisez des secrets Docker** pour les données sensibles
3. **Configurez un firewall** (UFW) pour limiter les ports ouverts
4. **Activez le monitoring** (Prometheus + Grafana)
5. **Configurez des alertes** pour les services en erreur
6. **Mettez en place des sauvegardes automatiques**
7. **Testez régulièrement la restauration** des sauvegardes

### Ports à Ouvrir

```bash
# Firewall UFW
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP (Traefik)
sudo ufw allow 443/tcp   # HTTPS (Traefik)
sudo ufw enable
```

## Support

Pour plus d'informations, consultez :
- [Documentation Xpeditis](../README.md)
- [Architecture](../ARCHITECTURE.md)
- [Deployment Guide](../DEPLOYMENT.md)
