# PASSATION VPS — Migration Fastmail → Google Workspace (exécution sur serveur)

> Document destiné à **Claude Code tournant sur le VPS Linux**. Objectif : finir
> la mise en place puis lancer la migration de masse, plus vite que depuis le
> poste local (WSL). L'essentiel de la « connexion Google » est **déjà
> configuré** — il ne faut SURTOUT PAS la recréer, juste la réutiliser.

## 0. Spécificités de CE VPS

- Hôte : `renova@renova.lorraine.fun` (152.228.229.253), Ubuntu 23.04, x86_64.
- **Utilisateur = `renova`** (home `/home/renova`), donc **≠ `gilles`** : il FAUT
  exécuter le `sed` du §4.3 pour corriger les chemins absolus de `gam.cfg`.
- Archi x86_64 = identique au poste WSL → le binaire GAM copié tourne tel quel.
- **Ubuntu 23.04 est en fin de vie** : `apt update` échoue tant qu'on n'a pas
  repointé les dépôts vers `old-releases.ubuntu.com` (voir §4.2, étape 0).
- Disque ~9,7 Go libres : suffisant, imapsync transfère en flux (rien stocké en
  local) ; surveiller seulement la taille de `~/.migrer/logs/`.

---

## 1. Contexte

On migre des boîtes mail **Fastmail → Google Workspace** :
1. création du compte Workspace de destination via **GAM** (Google Apps Manager) ;
2. copie des mails via **imapsync** (IMAP source → IMAP destination).

La destination Gmail est authentifiée en **XOAUTH2 via un service account GAM**
(délégation domain-wide). **Aucun mot de passe IMAP destination, aucune 2FA.**

Pourquoi le VPS : le poste local est limité en bande passante et le débit est
trop lent. Le VPS (datacenter) va plus vite et permet de paralléliser davantage.

Le script de migration de masse **parallèle** est `migrer-masse-parallele.sh`
(plusieurs boîtes simultanées, barre de progression par boîte). C'est lui qu'on
utilise ici.

---

## 2. La « connexion Google » — NE RIEN RECRÉER

Toute l'authentification Google tient dans **un dossier** : `~/.gam/`.

| Fichier | Rôle | Sensible |
|---|---|---|
| `~/.gam/oauth2service.json` | clé du **service account** ; imapsync l'utilise en XOAUTH2 pour Gmail | 🔴 secret (clé privée) |
| `~/.gam/oauth2.txt` | jeton OAuth de l'**admin** ; autorise GAM à créer les comptes | 🔴 secret |
| `~/.gam/client_secrets.json` | client OAuth du projet GAM | 🔴 secret |
| `~/.gam/gam.cfg` | config GAM (chemins, options) | non |
| `~/bin/gam7/gam` | binaire GAM (GAM7) | non |

Identifiants du service account (pour vérification, non secrets) :

- service account : `gam-project-q07rk@gam-project-q07rk.iam.gserviceaccount.com`
- client_id (délégation) : `106230129250450549157`
- project_id : `gam-project-q07rk`

**La délégation domain-wide** (scope `https://mail.google.com/`) est enregistrée
**dans la console Admin Google**, attachée au `client_id` ci-dessus. Elle est
indépendante de la machine : tant qu'on réutilise le même `oauth2service.json`,
elle fonctionne immédiatement sur le VPS. **Il ne faut donc PAS lancer**
`gam create project`, `gam oauth create`, ni reconfigurer la délégation.

---

## 3. Fichiers à recevoir sur le VPS

L'opérateur (Gilles) copie ces éléments depuis son poste WSL. Commandes rsync à
lui faire exécuter **depuis WSL** (remplacer `gilles@IP_VPS`) — recommander
l'utilisateur **`gilles`** sur le VPS pour que les chemins absolus de `gam.cfg`
correspondent :

```bash
# connexion Google + binaire GAM (le home VPS est /home/renova)
rsync -az --exclude gamcache --exclude 'oauth2.txt.lock' ~/.gam/  renova@renova.lorraine.fun:~/.gam/
rsync -az ~/bin/gam7/  renova@renova.lorraine.fun:~/bin/gam7/

# scripts + données (les .csv contiennent des secrets : voir §7)
rsync -az /mnt/d/dev/qlf/{migrer-masse-parallele.sh,migrer-oauth.sh,etat-import.sh,migrations.csv,comptes-crees.csv,PASSATION-VPS.md,vps-setup.sh} renova@renova.lorraine.fun:~/qlf/
```

Arborescence attendue côté VPS :

```
~/.gam/{oauth2service.json,oauth2.txt,client_secrets.json,gam.cfg}
~/bin/gam7/gam
~/qlf/{migrer-masse-parallele.sh,migrer-oauth.sh,etat-import.sh,migrations.csv,comptes-crees.csv}
```

`migrations.csv` : une ligne d'en-tête puis `dest_email,src_login,src_app_password`.

---

## 4. Tâches d'installation (à faire par toi, Claude Code, sur le VPS)

1. **Vérifier la présence des fichiers** du §3. Si `~/.gam/oauth2service.json`
   ou le binaire `~/bin/gam7/gam` manquent, s'arrêter et demander à l'opérateur
   de relancer le rsync — ne rien recréer.

2. **Installer imapsync + dépendances** (Debian/Ubuntu) :

   ```bash
   # ÉTAPE 0 (ce VPS uniquement) : Ubuntu 23.04 est EOL, repointer les dépôts.
   # Attrape tout miroir se terminant par archive/security.ubuntu.com
   # (y compris les miroirs cloud type nova.clouds.archive.ubuntu.com).
   sudo sed -i -E 's,https?://[a-z0-9._-]*(archive|security)\.ubuntu\.com,http://old-releases.ubuntu.com,g' /etc/apt/sources.list
   sudo sed -i -E 's,https?://[a-z0-9._-]*(archive|security)\.ubuntu\.com,http://old-releases.ubuntu.com,g' /etc/apt/sources.list.d/*.list 2>/dev/null || true

   sudo apt-get update
   sudo apt-get install -y git rsync tmux \
     libauthen-ntlm-perl libcgi-pm-perl libcrypt-openssl-rsa-perl libdata-uniqid-perl \
     libdigest-hmac-perl libdigest-md5-file-perl libdist-checkconflicts-perl \
     libencode-imaputf7-perl libfile-copy-recursive-perl libfile-tail-perl libio-compress-perl \
     libio-socket-inet6-perl libio-socket-ssl-perl libio-tee-perl libjson-webtoken-perl \
     libmail-imapclient-perl libmodule-scandeps-perl libnet-ssleay-perl libpar-packer-perl \
     libproc-processtable-perl libreadonly-perl libregexp-common-perl libsys-meminfo-perl \
     libterm-readkey-perl libtest-fatal-perl libtest-mock-guard-perl libtest-mockobject-perl \
     libtest-requires-perl libtest-simple-perl libunicode-string-perl liburi-perl
   # Module requis pour l'auth XOAUTH2 service-account (pas toujours packagé)
   if ! perl -MCrypt::OpenSSL::PKCS12 -e1 2>/dev/null; then
     sudo apt-get install -y libcrypt-openssl-pkcs12-perl 2>/dev/null || {
       sudo apt-get install -y cpanminus make gcc libssl-dev
       sudo cpanm --notest Crypt::OpenSSL::PKCS12
     }
   fi

   if ! command -v imapsync >/dev/null; then
     tmp=$(mktemp -d); git clone --depth 1 https://github.com/imapsync/imapsync "$tmp/i"
     sudo cp "$tmp/i/imapsync" /usr/local/bin/imapsync; rm -rf "$tmp"
   fi
   imapsync --version | head -1     # doit afficher une version (cible : >= 2.229)
   ```

   (Le dépôt contient `vps-setup.sh` qui fait exactement ça.)

3. **Adapter `gam.cfg` si le home n'est pas `/home/gilles`.** `gam.cfg` contient
   des chemins absolus (`config_dir`, `cache_dir`, `drive_dir`). Si l'utilisateur
   du VPS n'est pas `gilles`, corriger en une commande (idempotent) :

   ```bash
   sed -i "s#/home/gilles#$HOME#g" ~/.gam/gam.cfg
   ```

4. **Permissions des secrets** :

   ```bash
   chmod 700 ~/.gam
   chmod 600 ~/.gam/oauth2service.json ~/.gam/oauth2.txt ~/.gam/client_secrets.json
   chmod 600 ~/qlf/migrations.csv ~/qlf/comptes-crees.csv
   chmod +x ~/bin/gam7/gam ~/qlf/*.sh
   ```

5. **Fins de ligne** : si les scripts viennent de Windows, normaliser :
   `sed -i 's/\r$//' ~/qlf/*.sh ~/qlf/*.csv` (ou `dos2unix`).

---

## 5. Vérifier la connexion Google (avant toute migration)

```bash
export PATH="$HOME/bin/gam7:$PATH"

# a) GAM admin OK (doit lister le domaine sans erreur d'auth)
gam info domain

# b) Si le binaire ne s'exécute pas ("cannot execute binary file"),
#    l'archi diffère. Réinstaller UNIQUEMENT le binaire GAM7, sans toucher ~/.gam :
#      bash <(curl -s -S -L https://raw.githubusercontent.com/GAM-team/GAM/main/src/install-gam.sh)
#    -> répondre NON à la création de projet / config OAuth. ~/.gam est conservé.

# c) Délégation service-account OK pour l'IMAP (scope mail en PASS) :
gam user <un_compte_existant@domaine> check serviceaccount
#    La ligne https://mail.google.com/ doit être "PASS".

# d) Test de bout en bout sur UNE boîte, sans rien copier :
cd ~/qlf
JOBS=1 ./migrer-masse-parallele.sh <un_compte@domaine> --justlogin
#    Doit valider la connexion source (Fastmail) ET destination (Gmail XOAUTH2).
```

Si (c) échoue : la délégation domain-wide n'est pas (ou plus) en place dans la
console Admin Google pour le client_id `106230129250450549157` avec le scope
`https://mail.google.com/`. Ne pas recréer le service account ; il faut
(ré)autoriser ce scope côté console Admin. Commandes de rappel :

```bash
gam print serviceaccount                       # affiche le client_id
gam update domainwidedelegation 106230129250450549157 https://mail.google.com/
```

---

## 6. Lancer la migration de masse

Toujours dans `tmux` pour survivre à une déconnexion SSH :

```bash
tmux new -s migration
cd ~/qlf

# essai à blanc d'abord (mapping des dossiers, ne copie rien)
JOBS=1 ./migrer-masse-parallele.sh <un_compte@domaine> --dry

# puis le lot complet, 3 boîtes en parallèle
JOBS=3 ./migrer-masse-parallele.sh
```

Détacher : `Ctrl-b` puis `d`. Rattacher : `tmux attach -t migration`.

### Réglage de la parallélisation (`JOBS`)
- 2–4 raisonnable. Au-delà, risque de **throttling Gmail/Fastmail** (limites
  IMAP par utilisateur **et par IP**) → plus lent, voire erreurs temporaires.
- Le VPS a une seule IP : monter `JOBS` trop haut concentre toutes les sessions
  sur cette IP. Commencer à 3, surveiller les logs, monter à 4–5 si c'est propre.

### Affichage
Le script montre **une barre par boîte active** (nom + % + mails importés/total),
redessinée en place ; un spinner `analyse des dossiers…` pendant la phase de
comparaison initiale d'imapsync ; puis la synthèse `Réussis / Échecs`. Toute la
verbosité GAM/imapsync part dans `~/.migrer/logs/`.

### Relancer un échec
`JOBS=1 ./migrer-masse-parallele.sh <compte_en_echec@domaine>` — imapsync est
ré-entrant (`--skipcrossduplicates`), il ne recopie pas ce qui est déjà passé.

### Vérification post-migration
`./etat-import.sh` (compare source vs destination). Les comptes créés et leurs
mots de passe temporaires sont consignés dans `~/qlf/comptes-crees.csv`.

---

## 7. Sécurité (important)

- `oauth2service.json`, `oauth2.txt`, `client_secrets.json` et `migrations.csv`
  (mots de passe d'app Fastmail) sont des **secrets**. Transfert par SSH/rsync
  uniquement, `chmod 600`, ne jamais committer ni envoyer ailleurs.
- À la fin de la migration, envisager de supprimer du VPS : `migrations.csv`,
  `comptes-crees.csv`, et `~/.gam/` si le VPS n'est plus utilisé pour
  l'administration Workspace.
- Ne pas afficher le contenu de ces fichiers dans les logs / la sortie.

---

## 8. Dépannage de la barre de progression

Le script lit le `--logfile` d'imapsync pour alimenter chaque barre. La
progression tient compte de l'incrémental d'imapsync :

> **progression = (mails déjà en destination) + (mails copiés cette session) / (total source)**

Une boîte déjà migrée démarre donc proche de 100 % (et non à 0), une première
migration démarre à 0 et grimpe. Motifs par défaut (calés sur imapsync 2.229),
surchargeables par variable d'env :

| Variable | Défaut | Sert à |
|---|---|---|
| `PROGRESS_TOTAL_RE` | `Host1 Nb messages:` | dénominateur (total messages source) |
| `PROGRESS_BASE_RE`  | `Host2 Nb messages:` | valeur de départ (déjà en destination) |
| `PROGRESS_DONE_RE`  | `copied` | incrément (1 ligne `copied` par mail copié) |

- **Barre bloquée à `(analyse des dossiers…)`** longtemps : normal pour une
  grosse boîte (imapsync liste/compare avant de copier). Les compteurs
  n'apparaissent qu'après cette phase (lignes `Host1/Host2 Nb messages: N`).
- **Barre ne démarre pas au bon niveau** : la version d'imapsync nomme ces lignes
  autrement. Les retrouver puis ajuster les regex :
  ```bash
  LOG=$(ls -t ~/.migrer/logs/*_*.log | grep -v '\.run\.log' | head -1)
  grep -iE 'Nb messages|copied|appended' "$LOG" | head
  ```
  ex. `PROGRESS_DONE_RE='appended' JOBS=3 ./migrer-masse-parallele.sh`.

---

## 9. Détails imapsync (rappel)

Commande utilisée par le script (par boîte) :

```bash
imapsync \
  --host1 imap.fastmail.com --port1 993 --ssl1 \
  --user1 <src_login> --password1 <src_app_password> \
  --host2 imap.gmail.com --port2 993 --ssl2 \
  --user2 <dest@domaine> --password2 ~/.gam/oauth2service.json --authmech2 XOAUTH2 \
  --automap --skipcrossduplicates \
  --logdir ~/.migrer/logs --logfile <dest>_<horodatage>.log
```

- `--authmech2 XOAUTH2` + `--password2 <service_account.json>` = auth OAuth
  destination (pas de mot de passe Gmail).
- `--automap` : mappe Sent/Trash/Drafts → libellés Gmail.
- `--skipcrossduplicates` : évite les doublons / rend la reprise sûre.
- `--justlogin` : teste seulement les connexions. `--dry` : teste sans copier.

---

## 10. Variables d'environnement du script

| Variable | Défaut | Note |
|---|---|---|
| `JOBS` | `3` | boîtes en parallèle |
| `MIGRER_CSV` | `migrations.csv` | chemin du CSV |
| `SA_JSON` | `~/.gam/oauth2service.json` | clé service account |
| `GAM_BIN` | `~/bin/gam7/gam` | binaire GAM |
| `SRC_HOST`/`SRC_PORT` | `imap.fastmail.com`/`993` | source |
| `DST_HOST`/`DST_PORT` | `imap.gmail.com`/`993` | destination |
| `CRED_FILE` | `<dossier_script>/comptes-crees.csv` | comptes créés + mdp temporaires |
| `PROGRESS_TOTAL_RE` / `PROGRESS_BASE_RE` / `PROGRESS_DONE_RE` | voir §8 | parsing barres |

---

## Checklist rapide

- [ ] Fichiers reçus (§3) : `~/.gam/`, `~/bin/gam7/gam`, `~/qlf/*`
- [ ] imapsync installé (§4.2)
- [ ] `gam.cfg` adapté si home ≠ `/home/gilles` (§4.3) + permissions (§4.4)
- [ ] `gam info domain` OK et `check serviceaccount` → scope mail PASS (§5)
- [ ] `--justlogin` OK sur une boîte (§5d)
- [ ] `--dry` OK sur une boîte (§6)
- [ ] Lancement `JOBS=3` dans tmux (§6)
- [ ] Vérif post-migration `etat-import.sh` + nettoyage des secrets (§7)
