
Pourquoi utiliser Git pour maintenir WordPress ?
WordPress reste l’un des systèmes de gestion de contenu les plus utilisés au monde, mais sa méthode traditionnelle de maintenance n’a presque pas changé :
on met à jour depuis l’interface d’administration, on installe des plugins, on ajoute du code dans un thème enfant, et on croise les doigts pour que tout se passe bien.
Cette approche fonctionne pour un blog personnel, mais dès qu’un site devient un peu plus complexe ou qu’on souhaite travailler proprement — en séparant un environnement de développement d’un environnement de production — les limites apparaissent très vite :
- pas d’historique clair des changements,
- impossible de tester une mise à jour avant de l’appliquer en production,
- difficulté à revenir en arrière,
- fichiers modifiés directement sur le serveur,
- risques d’erreurs humaines,
- sauvegardes parfois insuffisantes ou incomplètes.
Aujourd’hui, même sur un hébergement mutualisé, il est possible — et conseillé — d’adopter des pratiques beaucoup plus professionnelles.
Git, associé à une stack locale (ici Lando), transforme complètement la manière de maintenir un site WordPress :
- on travaille localement sans risque,
- on teste les mises à jour avant de les appliquer,
- chaque modification est tracée,
- on déploie proprement via Git plutôt qu’en FTP,
- et on sécurise durablement son site sans dépendre uniquement des sauvegardes automatiques de l’hébergeur.
Ce workflow modernisé permet d’aborder WordPress non plus comme un simple CMS “à cliquer”, mais comme un véritable projet de développement où :
- le code est versionné,
- la configuration est centralisée,
- les environnements sont distincts,
- et les déploiements sont reproductibles.
L’objectif de cet article est de montrer, étape par étape, comment structurer et maintenir un site WordPress grâce à Git, en synchronisant un environnement local et un environnement de production — même sur un hébergement mutualisé.
Nous verrons notamment :
- ce qu’il faut (et ne faut pas) versionner,
- comment organiser le projet,
- comment maintenir un workflow propre entre local et production,
- comment déployer des changements en toute sécurité,
- comment s’appuyer sur Composer et WP-CLI quand c’est utile,
- tout en restant compatible avec un usage WordPress classique.
Ce guide s’adresse donc aux utilisateurs WordPress avancés, développeurs ou administrateurs techniques, qui souhaitent professionnaliser leur manière de travailler sans pour autant basculer dans une architecture trop complexe ou inaccessible.
Dans cet article, voici les principaux points abordés :
Dépôt GitHub compagnon
Pour compléter cet article, j’ai mis en ligne un dépôt GitHub volontairement minimal.
Il ne s’agit pas d’un projet WordPress prêt à l’emploi, mais d’un support technique :
- un .gitignore issu d’un site réel en production
- quelques notes opérationnelles
- un point d’entrée durable entre GitHub et cet article
👉 Le dépôt sert à héberger ce qui a plus de sens dans Git que dans un article.
🔗 https://github.com/manooweb/wordpress-git-workflow
L’article reste la référence pour la démarche et le raisonnement global.
🧰 1. Prérequis techniques
Avant de mettre en place un workflow Git entre votre environnement local et votre hébergement, il est essentiel de poser quelques bases.
Nous n’entrons pas ici dans l’installation détaillée de chaque outil : chacun possède une documentation claire et largement disponible.
L’objectif est simplement de s’assurer que vous disposez des outils indispensables pour suivre ce guide, effectuer vos déploiements, et maintenir WordPress de manière fiable et reproductible.
Ces prérequis sont volontairement orientés “bonne pratique” : ils reflètent un workflow réellement utilisable sur un site WordPress de production — pas un environnement de test ou de démonstration.
🔧 Outils nécessaires
1. Git
Git est au cœur de ce workflow.
Vous en aurez besoin :
- en local, pour versionner les changements que vous faites sur votre thème, plugins, ou configuration,
- et sur l’hébergement, pour mettre à jour votre site via un simple
git pull.
Important : votre hébergeur doit proposer Git en SSH.
✔ o2switch, ✔ Infomaniak, ✔ OVH mutualisé, ✔ Ionos (offre linux + SSH)
2. Une stack locale WordPress
Travailler proprement nécessite un environnement local fiable.
Dans ce guide, nous utiliserons Lando car :
- une stack PHP/MariaDB prête à l’emploi,
- il intègre composer et WP-CLI dans la recette pour WordPress
- Il gère SSL nativement
- il permet de très facilement ajouter de l’outillage (phpMyAdmin, mailpit, etc.)
- il permet de reproduire facilement la configuration du serveur (Redis, Memcached),
Mais vous pouvez utiliser ce que vous voulez (LocalWP, Docker, LAMP, MAMP, WAMP etc.).
3. Accès SSH à l’hébergement
Indispensable pour :
- lancer
git pulldirectement sur la production, - exécuter des commandes WP-CLI en cas de besoin (désactiver un plugin, réparer la base…),
- lancer composer si nécessaire,
- faire un minimum d’administration.
Sans SSH → pas de workflow Git viable..
4. WP-CLI
Très pratique pour :
- désactiver un plugin cassé (
wp plugin deactivate) - effectuer un search-replace propre
- vider le cache
- forcer une mise à jour DB (
wp core update-db)
Non indispensable à chaque étape du workflow, mais essentiel en cas :
- d’erreur fatale,
- d’urgence,
- de migration.
La plupart des hébergeurs qui proposent de l’hébergement spécifiquement pour WordPress l’intègrent par défaut.
(✔ o2switch par exemple)
5. Composer
Utilisé exclusivement pour :
- charger
phpdotenv, - gérer des dépendances PHP dans votre projet WordPress,
- optimiser l’autoload sur le serveur.
Composer doit être installé localement et présent sur l’hébergement.
(✔ o2switch par exemple)
6. Un éditeur de code moderne
Pour travailler efficacement localement sur le code de votre site.
Exemples :
- VS Code
- PhpStorm
- Sublime Text
- etc.
7. Une compréhension minimale de ce qu’on versionne dans Git
Il n’est pas nécessaire d’être expert Git, mais indispensable de comprendre :
- ce que vous ajoutez au dépôt,
- ce que vous ignorez,
- pourquoi certains fichiers ne doivent jamais être versionnés,
- pourquoi certains doivent impérativement l’être.
La section 3 de ce guide détaillera ce point.
En résumé
Pour suivre ce guide, vous avez besoin :
- d’un Git fonctionnel local + hébergement
- d’une stack locale WordPress (Lando conseillé)
- d’un accès SSH sur la production
- de WP-CLI
- de Composer
- d’un éditeur moderne
- et d’une compréhension minimale de ce qu’on met (ou pas) dans Git.
🗂️ 2. Structure Git recommandée pour un projet WordPress
Avant de parler de workflow, il est important de savoir comment votre projet est structuré :
où se trouve le code, où se trouve la configuration, où commence réellement le dépôt Git.
L’idée est de séparer :
- un dossier projet, qui contient tout ce qui entoure le site (config Lando, fichier
.env, etc.) ; - un webroot, qui correspond à la racine publique de votre site (là où pointe le domaine) et qui sert aussi de racine du dépôt Git.
Cette structure vous permet :
- d’avoir un code identique entre local et production ;
- de garder les secrets et certains fichiers de configuration en dehors de la zone publique ;
- de maîtriser exactement ce qui est versionné… et ce qui ne l’est pas (détaillé en section 3).
2.1 Vue d’ensemble : arborescence du projet
Voici l’arborescence de base que nous allons utiliser :
project-root/
├── .env ← fichier d’environnement (non versionné, hors webroot)
├── .env.production ← copie de sauvegarde de la config de prod (optionnelle, non versionnée)
├── .lando.yml ← configuration Lando (environnement local)
└── webroot/ ← racine publique du site ET racine du dépôt Git
├── .git/ ← dépôt Git
├── .gitignore ← règles d’ignorance Git
├── composer.json ← dépendances PHP du projet (versionné)
├── wp-config.php ← configuration WordPress (commune local / prod)
├── env-loader.php ← chargement de .env via phpdotenv
├── wp-admin/
├── wp-includes/
├── wp-content/
│ ├── plugins/ ← plugins (versionnés)
│ ├── mu-plugins/ ← must-use plugins (versionnés)
│ ├── themes/ ← thèmes (versionnés)
│ ├── uploads/ ← médias (NON versionnés)
│ └── cache/ ← caches divers (NON versionnés)
├── vendor/ ← dépendances Composer générées (NON versionné)
└── index.php, etc.
Quelques points importants à retenir :
- le dépôt Git est initialisé dans
webroot/(git initlancé dans ce dossier) ; - le fichier
.gitignorese trouve donc danswebroot/; - le fichier
.envest au niveauproject-root/→ il n’est pas dans le dépôt, il n’est pas accessible en HTTP ; composer.jsonest versionné danswebroot/pour pouvoir exécutercomposer installsur l’hébergement ;vendor/n’est pas versionné : il est régénéré à partir decomposer.json;- tout le code WordPress (core, thèmes, plugins, mu-plugins) est suivi par Git.
2.2 Dépôt Git : le cœur du workflow
Dans ce guide, le code de référence de votre site est celui du dépôt Git, pas celui de la production.
Concrètement :
- vous travaillez en local sur le code contenu dans
webroot/(thèmes, plugins, core, etc.) ; - vous commitez vos modifications (mise à jour d’un plugin, changement dans un thème, ajout d’un mu-plugin…) ;
- vous poussez vers votre remote (GitHub, GitLab, etc.) ;
- vous mettez à jour la production via
git pulldepuis ce même dépôt.
Les mises à jour WordPress (core et plugins) ne sont donc pas des opérations “magiques” en production, mais deviennent :
- mises à jour en local (via l’admin ou WP-CLI),
- tests en local,
- commit des fichiers modifiés,
- déploiement via Git sur l’hébergement.
💡 Idée clé
La production ne doit jamais être la “source de vérité” du code.
C’est le dépôt Git (et donc votre environnement local) qui fait foi.
On ne commit jamais depuis la production : on y déploie uniquement ce qui a été testé et validé en local.
Il peut y avoir les mises à jour automatiques sur la production; elles créeront un déphasage avec le dépôt Git mais une fois que vous aurez fait les vérifications en local et valider les modifications, vous pourrez parfaitement venir écrasez la production à partir du dépôt Git.
La manière dont vous ignorez certains fichiers (uploads, caches, vendor, etc.) sera détaillée dans la section 3, avec un .gitignore complet.
2.3 Composer, vendor/ et fichiers composer.*
Nous utiliserons Composer pour gérer les dépendances PHP (comme vlucas/phpdotenv) directement dans le webroot.
Les choix retenus dans ce workflow sont :
composer.jsonest versionné danswebroot/;composer.lockn’est pas versionné : il est régénéré lorsque nécessaire et vous ne faites jamais decomposer updateen production ;vendor/est exclu du dépôt (généré localement et sur l’hébergement aveccomposer install) ;- le dossier
vendor/est protégé en HTTP via.htaccess(voir section sécurité).
En pratique :
- en local, vous faites
composer installaprès un clone ou un pull ; - sur l’hébergement, vous faites également
composer install(oucomposer install --no-dev --optimize-autoloader) après ungit pull, si une dépendance a été ajoutée ou modifiée.
2.4 Où interviennent .env et env-loader.php ?
Pour que votre code soit strictement identique entre local et production tout en ayant des paramètres différents (base de données, URL, etc.), la configuration passe par un fichier .env commun et un chargeur dédié :
- le fichier
.envest situé dansproject-root/(hors webroot, non versionné) ; - son contenu est différent en local et en production (identifiants, URLs…) mais son nom reste le même ;
- vous pouvez conserver une copie de sauvegarde
.env.production(toujours hors webroot et non versionnée) pour la configuration réelle de la production ; - le fichier
env-loader.php(danswebroot/) se charge de lire ce.envviaphpdotenvdès le chargement de WordPress, et d’exposer les valeurs àwp-config.php.
Cette approche garantit :
- un seul code source pour tous les environnements ;
- des secrets jamais versionnés ;
- un même
wp-config.phppour local et production, entièrement piloté par les variables d’environnement.
Les détails d’implémentation de env-loader.php, de l’intégration dans wp-config.php et des règles .htaccess associées seront expliqués plus loin — l’important ici est de visualiser où se trouvent les fichiers et qui est responsable de quoi dans l’arborescence.
📦 3. Ce qu’il faut versionner / ne pas versionner
Avant d’aller plus loin dans le workflow Git entre local et production, il est indispensable de bien définir ce qui doit être présent dans le dépôt — et ce qui ne doit surtout pas l’être.
L’objectif n’est pas d’apprendre Git, mais de clarifier les règles essentielles pour maintenir un projet WordPress propre, reproductible et cohérent entre vos environnements.
Les sous-sections suivantes décrivent précisément quels fichiers doivent être versionnés, lesquels doivent être ignorés, et pourquoi.
3.1. Les fichiers et dossiers à versionner
Pour assurer une maintenance fiable du site, le code source doit être synchronisé entre local et production.
Le dépôt Git doit donc contenir :
✔ Le cœur WordPress (wp-admin + wp-includes+fichiers à la racine)
Même si WordPress est mis à jour automatiquement sur la production, c’est la version présente dans votre dépôt Git qui fait foi.
Les mises à jour automatiques en production peuvent créer un décalage temporaire, mais :
une fois la mise à jour testée et validée en local, vous pourrez la confirmer dans Git et déployer proprement, en écrasant la version du serveur.
C’est la logique du workflow :
→ la production reflète le dépôt Git, pas l’inverse.
✔ Le dossier wp-content/themes
Inclut votre thème enfant, vos thèmes custom, et tout code spécifique.
Les thèmes tiers se traitent de la même manière que le core :
→ mise à jour en local → validation → commit → déploiement.
✔ Le dossier wp-content/plugins
Tous les plugins doivent être versionnés, qu’ils soient :
- gratuits,
- premium,
- propres à votre site.
Les mises à jour automatiques ne posent pas de problème :
→ elles créent simplement un déphasage temporaire avant votre prochain déploiement Git.
✔ Le dossier wp-content/mu-plugins
Les MU-plugins étant souvent critiques, ils doivent impérativement être synchronisés via Git.
✔ Le fichier wp-config.php (incluant env-loader.php)
C’est un fichier fondamental du projet.
Il doit rester strictement identique entre local et production, et donc être versionné.
Pour information
Historiquement, wp-config.php ne devait jamais être versionné car il contenait les mots de passe et réglages propres à chaque environnement.
Dans ce workflow, le fichier ne contient plus aucune donnée sensible : tout est externalisé dans un fichier .env chargé via env-loader.php.wp-config.php redevient ainsi un fichier de configuration “structurelle”, identique entre local et production — et parfaitement compatible avec un dépôt Git.
3.2. Les fichiers et dossiers à ne pas versionner
Certaines données :
- sont volumineuses,
- sont générées automatiquement,
- dépendent d’un environnement,
→ elles n’ont rien à faire dans Git.
🚫 wp-content/uploads
Les médias doivent être synchronisés par un autre moyen (rsync, SSH, plugin de migration), mais jamais versionnés.
🚫 Caches, transients, sessions
wp-content/cache/
wp-content/litespeed/
wp-content/wflogs/
wp-content/_wp_generated/
🚫 Backups de base de données
*.sql
*.sql.gz
*.sql.zip
🚫 Fichiers journaux ou temporaires
*.log
*.tmp
🚫 Le dossier vendor/ à la racine du webroot
Ce dossier doit être régénéré via Composer :
composer install --no-dev --optimize-autoloader
Les vendor/ internes aux plugins ou au core WordPress ne doivent pas être ignorés :
→ ils font partie de leur code.
🚫 Les fichiers .env
Ils ne sont pas dans le webroot, et donc déjà hors périmètre du dépôt.
La règle dans .gitignore sert uniquement à éviter une copie accidentelle dans le mauvais dossier.
🚫 Le fichier wp-config-sample.php
Une fois votre installation ce fichier d’example n’a plus aucun intérêt et ne doit pas être conservé dans votre dépôt git.
A chaque mise à jour de WordPress, ce fichier va réapparaître et il est donc utile de l’ignorer pour qu’il ne soit pas conservé dans le depôt git et par conséquence être livré sur l’hébergement de votre site en production.
3.3. Ignorer globalement les fichiers système / éditeur
Certains fichiers ne concernent que votre poste de travail : fichiers système (Linux, macOS, Windows), fichiers temporaires, répertoires d’IDE, etc.
Ils n’ont aucune raison d’apparaître dans un dépôt Git, mais il est préférable de ne pas polluer le .gitignore du projet avec ces règles personnelles.
Git permet de définir un fichier .gitignore global, utilisé sur tous vos dépôts :
git config --global core.excludesfile ~/.gitignore
Créez le fichier dans le dossier de votre profil utilisateur.
Vous pouvez ensuite y ajouter les fichiers spécifiques à votre environnement :
# Fichiers système
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
# Éditeurs / swaps
*.swp
Cela permet de garder le .gitignore du projet strictement dédié à WordPress, tout en évitant que les fichiers locaux à votre machine ne soient ajoutés par erreur.
🔐 4. Intégrer env-loader.php dans wp-config.php + sécurité .htaccess
Jusqu’ici, le workflow s’appuie sur une idée clé :
le dépôt Git contient tout le code, mais aucune donnée sensible.
Pour que cela fonctionne réellement, il faut :
- sortir les identifiants de base de données et autres secrets du
wp-config.php; - les placer dans un fichier
.envsitué en dehors du webroot ; - charger ce fichier via un petit bootstrap :
env-loader.php; - protéger ce bootstrap et les dossiers sensibles (
vendor/,composer.json, etc.) côté HTTP.
Cette section montre pas à pas comment mettre en place ce mécanisme.
4.1. Rappel : où sont placés .env et env-loader.php ?
L’arborescence cible est la suivante :
project-root/
│
├── .env ← configuration (local ou production), hors webroot, non versionné
│
└── webroot/ ← racine WordPress (dépôt Git)
├── wp-config.php
├── env-loader.php
├── vendor/ ← dépendances Composer (phpdotenv, etc.)
├── composer.json
├── wp-content/
│ ├── plugins/
│ ├── themes/
│ └── mu-plugins/
└── ...
.env contient les secrets (BDD, clés diverses…)
env-loader.phpse trouve dans le webroot, aux côtés dewp-config.phpvendor/se trouve également dans le webroot, mais est ignoré par Git et protégé côté HTTP
Le but est que wp-config.php ne contienne plus aucun secret, et puisse donc être versionné sans risque.
4.2. Structure de env-loader.php
env-loader.php joue trois rôles :
- Charger l’autoloader Composer (
vendor/autoload.php) - Charger le fichier
.envvia phpdotenv - Gérer les erreurs de manière propre (dev vs prod)
Voici une version type :
<?php
defined( 'ABSPATH' ) || exit;
/**
* Environment variables bootstrap using vlucas/phpdotenv.
*
* This block is intended to be placed at the very top of wp-config.php,
* before any WordPress constants are defined.
*
* It loads environment variables from a file located OUTSIDE the webroot.
* Example structure:
*
* project-root/
* .env <-- environment file
* webroot/
* wp-config.php
* vendor/
*/
/**
* Determines whether the current environment is considered a development environment.
*
* You can customize this logic according to your own setup (hostname, IP, env var, etc.).
*
* @since 1.0.0
*
* @return bool True if this is a development environment, false otherwise.
*/
function env_is_dev(): bool {
return ( ! empty( $_SERVER['LANDO'] ) || getenv( 'LANDO' ) );
}
/**
* Handles configuration errors in a clean, predictable manner.
*
* - Logs the detailed error message (server-side only).
* - Displays a verbose message in development.
* - Displays a neutral HTTP 500 error in production.
*
* @since 1.0.0
*
* @param string $public_message Message shown to end users (must be neutral).
* @param string $log_message Detailed message stored in server error logs.
*
* @return void
*/
function env_config_fail( string $public_message, string $log_message ): void {
$is_dev = env_is_dev();
// Log internal error message.
error_log( '[ENV ERROR] ' . $log_message ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
if ( $is_dev ) {
// Verbose output in development environments.
if ( ! headers_sent() ) {
header( 'Content-Type: text/html; charset=utf-8' );
}
echo '<h1>Environment configuration error</h1>';
echo '<p>' . esc_html( $log_message ) . '</p>';
exit;
}
// Neutral output in production.
if ( ! headers_sent() ) {
header( 'HTTP/1.1 500 Internal Server Error' );
header( 'Content-Type: text/plain; charset=utf-8' );
}
echo $public_message;
exit;
}
// The project root is assumed to be one level above the webroot.
$project_root = dirname( __DIR__ );
// Single source of truth: environment file name.
$env_file_name = '.env';
// Environment file located outside the webroot.
$env_file = $project_root . '/' . $env_file_name;
// Composer autoloader located inside the webroot's vendor directory.
$autoload = __DIR__ . '/vendor/autoload.php';
/**
* 1. Ensure Composer autoloader exists.
*/
if ( ! file_exists( $autoload ) ) {
env_config_fail(
'Internal error. Please try again later.',
'Composer autoloader not found: ' . $autoload
);
}
require_once $autoload;
/**
* 2. Ensure Dotenv is available.
*/
if ( ! class_exists( \Dotenv\Dotenv::class ) ) {
env_config_fail(
'Internal error. Please try again later.',
'Dotenv class "\\Dotenv\\Dotenv" is not available. Verify Composer dependencies.'
);
}
/**
* 3. Ensure the environment file exists.
*/
if ( ! file_exists( $env_file ) ) {
env_config_fail(
'Configuration error. Please contact the site administrator.',
'Environment file missing: ' . $env_file
);
}
/**
* 4. Load environment variables and validate required keys.
*/
try {
// Load the specifically named environment file (e.g. .env).
$dotenv = \Dotenv\Dotenv::createImmutable( $project_root, $env_file_name );
$dotenv->safeLoad();
// Define required environment variables.
$dotenv->required(
array(
'DB_NAME',
'DB_USER',
'DB_PASSWORD',
'DB_HOST',
)
)->notEmpty();
} catch ( \Throwable $e ) {
env_config_fail(
'Internal error. Please try again later.',
$e->getMessage()
);
}
/**
* Retrieves an environment variable with an optional default value.
*
* Example:
* define( 'DB_NAME', env( 'DB_NAME', 'wordpress' ) );
*
* @since 1.0.0
*
* @param string $key Environment variable name.
* @param mixed $default Default value if variable is not set.
*
* @return mixed The environment variable value or the default.
*/
if ( ! function_exists( 'env' ) ) {
function env( string $key, mixed $default = null ): mixed {
return isset( $_ENV[ $key ] ) ? $_ENV[ $key ] : $default;
}
}
/**
* Retrieves an environment variable as a boolean.
*
* Accepted truthy values (case-insensitive):
* "1", "true", "on", "yes"
*
* Accepted falsy values (case-insensitive):
* "0", "false", "off", "no", ""
*
* Any other non-null value will return the default.
*
* Example:
* define( 'WP_DEBUG', env_bool( 'WP_DEBUG', false ) );
*
* @since 1.0.0
*
* @param string $key Environment variable name.
* @param bool $default Default value if variable is not set or invalid.
*
* @return bool The boolean value of the environment variable or the default.
*/
if ( ! function_exists( 'env_bool' ) ) {
function env_bool( string $key, bool $default = false ): bool {
$value = env( $key, null );
if ( null === $value ) {
return $default;
}
if ( is_bool( $value ) ) {
return $value;
}
$value = strtolower( (string) $value );
$truthy = array( '1', 'true', 'on', 'yes' );
$falsy = array( '0', 'false', 'off', 'no', '' );
if ( in_array( $value, $truthy, true ) ) {
return true;
}
if ( in_array( $value, $falsy, true ) ) {
return false;
}
return $default;
}
}
À adapter uniquement si nécessaire (nom du fichier .env, logique de détection dev, etc.).
4.3. Intégration minimale dans wp-config.php
Une fois env-loader.php en place, l’intégration dans wp-config.php est volontairement minimale :
<?php
require_once __DIR__ . '/env-loader.php';
define( 'WP_ENVIRONMENT_TYPE', env( 'WP_ENVIRONMENT_TYPE', 'production' ) );
define( 'DB_NAME', env( 'DB_NAME', 'wordpress' ) );
define( 'DB_USER', env( 'DB_USER', 'wordpress' ) );
define( 'DB_PASSWORD', env( 'DB_PASSWORD', 'wordpress' ) );
define( 'DB_HOST', env( 'DB_HOST', 'localhost' ) );
Ici :
- les identifiants de base de données ne se trouvent plus dans le fichier ;
- ils sont lus depuis le
.envvia la fonctionenv(); wp-config.phppeut donc être versionné sereinement.
4.4. Protéger env-loader.php des accès directs
Même si env-loader.php ne contient pas de secrets, il est préférable qu’il ne soit jamais exécuté directement via une URL.
La protection de base est déjà en place avec :
defined( 'ABSPATH' ) || exit;
- si le fichier est appelé par WordPress (via
wp-config.php) →ABSPATHest défini → exécution normale ; - si quelqu’un appelle
/env-loader.phpdirectement →ABSPATHn’est pas défini →exitimmédiat.
En complément, il est possible d’ajouter une règle .htaccess au niveau du webroot :
<Files env-loader.php>
Require all denied
</Files>
Ce n’est pas obligatoire, mais cela ajoute une barrière HTTP supplémentaire.
4.5. Protéger vendor/ et les fichiers Composer
Le dossier vendor/ ne doit pas être accessible en HTTP :
il contient du code tiers, des métadonnées (installed.json), etc., qui n’ont aucune raison d’être exposés.
Il peut être également judicieux de protéger le dépôt Git local (.git/) ou tout autre fichier ou dossier caché (commençant par un .)
Dans le .htaccess à la racine du WordPress, on peut ajouter :
# Bloquer le vendor du webroot
<IfModule mod_rewrite.c>
RewriteEngine On
# Bloquer fichiers et dossiers cachés
RewriteRule (^|/)\..+ - [F]
# vendor/ à la racine du site (dépendances du projet)
RewriteRule ^vendor/ - [F,L]
# vendor/ dans les plugins
RewriteRule ^wp-content/plugins/[^/]+/vendor/ - [F,L]
# (optionnel) vendor/ dans les mu-plugins
RewriteRule ^wp-content/mu-plugins/[^/]+/vendor/ - [F,L]
# (optionnel) vendor/ dans les thèmes
RewriteRule ^wp-content/themes/[^/]+/vendor/ - [F,L]
</IfModule>
Et pour les fichiers composer.json / composer.lock (où qu’ils se trouvent) :
# Bloquer composer.json / composer.lock partout
<FilesMatch "^composer\.(json|lock)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
</FilesMatch>
Le code continue de fonctionner normalement côté PHP, mais plus aucun fichier sensible lié à Composer n’est exposé en HTTP.
4.6. Protéger les fichiers .env en cas d’erreur humaine
Dans le workflow présenté, le fichier .env est toujours au-dessus du webroot.
Il n’est donc pas accessible en HTTP, et n’a pas besoin de protection spécifique.
Cependant, pour se prémunir d’une erreur de copie manuelle (ex. : .env posé par mégarde dans le webroot), il est possible d’ajouter une règle défensive :
# Par sécurité, si un .env se retrouve dans le webroot
<Files ".env">
Require all denied
</Files>
<Files ".env.*">
Require all denied
</Files>
Cela ne change rien dans le cas normal (le fichier reste en dehors du webroot), mais évite une exposition accidentelle.
Pour information
Certains hébergeurs sécurisent déjà l’accès aux fichiers composer, .env, etc. mais on ne prend jamais trop de précaution en le faisant soit même.
4.7. Pour aller plus loin
Une fois env-loader.php en place, vous pouvez aller bien au-delà d’une simple gestion des accès à la base de données.
Les exemples suivants montrent différentes manières d’adapter WordPress selon l’environnement, afin que chacun puisse s’en inspirer et façonner une configuration parfaitement alignée avec ses propres besoins.
4.7.1. Constantes WordPress dépendantes de l’environnement
Certaines constantes doivent être différentes selon que l’on se trouve en local ou en production.
Grâce à WP_ENVIRONMENT_TYPE et env-loader.php, ces valeurs peuvent être externalisées dans le fichier .env, ce qui évite de modifier wp-config.php.
Les cas les plus courants concernent les réglages de débogage :
WP_DEBUGWP_DEBUG_LOGWP_DEBUG_DISPLAYSCRIPT_DEBUGWP_ENVIRONMENT_TYPE(standard WordPress : local, development, staging, production)
Avec les helpers env() et env_bool(), la déclaration dans wp-config.php reste simple et propre :
define( 'WP_DEBUG', env_bool( 'WP_DEBUG', false ) );
define( 'WP_DEBUG_LOG', env_bool( 'WP_DEBUG_LOG', false ) );
define( 'WP_DEBUG_DISPLAY', env_bool( 'WP_DEBUG_DISPLAY', false ) );
define( 'SCRIPT_DEBUG', env_bool( 'SCRIPT_DEBUG', false ) );
define( 'WP_ENVIRONMENT_TYPE', env( 'WP_ENVIRONMENT_TYPE', 'production' ) );
Les valeurs sont ensuite définies dans .env, ce qui permet d’adapter finement le comportement du site sans jamais modifier wp-config.php.
4.7.2. Sécuriser les valeurs sensibles et les clés d’authentification
Certaines constantes WordPress contiennent des informations sensibles ou essentielles à la sécurité.
Grâce à env-loader.php, elles peuvent être externalisées dans .env pour éviter qu’elles apparaissent en clair dans wp-config.php.
C’est notamment le cas :
- de COOKIEHASH, utilisé dans plusieurs mécanismes internes ;
- de WP_CACHE_KEY_SALT, qui doit être unique pour isoler votre environnement ;
- des clés et SALT WordPress (
AUTH_KEY,LOGGED_IN_SALT, etc.), si vous choisissez de les externaliser.
L’avantage :
✔ pas d’information sensible dans le fichier versionné
✔ possibilité d’utiliser des valeurs différentes entre local et production
✔ un wp-config.php propre et stable dans Git
Exemple d’intégration :
define( 'COOKIEHASH', md5( env( 'COOKIE_HASH' ) ) );
define( 'WP_CACHE_KEY_SALT', env( 'WP_CACHE_KEY_SALT' ) );
// Exemple si l’on souhaite externaliser les clés WordPress
define( 'AUTH_KEY', env( 'AUTH_KEY', '' ) );
define( 'SECURE_AUTH_KEY', env( 'SECURE_AUTH_KEY', '' ) );
define( 'LOGGED_IN_KEY', env( 'LOGGED_IN_KEY', '' ) );
define( 'NONCE_KEY', env( 'NONCE_KEY', '' ) );
define( 'AUTH_SALT', env( 'AUTH_SALT', '' ) );
define( 'SECURE_AUTH_SALT', env( 'SECURE_AUTH_SALT', '' ) );
define( 'LOGGED_IN_SALT', env( 'LOGGED_IN_SALT', '' ) );
define( 'NONCE_SALT', env( 'NONCE_SALT', '' ) );
Ainsi, les valeurs réellement sensibles se trouvent uniquement dans vos fichiers .env, hors webroot, et jamais dans le dépôt Git.
4.7.3. Interaction avec les plugins de sécurité
Certains plugins de sécurité — comme SecuPress — peuvent modifier automatiquement le fichier wp-config.php pour ajouter ou réécrire des constantes.
Dans un workflow Git où wp-config.php est versionné, cette approche pose deux problèmes :
- cela crée des différences non souhaitées entre local et production ;
- certaines constantes doivent être différentes selon l’environnement (URLs, debug…).
Avec l’usage de .env et env-loader.php, on adopte une méthode bien plus fiable :
wp-config.phpreste propre, stable et versionné ;- toutes les constantes sensibles ou dépendantes de l’environnement sont déportées dans
.env; - le plugin détecte les constantes déjà définies et n’écrase plus rien.
Ainsi, vous laissez d’abord le plugin générer ses constantes, puis vous externalisez celles qui doivent varier selon l’environnement.
Exemple 1 — Les constantes de debug générées par SecuPress
SecuPress peut injecter ceci dans wp-config.php :
# BEGIN SecuPress debugging
define( 'WP_DEBUG', false );
# END SecuPress
# BEGIN SecuPress Correct Constants Values
define( 'WP_DEBUG_DISPLAY', false ); // Added by SecuPress.
# END SecuPress
Avec le workflow .env, vous remplacez simplement par :
# BEGIN SecuPress debugging
define( 'WP_DEBUG', env_bool( 'WP_DEBUG' ) );
# END SecuPress
# BEGIN SecuPress Correct Constants Values
define( 'WP_DEBUG_DISPLAY', env_bool( 'WP_DEBUG_DISPLAY' ) ); // Added by SecuPress.
# END SecuPress
Dans .env local:
WP_DEBUG=true
WP_DEBUG_DISPLAY=false
Dans .env production :
WP_DEBUG=false
WP_DEBUG_DISPLAY=false
Le plugin ne réécrit plus rien et la configuration reste propre.
Attention
Les constantes WP_DEBUG et WP_DEBUG_DISPLAY vues également en §4.7.1 susceptible d’être ajouté manuellement ne doivent pas faire doublon avec celles ajoutés par SecuPress.
SecuPress ne les ajoutera que si elles ne sont pas présentes. Sinon il les modifie.
Exemple 2 — WP_SITEURL et WP_HOME
SecuPress peut également injecter :
# BEGIN SecuPress locations
define( 'RELOCATE', false );
define( 'WP_HOME', 'https://monsite.com' );
define( 'WP_SITEURL', 'https://monsite.com' );
# END SecuPress
Or ces constantes doivent être radicalement différentes entre local et production.
Grâce à .env :
# BEGIN SecuPress locations
define( 'RELOCATE', false );
define( 'WP_SITEURL', env( 'WP_SITEURL' ) );
define( 'WP_HOME', env( 'WP_HOME' ) );
# END SecuPress
Dans .env local:
WP_HOME="https://monsite.lndo.site"
WP_SITEURL="https://monsite.lndo.site"
Dans .env production :
WP_HOME="https://monsite.fr"
WP_SITEURL="https://monsite.fr"
Résultat :
- SecuPress fonctionne parfaitement,
- aucune modification intempestive du fichier versionné,
- les environnements local/prod sont parfaitement isolés,
- aucun risque de casser le site en définissant une mauvaise URL.
4.7.4. Configurations serveur : Redis
La configuration de Redis peut elle aussi être entièrement externalisée dans .env.
Exemples de variables :
WP_REDIS_SCHEME=tcp
WP_REDIS_HOST=redis
WP_REDIS_PORT=6379
WP_REDIS_DATABASE=1
WP_REDIS_TIMEOUT=1
WP_REDIS_READ_TIMEOUT=1
WP_REDIS_PATH=
WP_REDIS_PASSWORD=
Et dans wp-config.php :
define( 'WP_REDIS_SCHEME', env( 'WP_REDIS_SCHEME', 'tcp' ) );
define( 'WP_REDIS_HOST', env( 'WP_REDIS_HOST', '127.0.0.1' ) );
define( 'WP_REDIS_PORT', (int) env( 'WP_REDIS_PORT', 6379 ) );
define( 'WP_REDIS_DATABASE', (int) env( 'WP_REDIS_DATABASE', '1' ) );
define( 'WP_REDIS_TIMEOUT', (int) env( 'WP_REDIS_TIMEOUT', '1' ) );
define( 'WP_REDIS_READ_TIMEOUT', (int) env( 'WP_REDIS_READ_TIMEOUT', '1' ) );
define( 'WP_REDIS_PATH', env( 'WP_REDIS_PATH', null ) );
define( 'WP_REDIS_PASSWORD', env( 'WP_REDIS_PASSWORD', null ) );
Ainsi :
- la production peut utiliser un socket Unix, un mot de passe Redis, ou une configuration optimisée ;
- le local utilise simplement les valeurs fournies par Lando ;
- le fichier wp-config.php reste identique, propre, et entièrement versionné ;
- aucune différence de logique n’existe entre local et production : seules les valeurs changent via
.env.
4.7.5. Exemples complets de .env local et .env production
Exemple .env local (Lando / développement)
DB_NAME=wordpress
DB_USER=wordpress
DB_PASSWORD=wordpress
DB_HOST=database
WP_SITEURL=https://monsite.lndo.site
WP_HOME=https://monsite.lndo.site
COOKIE_HASH=moncookieuniquedev
WP_ENVIRONMENT_TYPE=development
WP_DEBUG=true
WP_DEBUG_LOG=true
WP_DEBUG_DISPLAY=false
WP_REDIS_SCHEME=tcp
WP_REDIS_HOST=redis
WP_REDIS_PORT=6379
WP_REDIS_DATABASE=1
WP_REDIS_TIMEOUT=1
WP_REDIS_READ_TIMEOUT=1
WP_REDIS_PATH=
WP_REDIS_PASSWORD=
Exemple .env production
DB_NAME=prod_xxx
DB_USER=prod_xxx
DB_PASSWORD=********
DB_HOST=localhost
WP_SITEURL=https://monsite.com
WP_HOME=https://monsite.com
COOKIE_HASH=moncookieuniqueprod
WP_ENVIRONMENT_TYPE=production
WP_DEBUG=false
WP_DEBUG_LOG=false
WP_DEBUG_DISPLAY=false
WP_REDIS_SCHEME=unix
WP_REDIS_HOST=127.0.0.1
WP_REDIS_PORT=0
WP_REDIS_DATABASE=1
WP_REDIS_TIMEOUT=1
WP_REDIS_READ_TIMEOUT=1
WP_REDIS_PATH=/home/USER/redis/redis.sock
WP_REDIS_PASSWORD=********
En résumé
Pour que la configuration basée sur .env soit correctement intégrée au workflow Git :
env-loader.phpcharge les variables d’environnement depuis un fichier.envsitué hors webroot ;wp-config.phpne contient plus de secrets et peut être versionné sereinement ;env-loader.phpest protégé à la fois pardefined( 'ABSPATH' ) || exit;et, si souhaité, par une règle.htaccess;- le dossier
vendor/et les fichierscomposer.*sont inaccessibles en HTTP, tout en restant utilisables par PHP ; - une règle défensive peut bloquer tout fichier
.envqui se retrouverait par erreur dans le webroot.
🚀 5. Workflow complet : développement local → Git → production
Le cœur de ce guide repose sur un workflow clair, reproductible et sans surprise entre votre environnement local (Lando) et votre hébergement (o2switch, OVH, Infomaniak, IONOS…).
Cette section décrit le cycle complet, depuis la création du dépôt jusqu’au déploiement propre en production.
5.1. Initialiser le dépôt Git local et le dépôt central
On suppose à ce stade que :
- votre stack locale (Lando, Docker, autre) est opérationnelle,
- WordPress fonctionne déjà en local dans le dossier
webroot/(installation neuve ou site existant migré).
Pour information
Que ce soit un nouveau projet WordPress ou un site récupéré par FTP ou sauvegarde, la logique d’initialisation Git reste la même.
1️⃣ Créer le dépôt distant (GitHub, GitLab, Forge, etc.)
Sur votre forge Git préférée (GitHub, GitLab, Bitbucket, dépôt privé…), créez un dépôt vide :
- sans README automatique,
- sans
.gitignoregénéré par l’interface, - sans modèle WordPress pré-rempli.
L’objectif : que ce soit votre projet qui fasse foi, pas un squelette imposé.
2️⃣ Initialiser le dépôt Git dans le webroot local
Dans votre environnement local, placez-vous dans le dossier webroot/ de votre projet (là où se trouve wp-config.php) :
cd /chemin/vers/project-root/webroot
git init
Ajoutez ensuite votre .gitignore (défini dans la section précédente) si ce n’est pas déjà fait, ainsi que les fichiers de configuration propres au projet.
3️⃣ Faire le premier commit
On ajoute tout ce qui doit être versionné (core WordPress, wp-content, configuration, etc.) :
git add .
git commit -m "Initial commit: base WordPress + configuration projet"
À ce stade :
- votre dépôt local contient la version de référence du site,
- les fichiers ignorés (
wp-content/uploads, backups SQL, cache, etc.) ne sont pas intégrés.
4️⃣ Lier le dépôt local au dépôt distant
Ajoutez le dépôt distant comme remote :
git remote add origin git@github.com:mon-user/mon-projet.git
# ou avec une URL HTTPS si vous préférez
Vous pouvez vérifier :
git remote -v
5️⃣ Pousser la branche principale
git branch -M main
git push -u origin main
Votre projet WordPress est maintenant :
- versionné proprement,
- centralisé dans un dépôt Git distant,
- prêt à être synchronisé avec votre hébergement (section suivante).
Pour un site existant récupéré par FTP ou via une sauvegarde :
- placez tous les fichiers dans
webroot/, - ajustez
wp-config.phppour utiliser.env+env-loader.php, - puis appliquez exactement les mêmes étapes d’initialisation Git que ci-dessus.
5.2. Développer localement : thèmes, plugins, configuration
Une fois votre environnement local opérationnel et le dépôt Git initialisé, vous pouvez commencer à travailler sereinement sur votre site WordPress.
En local, vous allez pouvoir :
- ajouter ou modifier du code dans votre thème enfant ;
- développer ou maintenir des plugins personnalisés ;
- gérer vos mu-plugins ;
- tester des optimisations ou des modifications de configuration ;
- mettre à jour le cœur WordPress ;
- mettre à jour votre thème parent ;
- mettre à jour les extensions ;
- mettre à jour les traductions ;
- tester des évolutions majeures sans impact sur la production.
Ce travail se fait sans risque, puisque rien n’est déployé tant que vous ne faites pas de git push.
1️⃣ Organisation recommandée pour le développement
- Travaillez dans un thème enfant lorsque vous ajustez un thème tiers.
- Placez votre code maison dans :
wp-content/mu-plugins/pour les fonctionnalités critiques,wp-content/plugins/si vous préférez des modules indépendants,wp-content/themes/votre-theme-enfant/pour la partie visuelle.
- Testez régulièrement :
- les pages clés,
- les formulaires,
- les performances,
- le cache et cache objet (Redis).
2️⃣ Composer et dépendances PHP
Si votre projet utilise phpdotenv — ce qui devrait être le cas si vous avez suivi les § 4.1 à 4.6 — ou d’autres dépendances PHP :
- Installez-les avec :
lando composer install
- Ne versionnez pas le dossier
vendor/local : il sera régénéré sur la production.
3️⃣ WP-CLI comme outil de développement
WP-CLI facilite de nombreuses tâches :
lando wp plugin update --all
lando wp theme update --all
lando wp core update
lando wp core update-db
Idéal pour appliquer rapidement les mises à jour locales avant de les valider dans Git.
4️⃣ L’importance des tests avant commit
À chaque modification significative :
- rechargez le site,
- videz le cache et le cache objet si nécessaire
lando wp cache flush
- vérifiez les erreurs éventuelles en consultant
wp-content/debug.logsi vous avez activéWP_DEBUG_LOGpar exemple.
5.3. Déployer en production via Git
Que votre site soit neuf ou déjà en place, le déploiement suit toujours le même principe :
👉 le code vient du dépôt Git — jamais l’inverse.
👉 la production doit refléter exactement ce qui a été validé en local.
Très important
Avant toute opération, assurez-vous que :
- le fichier .env de production (hors webroot) est bien présent,
- il contient la configuration correcte de la production,
- vous en avez une copie locale au cas où.
Le déploiement écrasera toujours les fichiers du site. - le fichier
wp-config.phpsera écrasé par la référence dans le dépôt Git
Selon votre situation, deux scénarios possibles :
🟦 Cas 1 — Nouveau site
Votre projet n’existe pas encore sur le serveur.
Vous allez simplement cloner votre dépôt Git vide puis déployer votre premier commit.
1. Se connecter à l’hébergement en ssh
ssh user@votre-serveur
2. Se placer dans le répertoire webroot
(ex : public_html ou un sous-dossier dédié, abitrairement appelé webroot ici pour coller à l’environnement local)
cd webroot
3. Cloner votre dépôt Git
git clone https://github.com/mon-user/mon-projet.git .
4. Installer les dépendances PHP
composer install --no-dev --optimize-autoloader
5. Importer la base de données sauvegarde de votre base de données locale
En supposant que vous avez au préalable :
- fait un export avant en local avec
lando wp db export local.sql - transférer ce fichier en FTP sur votre hébergement
- créer la base de données sur votre hébergement
wp db import local.sql
6. Search-replace des URLs dans la base de données
wp search-replace "https://monsite.lndo.site" "https://monsite.com" --all-tables
7. Vider la cache
wp cache flush
8. Tester votre site
Votre site devrait être opérationnel : la production est parfaitement alignée avec le dépôt Git et votre site en local.
🟧 Cas 2 — Site existant que l’on met sous Git
C’est le cas le plus fréquent :
vous avez un site WordPress déjà installé et fonctionnel sur votre hébergement, mais vous voulez désormais qu’il soit maintenu via Git.
L’objectif est simple :
➡️ remplacer totalement les fichiers du serveur par ceux du dépôt Git
➡️ sans manipulations complexes, sans conflits
Le moyen le plus sûr et le plus propre :
1. Se connecter à l’hébergement
ssh user@votre-serveur
2. Se placer dans le répertoire webroot
(ex : public_html ou un sous-dossier dédié, abitrairement appelé webroot ici pour coller à l’environnement local)
cd webroot
3. Initialiser Git s’il ne l’est pas déjà
git init
git remote add origin https://github.com/mon-user/mon-projet.git
git fetch origin
4. Écraser entièrement les fichiers existants par la version Git
👉 C’est volontaire.
👉 On part sur une base propre et maîtrisée.
git reset --hard origin/main
Tous les fichiers modifiés, ajoutés ou supprimés sur la prod seront écrasés par la version validée en local.
C’est ce que l’on veut dans un workflow Git propre.
5. Installer les dépendances PHP
composer install --no-dev --optimize-autoloader
6. Mettre à jour la base de données WordPress (si nécessaire)
Lorsqu’une version locale du core a modifié le schéma SQL :
wp core update-db
(WP-CLI ne fait pas de mise à jour de fichiers : il applique seulement les migrations SQL nécessaires.)
7. Vider le cache
wp cache flush
8. Tester votre site
Votre site devrait être opérationnel et fonctionner comme celui qui existait avant : la production est parfaitement alignée avec le dépôt Git et votre site en local.
Pour information
Pas de de transfert et d’import de la base de données dans ce cas, c’est la base de données de production qui fait foi et est déjà présente puisque le site existait déjà.
C’est votre base de données locale qui devrait être en phase avec celle de production.
🟩 Déploiements suivants (cycle normal)
Une fois l’un de ces deux scénarios effectué, tous les prochains déploiements se résument à :
ssh user@serveur
cd webroot
git pull
wp core update-db
wp cache flush
Votre production reste toujours synchronisée avec ce que vous avez validé en local.
En résumé
- Production alignée exactement sur Git
- Aucun transfert FTP hormis dans le cas d’une nouvelle installation pour transférer la base de données locale
- Aucun conflit
- Un déploiement propre, reproductible, maîtrisé.
5.4. Bonus — Automatiser le git pull avec GitHub Actions
Une fois le dépôt en production en place, la mise à jour du site se résume à une commande côté serveur : git pull.
J’ai donc poussé l’idée jusqu’au bout en automatisant cette commande via GitHub Actions avec un runner self-hosted (installé sur mon PC et lancé comme service au démarrage).
À chaque push sur main, le workflow se connecte en SSH à mon hébergement, vérifie que le dépôt est “clean”, puis exécute le git pull.
En cas de dépôt non clean (situation exceptionnelle), le déploiement s’arrête et affiche les fichiers concernés dans les logs GitHub Actions.
name: Deploy website-site to hosting
on:
push:
branches: [ main ]
workflow_dispatch: {}
concurrency:
group: deploy-website-site-production
cancel-in-progress: false
jobs:
deploy:
runs-on: self-hosted
steps:
- name: SSH deploy
run: |
ssh user@server <<'SSH'
set -e
cd webroot
[ -z "$(git status --porcelain)" ] || { git status --porcelain; exit 1; }
git pull
SSH
Pour information
Le runner est « self-hosted » pour garantir facilement l’accès SSH à partir de votre ordinateur; en effet, les accès SSH sont souvent verrouillés chez les hébergeurs à une IP précise pour de simple mesure de sécurité.
Le runner « self-hosted » est attaché à un dépôt GitHub (un runner par dépôt dans mon cas).
🔄 6. Synchroniser la base et les médias entre local et production
Même avec un workflow Git propre, deux éléments essentiels ne sont jamais versionnés :
- la base de données (contenu, options, URLs, widgets, pages…)
- les médias (
wp-content/uploads/)
Pour garder votre environnement local cohérent avec la production, il faut donc synchroniser régulièrement ces deux éléments — surtout lors de travaux significatifs ou avant un déploiement important.
Cette section présente la méthode la plus simple, robuste et rapide pour synchroniser dans les deux sens (local ↔ production) en utilisant les outils déjà disponibles : WP-CLI, SSH, et rsync.
6.1. Récupérer la base de données de la production vers le local
C’est l’opération la plus courante : vous souhaitez travailler localement sur la vraie base du site.
1️⃣ Exporter la base depuis la production
Sur l’hébergement (SSH) :
wp db export ~/prod.sql
2️⃣ Télécharger le dump vers votre machine
Depuis votre ordinateur :
rsync -avz -e ssh user@serveur:~/prod.sql .
3️⃣ Importer dans votre environnement local
Dans votre projet Lando :
lando wp db import prod.sql
4️⃣ Corriger les URLs (production → local)
Très important : production et local n’ont pas les mêmes URLs.
lando wp search-replace 'https://monsite.com' 'https://monsite.lndo.site' --all-tables
Important
WP-CLI corrige automatiquement les données sérialisées : c’est pour cela qu’il ne faut jamais faire ce remplacement “à la main”.
Votre base locale correspond désormais exactement à la production.
6.2. Envoyer la base locale vers la production (cas exceptionnel)
À utiliser uniquement lorsque :
- vous partez d’un projet « from scratch »,
- vous réinitialisez une production dégradée,
- vous migrez un site existant vers un nouveau serveur.
1️⃣ Exporter en local
lando wp db export ../local.sql
2️⃣ Upload du fichier SQL vers la production
rsync -avz -e ssh ../local.sql user@serveur:~/
3️⃣ Import sur le serveur
wp db import local.sql
4️⃣ Corriger les URLs (local → production)
Très important : local et production n’ont pas les mêmes URLs.
wp search-replace 'https://monsite.lndo.site' 'https://monsite.com' --all-tables
Votre production correspond maintenant à votre local.
6.3. Synchroniser les médias entre local et production via rsync
Les médias ne doivent jamais être dans Git, mais doivent être identiques entre local et production pour travailler correctement.
La solution la plus simple est rsync.
6.3.1. Récupérer les uploads de la production vers le local
Depuis votre machine :
rsync -avz -e ssh user@serveur:~/webroot/wp-content/uploads/ webroot/wp-content/uploads/
Options utiles :
-a: archive (préserve dates, permissions…)-v: verbose-z: compression lors du transfert
Seuls les nouveaux fichiers ou ceux modifiés seront copiés → très rapide.
6.3.2. Envoyer les uploads du local vers la production
Rare, mais utile lors d’un départ “from scratch” :
rsync -avz -e ssh /webroot/wp-content/uploads/ user@serveur:~/webroot/wp-content/uploads/
En résumé
Pour garder vos environnements synchronisés :
- la base se synchronise via WP-CLI :
wp db export,wp db import,wp search-replace - les médias se synchronisent via rsync :
rsync -avz - production → local est le cas le plus courant
- local → production est réservé aux migrations / réinitialisations
Cette approche complète parfaitement le workflow Git :
le code versionné + une base synchronisée + les médias alignés = un environnement local 100% fidèle à la production.
🏁 7. Conclusion — WordPress + Git : un workflow moderne, fiable et reproductible
Adopter un workflow Git pour maintenir un site WordPress — même sur un simple hébergement mutualisé — change profondément la manière de travailler.
On ne “bricole” plus directement sur la production.
On ne dépend plus entièrement des sauvegardes automatisées.
On ne croise plus les doigts pendant les mises à jour.
À la place :
- chaque modification est tracée, versionnée, contrôlée ;
- le développement local devient la norme, pas l’exception ;
- le déploiement est propre, reproductible et sans surprise ;
- la configuration est centralisée, claire, structurée ;
- la production est sécurisée, car aucun fichier sensible ne s’y trouve.
Grâce à la combinaison :
- Git (versionnage du code),
- une stack locale comme Lando (environnement identique à la prod),
- Composer + phpdotenv (gestion propre des dépendances et de la configuration),
- env-loader.php (pont fiable entre .env et WordPress),
- SSH + WP-CLI (outils d’administration avancée),
- un .gitignore propre (dépôt léger et pertinent),
…vous obtenez un workflow professionnel, proche de ce qui se fait dans les environnements DevOps modernes — mais parfaitement compatible avec une production mutualisée.
Résultats obtenus
Avec ce workflow, vous bénéficiez de :
🔹 Sécurité
- aucune donnée sensible dans Git ;
.enven dehors du webroot ;- wp-config.php propre et versionné ;
- protection des fichiers Composer / vendor / .env via .htaccess.
🔹 Sérénité lors des mises à jour
- test local avant la production ;
- plus aucune modification sauvage en prod ;
- capacité de revenir en arrière en un instant.
🔹 Stabilité long terme
- des environnements dev/prod cohérents ;
- un code maîtrisé dans le temps ;
- un fonctionnement documenté et reproductible.
🔹 Évolutivité
- facile d’ajouter staging, CI/CD, tests automatiques, etc.
- simple d’intégrer d’autres développeurs ou contributeurs.
🚀 Enfin, un WordPress qui se maintient proprement
Avec ce workflow :
- le local est la source de vérité ;
- la production reflète toujours le dépôt Git ;
- les environnements sont isolés mais cohérents ;
- la configuration dépendante de l’environnement est proprement externalisée ;
- le déploiement devient un geste simple et maîtrisé.
Ce n’est plus “du WordPress à l’ancienne” :
c’est un vrai projet de développement, robuste, sécurisé et professionnel.
❓ FAQ — Git et WordPress
Oui. Vous pouvez tout à fait ajouter Git sur un site WordPress déjà en production.
La bonne approche consiste à faire une sauvegarde complète (fichiers et base), à créer un dépôt Git à partir du code actuel (thèmes, plugins, mu-plugins, fichiers de configuration), puis à pousser ce dépôt vers un dépôt distant (GitHub, GitLab, etc.). Ensuite, vous faites évoluer le site via Git plutôt qu’en modifiant directement la production, ce qui vous donne un historique propre et la possibilité de revenir en arrière.
Oui, mais il faut encadrer leur usage pour garder un historique propre.
En pratique, vous pouvez laisser les mises à jour automatiques en production (utile pour les correctifs de sécurité), puis reproduire ces mises à jour en local, tester, corriger les éventuels problèmes, commiter et redéployer le code en écrasant la production via Git.
L’élément crucial est de sauvegarder régulièrement la base de données (avant/après les mises à jour) afin de pouvoir revenir en arrière à la fois sur le code et sur la structure de la base si besoin.
Non, la base de données ne doit pas être versionnée telle quelle dans Git. Elle change très souvent, ce qui produirait des conflits permanents et un dépôt énorme.
La bonne pratique est de la sauvegarder via des exports SQL ou des outils comme WP-CLI, puis d’automatiser autant que possible les opérations d’import/export entre local et production.
Pas complètement. Git est idéal pour versionner le code (thèmes, plugins, mu-plugins, scripts de configuration), mais il ne gère ni la base de données ni les fichiers téléversés.
Pour remplacer un plugin de migration, vous devrez combiner Git avec des exports/imports de base (WP-CLI,mysqldump, etc.) et un outil de synchronisation de fichiers (rsync, SSH/SFTP ou un script dédié).
📚 Références
Voici les ressources officielles liées aux outils, concepts et bonnes pratiques utilisés dans cet article. Elles permettent d’aller plus loin, de vérifier les points techniques, ou d’explorer les alternatives.
