# Déployer WordPress avec rsync : notre script maison, expliqué ligne à ligne

> Pas de plateforme de déploiement sophistiquée, juste un script bash et rsync. Voici comment on déploie nos sites WordPress depuis trois ans, sans mauvaise surprise.

- Auteur : Clément Hadrot
- Publié le : 2020-08-26
- Mis à jour le : 2020-08-26
- Catégorie : Outils &amp; workflow
- URL : https://wpmoderne.dev.wordpress-developpement.fr/outils/deployer-wordpress-rsync-script-maison/

## L’essentiel

- Un script de moins de 50 lignes suffit pour un déploiement fiable
- --exclude protège les uploads et wp-config.php
- --dry-run avant chaque déploiement réel

Avant de s'intéresser à des outils comme Deployer ou à des pipelines CI/CD complets, beaucoup d'agences déploient encore leurs sites WordPress avec `rsync`, tout simplement. Ce n'est pas une solution dépassée : c'est un outil fiable, disponible partout, et parfaitement adapté à la majorité des projets qui n'ont pas besoin de zéro downtime ou de rollback automatisé.

Voici le script qu'on utilise en interne depuis plusieurs mois, affiné projet après projet, avec les explications de chaque option — parce qu'un script rsync mal compris peut aussi bien sauver une mise en production que la saccager.

## Le principe de base de rsync

`rsync` ne copie que les fichiers modifiés, en comparant taille et date de dernière modification entre la source et la destination. C'est ce qui le rend rapide sur des mises à jour incrémentales : un déploiement qui ne touche que trois fichiers PHP ne transfère que ces trois fichiers, pas l'intégralité du thème.

```
rsync -avz --delete \
  --exclude 'wp-content/uploads' \
  --exclude 'wp-config.php' \
  --exclude '.git' \
  --exclude '.env' \
  ./ utilisateur@serveur:/var/www/site/
```

Chaque option a un rôle précis : `-a` pour le mode archive (préserve permissions, liens symboliques, dates), `-v` pour le mode verbeux, `-z` pour compresser les données pendant le transfert. `--delete` est la plus dangereuse : elle supprime sur le serveur tout fichier absent en local. Indispensable pour ne pas accumuler de fichiers fantômes, mais à utiliser avec un `--dry-run` systématique avant le premier essai sur un nouveau projet.

## Le script complet

```
#!/bin/bash
set -e

ENV=$1
SOURCE="./wp-content/themes/mon-theme/"
REMOTE_USER="deploy"
REMOTE_HOST="serveur-${ENV}.exemple.fr"
REMOTE_PATH="/var/www/site/wp-content/themes/mon-theme/"

if [ -z "$ENV" ]; then
  echo "Usage : ./deploy.sh [staging|production]"
  exit 1
fi

echo "Déploiement vers ${ENV}..."
rsync -avz --delete \
  --exclude 'node_modules' \
  --exclude '.git' \
  --exclude '*.map' \
  "$SOURCE" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}"

echo "Vidage du cache distant..."
ssh "${REMOTE_USER}@${REMOTE_HOST}" "cd /var/www/site && wp cache flush"

echo "Déploiement terminé."
```

> L'essentiel à retenir : Un script de moins de 50 lignes suffit pour un déploiement fiable ; --exclude protège les uploads et wp-config.php ; --dry-run avant chaque déploiement réel

Le `set -e` en tête de script n'est pas décoratif : il arrête immédiatement l'exécution si une commande échoue, évitant qu'un déploiement partiel se poursuive silencieusement. On demande toujours l'environnement cible en argument, pour éviter le classique déploiement en production alors qu'on visait le staging.

## Ce que --exclude doit toujours protéger

- `wp-content/uploads` : les médias vivent sur le serveur, pas dans le dépôt de code
- `wp-config.php` ou `.env` : la configuration de chaque environnement lui appartient
- `.git` et `node_modules` : inutiles en production, et lourds à transférer
- les fichiers de cache générés par des plugins comme un cache de pages

Oublier une seule de ces exclusions peut effacer des médias en production ou écraser la configuration de base de données d'un environnement avec celle d'un autre — l'incident classique du premier déploiement mal testé.

## Toujours passer par --dry-run

Avant tout déploiement vers la production, on ajoute systématiquement `--dry-run` à la commande pour visualiser ce qui serait transféré ou supprimé, sans rien exécuter réellement :

```
rsync -avzn --delete --exclude 'wp-content/uploads' ./ utilisateur@serveur:/var/www/site/
```

Le `n` ajouté à `-avz` active ce mode simulation. Sur un script de déploiement automatisé, on le rend même obligatoire pour tout nouveau membre de l'équipe tant qu'il n'a pas trois ou quatre déploiements réussis à son actif.

## Les limites de cette approche

rsync fait très bien ce qu'on lui demande, mais il a des limites qu'il faut connaître avant de s'y fier aveuglément : pas de rollback automatique en cas de problème après déploiement, pas de gestion native du zéro downtime (le site est brièvement dans un état intermédiaire pendant le transfert), et aucune vérification automatique que le site fonctionne après coup. Pour des sites à fort trafic ou des équipes plus grandes, des outils comme Deployer apportent ces garanties supplémentaires — au prix d'une complexité de mise en place plus élevée.

> Notre règle interne : rsync convient tant qu'une interruption de quelques secondes pendant le déploiement n'a pas d'impact business mesurable. Au-delà, il faut regarder du côté du déploiement atomique.

## En résumé

Un script rsync bien pensé reste une solution parfaitement légitime pour déployer un site WordPress, à condition de protéger explicitement les uploads et la configuration, de tester systématiquement en `--dry-run`, et d'accepter ses limites en matière de continuité de service. Ce n'est qu'en dépassant ces limites — trafic important, équipe plus grande, exigence de zéro downtime — qu'on a vraiment besoin d'outiller davantage le déploiement.
