# Guide de Migration Moodle vers Infrastructure RBER

> Guide pratique basé sur la migration réussie de l'UNSTIM (elearningum.rber.bj)

---

## Table des matières

1. [Prérequis](#1-prérequis)
2. [Phase 1 : Audit de l'environnement source](#2-phase-1--audit-de-lenvironnement-source)
3. [Phase 2 : Préparation infrastructure RBER](#3-phase-2--préparation-infrastructure-rber)
4. [Phase 3 : Sauvegarde des données](#4-phase-3--sauvegarde-des-données)
5. [Phase 4 : Transfert et restauration](#5-phase-4--transfert-et-restauration)
6. [Phase 5 : Configuration post-migration](#6-phase-5--configuration-post-migration)
7. [Phase 6 : Configuration rberConnect (SSO)](#7-phase-6--configuration-rberconnect-sso)
8. [Phase 7 : Validation et mise en production](#8-phase-7--validation-et-mise-en-production)
9. [Troubleshooting](#9-troubleshooting)
10. [Checklist de migration](#10-checklist-de-migration)

---

## 1. Prérequis

### Infrastructure RBER requise

| Composant | Version | Statut |
|-----------|---------|--------|
| Cluster RKE2 | v1.32+ | ✅ Disponible |
| CloudNativePG | v1.24+ | ✅ Disponible |
| Longhorn Storage | v1.7+ | ✅ Disponible |
| HAProxy Ingress | v1.11+ | ✅ Disponible |
| Harbor Registry | v2.11+ | ✅ Disponible |
| Keycloak (rberConnect) | v26+ | ✅ Disponible |

### Accès requis

- SSH vers le serveur Moodle source
- Accès admin Moodle source
- Accès base de données source (MySQL/MariaDB ou PostgreSQL)
- kubectl configuré sur le cluster RBER
- Accès Harbor (harbor.rber.bj)

### Outils sur le poste de travail

```bash
# Vérifier les outils
kubectl version --client
helm version
pg_dump --version      # Si source PostgreSQL
mysqldump --version    # Si source MySQL
rsync --version
```

### Informations à collecter avant de commencer

| Information | Exemple UNSTIM | Votre valeur |
|-------------|----------------|--------------|
| URL source | elearning.unstim.bj | |
| URL cible RBER | elearningum.rber.bj | |
| Version Moodle | 4.x / 5.x | |
| Type BDD source | MySQL / PostgreSQL | |
| Taille BDD | ~2 GB | |
| Taille moodledata | ~50 GB | |
| Namespace K8s | moodle-unstim | |

---

## 2. Phase 1 : Audit de l'environnement source

### 2.1 Informations système

```bash
# Connexion au serveur source
ssh admin@elearning.UNIVERSITE.bj

# Version système
cat /etc/os-release
uname -a

# Version Moodle
sudo -u www-data php /var/www/moodle/admin/cli/version.php

# Version PHP et extensions
php -v
php -m | grep -E "curl|gd|intl|mbstring|pgsql|mysqli|xml|zip|soap|ldap"
```

### 2.2 Audit base de données

**Pour MySQL/MariaDB :**
```bash
mysql -u root -p -e "
SELECT 
    table_schema AS 'Database',
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size_MB'
FROM information_schema.tables
WHERE table_schema = 'moodle'
GROUP BY table_schema;
"
```

**Pour PostgreSQL :**
```bash
sudo -u postgres psql -d moodle -c "
SELECT pg_size_pretty(pg_database_size('moodle')) AS size;
"
```

### 2.3 Statistiques Moodle

```bash
# Remplacer par la commande appropriée selon le type de BDD
mysql -u root -p moodle -e "
SELECT 'Utilisateurs' AS metric, COUNT(*) AS value FROM mdl_user WHERE deleted=0
UNION ALL SELECT 'Cours', COUNT(*) FROM mdl_course WHERE id > 1
UNION ALL SELECT 'Fichiers', COUNT(*) FROM mdl_files WHERE filename != '.'
UNION ALL SELECT 'Devoirs', COUNT(*) FROM mdl_assign;
"
```

### 2.4 Audit moodledata

```bash
# Taille totale
du -sh /var/moodledata/

# Répartition
du -h --max-depth=1 /var/moodledata/ | sort -hr

# Nombre de fichiers
find /var/moodledata -type f | wc -l
```

### 2.5 Plugins installés

```bash
# Liste des plugins
php /var/www/moodle/admin/cli/plugin_list.php > /tmp/plugins_list.txt
cat /tmp/plugins_list.txt

# Plugins custom (local)
ls -la /var/www/moodle/local/

# Thèmes custom
ls -la /var/www/moodle/theme/ | grep -v boost | grep -v classic
```

### 2.6 Configuration actuelle

```bash
# Sauvegarder config.php
cat /var/www/moodle/config.php > /tmp/config.php.backup

# Paramètres critiques à noter
grep -E "wwwroot|dataroot|dbtype|dbhost|dbname|prefix" /var/www/moodle/config.php
```

---

## 3. Phase 2 : Préparation infrastructure RBER

### 3.1 Créer le namespace

```bash
# Variables - ADAPTER selon l'université
UNIVERSITY="unstim"  # uac, una, up, unstim
NAMESPACE="moodle-${UNIVERSITY}"

# Créer le namespace
kubectl create namespace ${NAMESPACE}

# Labelliser
kubectl label namespace ${NAMESPACE} \
  university=${UNIVERSITY} \
  app=moodle \
  environment=production
```

### 3.2 Créer le PVC pour moodledata

```yaml
# moodle-${UNIVERSITY}-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: moodle-${UNIVERSITY}-data
  namespace: moodle-${UNIVERSITY}
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: longhorn
  resources:
    requests:
      storage: 100Gi  # Ajuster selon audit (+50% marge)
```

```bash
kubectl apply -f moodle-${UNIVERSITY}-pvc.yaml
kubectl get pvc -n ${NAMESPACE}
```

### 3.3 Base de données

**Option A : Base dédiée (recommandé pour isolation)**

Créer un cluster CloudNativePG dédié selon le guide infrastructure.

**Option B : Base partagée (utilisé pour UNSTIM)**

Utiliser le cluster PostgreSQL partagé existant :
- Host : `edu-pg-main-rw.shared.svc.cluster.local`
- Créer une base de données dédiée par université

```bash
# Créer la base dans le cluster partagé
kubectl exec -it -n shared edu-pg-main-1 -- psql -U postgres -c "
CREATE DATABASE moodle_${UNIVERSITY};
CREATE USER moodle_${UNIVERSITY} WITH PASSWORD 'MOT_DE_PASSE_FORT';
GRANT ALL PRIVILEGES ON DATABASE moodle_${UNIVERSITY} TO moodle_${UNIVERSITY};
"
```

### 3.4 Déployer Moodle (Helm Bitnami)

```bash
# Ajouter le repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# Créer le fichier values
cat > moodle-${UNIVERSITY}-values.yaml << 'EOF'
image:
  registry: docker.io
  repository: bitnami/moodle
  tag: 4.5.1-debian-12-r0  # Adapter à la version source

moodleSkipInstall: true  # IMPORTANT : on migre, on n'installe pas

postgresql:
  enabled: false  # On utilise CloudNativePG externe

externalDatabase:
  host: edu-pg-main-rw.shared.svc.cluster.local
  port: 5432
  user: moodle
  database: moodle
  type: pgsql

persistence:
  enabled: true
  existingClaim: moodle-UNIVERSITY-data  # Remplacer UNIVERSITY

resources:
  requests:
    memory: "2Gi"
    cpu: "1000m"
  limits:
    memory: "4Gi"
    cpu: "2000m"

replicaCount: 1  # Commencer à 1, augmenter après validation

ingress:
  enabled: true
  ingressClassName: haproxy
  hostname: elearningXX.rber.bj  # Remplacer XX
  annotations:
    haproxy.org/ssl-redirect: "false"

livenessProbe:
  enabled: true
  initialDelaySeconds: 600
  periodSeconds: 30

readinessProbe:
  enabled: true
  initialDelaySeconds: 120
  periodSeconds: 10
EOF

# Installer
helm install moodle-${UNIVERSITY} bitnami/moodle \
  --namespace ${NAMESPACE} \
  --values moodle-${UNIVERSITY}-values.yaml \
  --set externalDatabase.password="MOT_DE_PASSE_DB" \
  --wait --timeout 20m
```

---

## 4. Phase 3 : Sauvegarde des données

### 4.1 Activer le mode maintenance

```bash
# Sur le serveur source
sudo -u www-data php /var/www/moodle/admin/cli/maintenance.php --enable

# Vérifier
curl -I http://elearning.UNIVERSITE.bj
```

### 4.2 Dump de la base de données

**Source MySQL → Cible PostgreSQL :**

```bash
# Dump MySQL
mysqldump -u root -p \
  --single-transaction \
  --quick \
  --lock-tables=false \
  --routines \
  --triggers \
  --hex-blob \
  --default-character-set=utf8mb4 \
  moodle > moodle_dump_$(date +%Y%m%d_%H%M%S).sql

# Compresser
gzip moodle_dump_*.sql
```

**Source PostgreSQL → Cible PostgreSQL :**

```bash
sudo -u postgres pg_dump -Fc moodle > moodle_dump_$(date +%Y%m%d_%H%M%S).dump
```

### 4.3 Archiver moodledata

```bash
# Exclure cache, sessions, temp
tar -czf moodledata_backup_$(date +%Y%m%d_%H%M%S).tar.gz \
  --exclude='cache/*' \
  --exclude='sessions/*' \
  --exclude='temp/*' \
  --exclude='trashdir/*' \
  --exclude='localcache/*' \
  -C /var moodledata

# Vérifier la taille
ls -lh moodledata_backup_*.tar.gz

# Checksum
sha256sum moodledata_backup_*.tar.gz > moodledata.sha256
```

### 4.4 Sauvegarder plugins custom

```bash
tar -czf moodle_plugins_$(date +%Y%m%d).tar.gz \
  -C /var/www/moodle \
  local/ \
  theme/ \
  mod/ \
  blocks/ \
  auth/
```

---

## 5. Phase 4 : Transfert et restauration

### 5.1 Transfert des fichiers

**Option A : Via MinIO (recommandé pour gros volumes)**

```bash
# Sur le serveur source
mc alias set rber http://minio.rber.bj:9000 ACCESS_KEY SECRET_KEY
mc mb rber/migrations/${UNIVERSITY}
mc cp moodle_dump_*.gz rber/migrations/${UNIVERSITY}/
mc cp moodledata_backup_*.tar.gz rber/migrations/${UNIVERSITY}/
```

**Option B : SCP direct**

```bash
scp moodle_dump_*.gz admin@10.29.112.130:/tmp/migration/
scp moodledata_backup_*.tar.gz admin@10.29.112.130:/tmp/migration/
```

### 5.2 Conversion MySQL → PostgreSQL (si nécessaire)

```bash
# Installer pgloader
sudo apt-get install -y pgloader

# Créer le fichier de configuration
cat > migration.load << 'EOF'
LOAD DATABASE
    FROM mysql://user:password@source-server:3306/moodle
    INTO postgresql://moodle:password@edu-pg-main-rw.shared.svc.cluster.local:5432/moodle

WITH include drop, create tables, create indexes, reset sequences

CAST type datetime to timestamp using zero-dates-to-null,
     type date using zero-dates-to-null
EOF

# Exécuter (peut prendre plusieurs heures)
pgloader migration.load
```

**Ou import direct PostgreSQL → PostgreSQL :**

```bash
# Port-forward vers le cluster PG
kubectl port-forward -n shared svc/edu-pg-main-rw 5432:5432 &

# Restaurer
pg_restore -h localhost -U moodle -d moodle moodle_dump_*.dump
```

### 5.3 Restaurer moodledata

**Méthode recommandée avec suivi de progression :**

```bash
# Avec pv pour voir la progression
pv moodledata_backup_*.tar.gz | kubectl exec -i -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- tar -xzf - -C /bitnami/moodledata --strip-components=1 --no-same-owner

# Sans pv
cat moodledata_backup_*.tar.gz | kubectl exec -i -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- tar -xzf - -C /bitnami/moodledata --strip-components=1 --no-same-owner
```

**Suivre la progression (autre terminal) :**

```bash
watch -n 5 'kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- du -sh /bitnami/moodledata'
```

### 5.4 Corriger les permissions

```bash
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- chown -R 1001:1001 /bitnami/moodledata
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- chmod -R 755 /bitnami/moodledata
```

---

## 6. Phase 5 : Configuration post-migration

### 6.1 Configurer config.php

**⚠️ Point critique** - Un config.php mal configuré casse l'affichage (CSS non chargé).

```bash
kubectl exec -i -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- bash -c 'cat > /bitnami/moodle/config.php' << 'EOF'
<?php  // Moodle configuration file
unset($CFG);
global $CFG;
$CFG = new stdClass();

// === DATABASE ===
$CFG->dbtype    = 'pgsql';
$CFG->dblibrary = 'native';
$CFG->dbhost    = 'edu-pg-main-rw.shared.svc.cluster.local';  // Adapter si base dédiée
$CFG->dbname    = 'moodle';      // Adapter : moodle_uac, moodle_una, etc.
$CFG->dbuser    = 'moodle';      // Adapter
$CFG->dbpass    = 'MOT_DE_PASSE';  // Adapter
$CFG->prefix    = 'mdl_';
$CFG->dboptions = array(
  'dbpersist' => 0,
  'dbport'    => 5432,
  'dbsocket'  => '',
);

// === URL ===
if (empty($_SERVER['HTTP_HOST'])) {
  $_SERVER['HTTP_HOST'] = '127.0.0.1:8080';
}

// Détection automatique HTTP/HTTPS
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
  $CFG->wwwroot = 'https://elearningXX.rber.bj';  // Adapter XX
} else {
  $CFG->wwwroot = 'http://elearningXX.rber.bj';   // Adapter XX
}

// === PATHS ===
$CFG->dataroot  = '/bitnami/moodledata';
$CFG->admin     = 'admin';
$CFG->directorypermissions = 02775;

// === PERFORMANCE (optionnel) ===
$CFG->cachejs = true;
$CFG->langstringcache = true;

// === PROXY SETTINGS (si derrière HAProxy) ===
$CFG->reverseproxy = true;
$CFG->sslproxy = true;  // Si HTTPS terminé au niveau ingress

require_once(__DIR__ . '/lib/setup.php');
EOF
```

### 6.2 Purger les caches

```bash
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php /bitnami/moodle/admin/cli/purge_caches.php
```

### 6.3 Mettre à jour les URLs dans la base

```bash
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php /bitnami/moodle/admin/cli/replace.php \
  --search="http://elearning.ANCIEN-DOMAINE.bj" \
  --replace="https://elearningXX.rber.bj" \
  --non-interactive
```

### 6.4 Exécuter les mises à jour de base

```bash
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php /bitnami/moodle/admin/cli/upgrade.php --non-interactive
```

---

## 7. Phase 6 : Configuration rberConnect (SSO)

rberConnect utilise Keycloak pour l'authentification centralisée. Cette configuration permet aux utilisateurs de se connecter avec leurs identifiants universitaires unifiés.

### 7.1 Prérequis Keycloak

Vérifier que le client Moodle existe dans Keycloak :
- **Realm** : rber
- **Client ID** : moodle-UNIVERSITY (ex: moodle-unstim)
- **Client Protocol** : openid-connect
- **Access Type** : confidential
- **Valid Redirect URIs** : https://elearningXX.rber.bj/*

### 7.2 Récupérer les informations Keycloak

```bash
# URLs Keycloak RBER
KEYCLOAK_URL="https://auth.rber.bj"
REALM="rber"

# Endpoints (à vérifier)
# Authorization: ${KEYCLOAK_URL}/realms/${REALM}/protocol/openid-connect/auth
# Token: ${KEYCLOAK_URL}/realms/${REALM}/protocol/openid-connect/token
# Userinfo: ${KEYCLOAK_URL}/realms/${REALM}/protocol/openid-connect/userinfo
```

### 7.3 Activer OAuth2 dans Moodle

**Étape 1 : Accéder à l'administration**

1. Aller sur `https://elearningXX.rber.bj/admin`
2. Se connecter en tant qu'administrateur
3. Naviguer vers : **Administration du site** → **Plugins** → **Authentification** → **Gestion de l'authentification**

**Étape 2 : Activer OAuth 2**

1. Dans la liste des plugins d'authentification, activer **OAuth 2**
2. Cliquer sur **Réglages** à côté de OAuth 2

**Étape 3 : Créer un service OAuth 2**

1. Aller dans : **Administration du site** → **Serveur** → **Services OAuth 2**
2. Cliquer sur **Créer un nouveau service personnalisé**

### 7.4 Configuration du service OAuth 2

Remplir les champs suivants :

| Champ | Valeur |
|-------|--------|
| **Nom** | rberConnect |
| **Client ID** | moodle-UNIVERSITY |
| **Client secret** | (récupérer dans Keycloak) |
| **Authenticate token requests via HTTP headers** | ✅ Oui |
| **Service Base URL** | https://auth.rber.bj/realms/rber |
| **Scopes** | openid profile email |

**Endpoints à configurer :**

| Endpoint | URL |
|----------|-----|
| **Authorization endpoint** | https://auth.rber.bj/realms/rber/protocol/openid-connect/auth |
| **Token endpoint** | https://auth.rber.bj/realms/rber/protocol/openid-connect/token |
| **Userinfo endpoint** | https://auth.rber.bj/realms/rber/protocol/openid-connect/userinfo |
| **JWKS URL** | https://auth.rber.bj/realms/rber/protocol/openid-connect/certs |

### 7.5 Mapper les attributs utilisateur

Dans la configuration du service OAuth 2, configurer le **User field mappings** :

| Champ Moodle | Claim OAuth 2 |
|--------------|---------------|
| username | preferred_username |
| email | email |
| firstname | given_name |
| lastname | family_name |

### 7.6 Configuration via CLI (alternative)

```bash
kubectl exec -it -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- bash

# Dans le pod
php /bitnami/moodle/admin/cli/cfg.php --name=auth --set=oauth2
php /bitnami/moodle/admin/cli/cfg.php --name=authpreventaccountcreation --set=0
php /bitnami/moodle/admin/cli/cfg.php --name=allowaccountssameemail --set=1

exit
```

### 7.7 Créer le service OAuth 2 via SQL (avancé)

```sql
-- Exécuter dans la base Moodle
INSERT INTO mdl_oauth2_issuer (
    name, 
    clientid, 
    clientsecret, 
    baseurl,
    loginscopes,
    loginscopesoffline,
    enabled,
    showonloginpage
) VALUES (
    'rberConnect',
    'moodle-UNIVERSITY',
    'CLIENT_SECRET_ICI',
    'https://auth.rber.bj/realms/rber',
    'openid profile email',
    'openid profile email offline_access',
    1,
    1
);
```

### 7.8 Tester l'authentification

1. Ouvrir une fenêtre de navigation privée
2. Aller sur `https://elearningXX.rber.bj/login/`
3. Cliquer sur le bouton **rberConnect** (ou équivalent)
4. Être redirigé vers Keycloak
5. Se connecter avec les identifiants universitaires
6. Être redirigé vers Moodle, connecté

### 7.9 Configuration Keycloak côté serveur

Si le client n'existe pas encore dans Keycloak :

```bash
# Se connecter à Keycloak Admin
# https://auth.rber.bj/admin/

# Créer le client :
# 1. Realm : rber
# 2. Clients → Create client
# 3. Client ID : moodle-UNIVERSITY
# 4. Client Protocol : openid-connect
# 5. Root URL : https://elearningXX.rber.bj
# 6. Valid redirect URIs : https://elearningXX.rber.bj/*
# 7. Web origins : https://elearningXX.rber.bj
# 8. Access Type : confidential
# 9. Sauvegarder et récupérer le secret dans l'onglet Credentials
```

---

## 8. Phase 7 : Validation et mise en production

### 8.1 Tests fonctionnels

| Test | Commande / Action | Résultat attendu |
|------|-------------------|------------------|
| Page d'accueil | `curl -I https://elearningXX.rber.bj` | HTTP 200, CSS chargé |
| Login admin | Se connecter via navigateur | Accès au tableau de bord |
| Login SSO | Cliquer sur rberConnect | Redirection Keycloak → Moodle |
| Upload fichier | Ajouter un fichier dans un cours | Fichier accessible |
| Téléchargement | Télécharger un fichier existant | Téléchargement OK |
| Cours existants | Vérifier la liste des cours | Tous les cours présents |
| Utilisateurs | Administration → Utilisateurs | Comptes migrés |

### 8.2 Vérification des données

```bash
# Compter les utilisateurs
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php -r "
require('/bitnami/moodle/config.php');
global \$DB;
echo 'Utilisateurs actifs: ' . \$DB->count_records('user', ['deleted' => 0]) . PHP_EOL;
echo 'Cours: ' . \$DB->count_records('course') . PHP_EOL;
"
```

### 8.3 Test de performance

```bash
# Test basique avec curl
time curl -s -o /dev/null -w "%{http_code}" https://elearningXX.rber.bj

# Test de charge (si ab disponible)
ab -n 100 -c 10 https://elearningXX.rber.bj/
```

### 8.4 Configuration DNS

Coordonner avec l'administrateur réseau :

```dns
; Zone RBER
elearningXX.rber.bj.    IN  A    10.29.112.100  ; IP HAProxy VIP

; Optionnel : ancien domaine en redirection
elearning.UNIVERSITY.bj. IN  CNAME  elearningXX.rber.bj.
```

### 8.5 Désactiver la maintenance sur l'ancien serveur

```bash
# Sur l'ancien serveur (si toujours accessible)
sudo -u www-data php /var/www/moodle/admin/cli/maintenance.php --disable

# Ou éteindre l'ancien serveur après validation complète
```

### 8.6 Communication aux utilisateurs

```
Objet : ✅ Migration réussie - Nouvelle plateforme e-learning

Chers utilisateurs,

La plateforme e-learning de [UNIVERSITÉ] est maintenant accessible sur :
🔗 https://elearningXX.rber.bj

Nouveautés :
- Connexion simplifiée via rberConnect (identifiants universitaires)
- Performances améliorées
- Disponibilité renforcée

Vos cours et données ont été migrés. Vos identifiants restent les mêmes.

Support : support@rber.bj
```

---

## 9. Troubleshooting

### 9.1 CSS ne charge pas (page sans style)

**Cause :** `wwwroot` incorrect dans config.php

```bash
# Vérifier
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- grep wwwroot /bitnami/moodle/config.php

# Le protocole (http/https) doit correspondre à l'URL utilisée
# Corriger si nécessaire
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- sed -i "s|http://|https://|g" /bitnami/moodle/config.php

# Purger le cache
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php /bitnami/moodle/admin/cli/purge_caches.php

# Vider le cache du navigateur : Ctrl+Shift+R
```

### 9.2 Erreur de connexion base de données

```bash
# Vérifier la connectivité
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php -r "
\$conn = pg_connect('host=edu-pg-main-rw.shared.svc.cluster.local port=5432 dbname=moodle user=moodle password=XXX');
if (\$conn) { echo 'DB OK'.PHP_EOL; } else { echo 'DB FAIL'.PHP_EOL; }
"

# Vérifier les credentials dans config.php
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- grep -E "dbhost|dbname|dbuser|dbpass" /bitnami/moodle/config.php
```

### 9.3 Erreur 502 Bad Gateway

```bash
# Vérifier le pod
kubectl get pods -n ${NAMESPACE}
kubectl logs -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} --tail=50

# Vérifier l'ingress
kubectl get ingress -n ${NAMESPACE}
kubectl describe ingress -n ${NAMESPACE}

# Vérifier le service
kubectl get svc -n ${NAMESPACE}
```

### 9.4 Fichiers non accessibles

```bash
# Vérifier les permissions
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- ls -la /bitnami/moodledata/

# Corriger
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- chown -R 1001:1001 /bitnami/moodledata
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- chmod -R 755 /bitnami/moodledata
```

### 9.5 rberConnect ne fonctionne pas

```bash
# Vérifier que OAuth2 est activé
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- php /bitnami/moodle/admin/cli/cfg.php --name=auth

# Tester la connectivité vers Keycloak
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- curl -I https://auth.rber.bj/realms/rber/.well-known/openid-configuration

# Vérifier les logs
kubectl logs -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} | grep -i oauth
```

### 9.6 Pod en CrashLoopBackOff

```bash
# Voir les logs du pod précédent
kubectl logs -n ${NAMESPACE} -l app.kubernetes.io/name=moodle --previous

# Vérifier les events
kubectl get events -n ${NAMESPACE} --sort-by='.lastTimestamp' | tail -20

# Vérifier les ressources
kubectl describe pod -n ${NAMESPACE} -l app.kubernetes.io/name=moodle
```

### 9.7 Commandes de diagnostic générales

```bash
# État général
kubectl get all -n ${NAMESPACE}

# Logs en temps réel
kubectl logs -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -f

# Entrer dans le pod
kubectl exec -it -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- bash

# Vérifier le config.php complet
kubectl exec -n ${NAMESPACE} deploy/moodle-${UNIVERSITY} -- cat /bitnami/moodle/config.php
```

---

## 10. Checklist de migration

### Avant la migration

- [ ] Audit de l'environnement source complété
- [ ] Taille de stockage estimée (+50% marge)
- [ ] Namespace créé
- [ ] PVC créé
- [ ] Base de données préparée
- [ ] Fenêtre de maintenance planifiée et communiquée

### Sauvegarde

- [ ] Mode maintenance activé sur source
- [ ] Dump base de données effectué
- [ ] Checksum du dump vérifié
- [ ] Archive moodledata créée
- [ ] Checksum moodledata vérifié
- [ ] Plugins custom sauvegardés
- [ ] config.php sauvegardé

### Transfert et restauration

- [ ] Fichiers transférés vers RBER
- [ ] Checksums vérifiés après transfert
- [ ] Base de données restaurée (conversion MySQL→PG si nécessaire)
- [ ] Moodledata restauré
- [ ] Permissions corrigées (1001:1001)

### Configuration

- [ ] config.php configuré correctement
- [ ] wwwroot correspond au protocole utilisé (HTTP/HTTPS)
- [ ] Caches purgés
- [ ] URLs mises à jour dans la base
- [ ] Upgrade Moodle exécuté

### rberConnect (SSO)

- [ ] Client Keycloak créé/vérifié
- [ ] Service OAuth 2 créé dans Moodle
- [ ] Endpoints configurés
- [ ] Mapping attributs configuré
- [ ] Test de connexion SSO réussi

### Validation

- [ ] Page d'accueil charge avec CSS
- [ ] Login administrateur fonctionne
- [ ] Login utilisateur standard fonctionne
- [ ] Login SSO (rberConnect) fonctionne
- [ ] Cours existants visibles
- [ ] Upload de fichiers fonctionne
- [ ] Téléchargement de fichiers fonctionne
- [ ] Nombre d'utilisateurs correspond
- [ ] Nombre de cours correspond

### Mise en production

- [ ] DNS configuré
- [ ] Certificat SSL valide (si applicable)
- [ ] Ancien serveur maintenance désactivée ou éteint
- [ ] Communication utilisateurs envoyée
- [ ] Monitoring configuré
- [ ] Backup automatique configuré

---

## Annexe : Correspondance des universités

| Université | Code | Namespace | URL RBER | Client Keycloak |
|------------|------|-----------|----------|-----------------|
| UNSTIM | unstim | moodle-unstim | elearningum.rber.bj | moodle-unstim |
| UAC | uac | moodle-uac | elearningac.rber.bj | moodle-uac |
| UNA | una | moodle-una | elearningna.rber.bj | moodle-una |
| UP | up | moodle-up | elearningup.rber.bj | moodle-up |

---

**Version** : 2.0  
**Basé sur** : Migration UNSTIM - Décembre 2025  
**Contact** : devops@rber.bj