Déployer WordPress sur un VPS, c’est souvent le début d’une longue liste de galères : configuration du serveur, gestion des mises à jour, et le fameux moment de stress quand on déploie une mise à jour et que le site tombe. Kamal 2 change la donne en combinant Docker et un proxy intelligent pour obtenir des déploiements sans interruption, le tout piloté par un simple fichier de configuration. Dans cet article, on va voir ensemble comment mettre en place toute la chaîne, du VPS jusqu’au pipeline CI/CD avec GitHub Actions.
Pourquoi déployer WordPress avec Kamal 2 sur un VPS en 2026 ?
On va être honnêtes : en 2026, continuer à déployer WordPress sur un hébergement mutualisé, c’est un peu comme conduire une voiture des années 90 sur l’autoroute. Ça avance, mais on est loin d’être aux commandes.
Les limites des hébergements mutualisés classiques
Si vous avez déjà géré un site WordPress un peu sérieux sur un hébergement partagé, vous connaissez la chanson. Les performances sont imprévisibles — un voisin qui consomme trop de ressources et votre site ralentit sans prévenir. Pas moyen de choisir votre version de PHP précisément, encore moins d’installer des extensions système spécifiques. Et côté déploiement, on parle souvent encore de FTP ou au mieux d’un panel cPanel peu flexible.
Le vrai problème, c’est l’absence de contrôle. Pas d’isolation réelle entre les environnements, pas de reproductibilité, et des mises à jour qui ressemblent parfois à un jeu de hasard. Pour un projet professionnel, c’est difficile à justifier.
Kamal 2 : c’est quoi exactement ?
Kamal 2 est un outil de déploiement open source développé par Basecamp (les créateurs de Ruby on Rails et Hey). C’est le successeur de MRSK, et il repose entièrement sur Docker pour packager et déployer vos applications sur n’importe quel VPS.
L’idée centrale est simple : vous décrivez votre infrastructure dans un fichier deploy.yml, et Kamal se charge du reste — connexion SSH au serveur, pull de l’image Docker, rolling update sans interruption de service. Et contrairement à ce qu’on pourrait croire, Kamal 2 n’est pas réservé aux applications Rails. Il fonctionne avec n’importe quelle stack Dockerisée. WordPress inclus, évidemment.
Docker + Kamal : le duo gagnant pour WordPress
Docker apporte ce qui manque cruellement aux hébergements mutualisés : l’isolation, la reproductibilité et la portabilité. Votre environnement WordPress tourne dans un conteneur identique en local, en staging et en production. Fini le classique « ça marchait sur ma machine ».
Et Kamal 2 vient compléter Docker avec ce dont on a besoin en production :
- Zéro downtime grâce au rolling update : Kamal lance le nouveau conteneur avant de couper l’ancien
- Configuration déclarative dans un seul fichier
deploy.yml, clair et versionnable dans Git - Gestion des secrets intégrée, pour ne jamais commiter vos credentials en clair
- Accessory containers : MySQL, Redis, Traefik… tout peut être orchestré depuis Kamal
Bon, je ne vais pas vous mentir : il y a une courbe d’apprentissage. Docker et la configuration réseau demandent un peu de temps. Mais une fois la mécanique en place, les déploiements deviennent vraiment fluides et reproductibles. C’est un investissement qui vaut le coup.
Préparer l’environnement : VPS, Docker et image WordPress
On entre dans le vif du sujet. Cette section est la plus dense du tutoriel, donc prenez le temps de bien suivre chaque étape — les erreurs de configuration ici se paient cash plus tard.
Choisir et configurer son VPS (Ubuntu 22.04 / 24.04)
Pour faire tourner WordPress dans Docker avec Kamal 2, un petit VPS entrée de gamme peut suffire pour commencer, mais on recommande au minimum 2 vCPU et 2 Go de RAM. Les offres de chez Hetzner, Infomaniak ou OVH font très bien l’affaire — comptez entre 5 et 15 €/mois pour ce type de config.
Une fois votre VPS commandé sous Ubuntu 22.04 ou 24.04, voici les premières étapes incontournables :
- Créer un utilisateur dédié (pas root !) avec droits sudo :
adduser deploy
usermod -aG sudo deploy - Ajouter votre clé SSH publique dans
~/.ssh/authorized_keyspour cet utilisateur. - Installer Docker — via le script officiel ou le paquet
docker.io:curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker deploy
Et côté local ? Kamal 2 s’installe via Ruby (gem install kamal), donc vous avez besoin de Ruby sur votre machine de déploiement. Si vous utilisez Bundler, ajoutez simplement gem "kamal" à votre Gemfile. Pas de Ruby en local ? Ça se règle rapidement avec rbenv ou asdf.
Créer une image Docker WordPress production-ready
C’est là que beaucoup de gens font l’erreur de prendre l’image Docker WordPress « telle quelle » et de tout monter en volume. Mauvaise idée pour la reproductibilité. L’objectif : embarquer vos plugins et thèmes directement dans l’image, et ne laisser en volume que ce qui doit l’être (les uploads, les données).
Voici un exemple de Dockerfile minimaliste mais solide, basé sur wordpress:php8.3-apache :
FROM wordpress:php8.3-apache
# Copie des thèmes et plugins dans l'image
COPY ./wp-content/themes /var/www/html/wp-content/themes
COPY ./wp-content/plugins /var/www/html/wp-content/plugins
# Permissions correctes
RUN chown -R www-data:www-data /var/www/html/wp-content
# Variables d'environnement (surchargées au runtime via Kamal)
ENV WORDPRESS_DB_HOST=db \
WORDPRESS_DB_NAME=wordpress \
WORDPRESS_DB_USER=wp_user \
WORDPRESS_DB_PASSWORD=changeme
Les variables d’environnement définies ici sont des valeurs par défaut — elles seront surchargées au moment du déploiement via les secrets Kamal (on y revient juste après). Point critique : wp-content/uploads ne doit pas être copié dans l’image. Ce dossier doit être monté en volume Docker pour que vos médias survivent aux déploiements.
Vous pouvez aussi opter pour une stack php8.3-fpm + nginx si vous recherchez de meilleures performances sous charge, mais la variante Apache est largement suffisante pour la plupart des projets.
Configurer le fichier deploy.yml de Kamal 2
C’est le cœur de Kamal : le fichier deploy.yml, à placer à la racine de votre projet. Voici un exemple commenté, adapté à un déploiement WordPress typique :
# Nom du service (utilisé pour nommer les containers)
service: monsite-wordpress
# Image Docker à construire et pousser vers votre registry
image: votre-registry/monsite-wordpress
# Serveur(s) cible(s)
servers:
web:
- 1.2.3.4 # IP de votre VPS
# Kamal Proxy gère le zero downtime et le HTTPS automatiquement
proxy:
ssl: true
host: monsite.fr
# Variables d'environnement injectées au runtime
env:
secret:
- WORDPRESS_DB_PASSWORD
- WORDPRESS_AUTH_KEY
- WORDPRESS_SECURE_AUTH_KEY
clear:
WORDPRESS_DB_HOST: "127.0.0.1:3306"
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wp_user
# Volumes persistants
volumes:
- "/data/wp-uploads:/var/www/html/wp-content/uploads"
# Accessories : services annexes gérés par Kamal (MySQL, Redis...)
accessories:
db:
image: mysql:8.0
host: 1.2.3.4
env:
secret:
- MYSQL_ROOT_PASSWORD
clear:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp_user
volumes:
- "/data/mysql:/var/lib/mysql"
Les secrets (mots de passe, clés d’auth WordPress…) sont stockés dans .kamal/secrets — un fichier qui ne doit jamais être commité dans Git. Kamal les injecte automatiquement au moment du déploiement. Propre et sécurisé.
Pour initialiser tout l’environnement la première fois, une seule commande :
kamal setup
Elle va se connecter à votre VPS, installer Docker si ce n’est pas fait, lancer les accessories, construire et pousser l’image, puis démarrer le container applicatif derrière Kamal Proxy. Impressionnant pour une seule commande, non ?
Gérer la base de données MySQL et les volumes persistants
Deux sujets à ne surtout pas bâcler : la persistance des données et les backups.
Avec Kamal 2, MySQL tourne en tant qu’accessory sur le même VPS (comme dans l’exemple ci-dessus). C’est pratique pour commencer. Si votre site grossit, vous pourrez pointer vers une base externe (PlanetScale, RDS, etc.) en changeant simplement WORDPRESS_DB_HOST — sans toucher au reste de la configuration.
Les volumes Docker, c’est non négociable. Deux montages essentiels à prévoir :
/data/mysql→/var/lib/mysql: pour les données MySQL/data/wp-uploads→/var/www/html/wp-content/uploads: pour les médias WordPress
Sans ça, chaque redéploiement efface tout. Vécu, et c’est douloureux.
Pour les backups, voici une stratégie simple à mettre en place rapidement :
# Dump MySQL quotidien via cron
0 3 * * * docker exec kamal-monsite-wordpress-db mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" wordpress > /data/backups/wp_$(date +\%F).sql
Vous pouvez ensuite coupler ça à rclone pour envoyer automatiquement vos dumps vers un stockage S3 ou Backblaze B2. Ce n’est pas la partie la plus sexy du déploiement, mais c’est celle que vous regretterez d’avoir ignorée le jour où quelque chose déraille.
Intégrer la CI/CD avec GitHub Actions pour un déploiement automatique
On a un VPS configuré, une image Docker qui tourne, et Kamal 2 qui gère le déploiement. C’est déjà bien ! Mais honnêtement, lancer kamal deploy à la main depuis son poste, c’est pas vraiment ce qu’on appelle un pipeline CI/CD moderne. Automatisons tout ça avec GitHub Actions : un git push sur main, et le déploiement se lance tout seul, sans intervention humaine.
Créer le workflow GitHub Actions
Créez le fichier .github/workflows/deploy.yml à la racine de votre repo. Voici un exemple complet, commenté pour que ce soit clair :
name: Deploy WordPress to VPS
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# 1. Récupération du code source
- name: Checkout repository
uses: actions/checkout@v4
# 2. Setup Ruby (Kamal est une gem Ruby)
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
# 3. Installation de Kamal
- name: Install Kamal
run: gem install kamal
# 4. Configuration de la clé SSH pour accéder au VPS
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.VPS_IP }} >> ~/.ssh/known_hosts
# 5. Login sur le registry Docker (ici GitHub Container Registry)
- name: Login to GitHub Container Registry
run: echo "${{ secrets.KAMAL_REGISTRY_PASSWORD }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
# 6. Déploiement via Kamal
- name: Deploy with Kamal
env:
KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: kamal deploy
Ce qui se passe concrètement : GitHub Actions tourne sur un runner Ubuntu, installe Kamal, établit une connexion SSH vers votre VPS grâce à la clé privée stockée dans les secrets, puis exécute kamal deploy. Kamal va builder l’image, la pousser sur le registry, et orchestrer le déploiement zéro downtime sur le VPS. Tout ça en quelques minutes, sans que vous ayez à toucher quoi que ce soit.
Sécuriser les secrets et automatiser le build Docker
C’est la partie qu’on a tendance à bâcler — et c’est souvent là que les problèmes arrivent. Prenez le temps de bien configurer vos secrets GitHub (dans Settings > Secrets and variables > Actions) :
SSH_PRIVATE_KEY: la clé privée SSH correspondant à la clé publique ajoutée sur le VPS (pour l’utilisateurdeployouroot)KAMAL_REGISTRY_PASSWORD: le token d’accès à votre registry Docker (GitHub Container Registry ou Docker Hub)VPS_IP: l’adresse IP de votre VPS (techniquement pas un secret, mais c’est plus propre ainsi)DB_PASSWORD: le mot de passe MySQL, évidemment jamais commité dans le repo
Côté Kamal 2, les secrets sont gérés via le fichier .kamal/secrets (à ajouter absolument dans votre .gitignore). Ce fichier est alimenté par les variables d’environnement du runner CI :
# .kamal/secrets
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
DB_PASSWORD=$DB_PASSWORD
Kamal 2 lit automatiquement ce fichier au moment du déploiement et injecte les valeurs dans les conteneurs. C’est propre, c’est sécurisé.
Un point important si votre runner GitHub Actions tourne sur linux/amd64 mais que vous développez sur Mac (ARM) : précisez la plateforme cible dans votre deploy.yml Kamal pour éviter les surprises :
builder:
arch: amd64
Ça force le build en --platform linux/amd64, ce qui garantit la compatibilité avec votre VPS.
Et voilà le flux complet : vous faites un git push sur main → GitHub Actions se déclenche → l’image Docker est buildée et poussée sur le registry → Kamal 2 déploie la nouvelle version sur le VPS via Kamal Proxy, sans aucune interruption de service. Un vrai pipeline CI/CD, moderne et reproductible.
Zéro downtime en pratique : comprendre Kamal Proxy et les rollbacks
C’est souvent la partie qui suscite le plus de questions : « Mais concrètement, comment Kamal fait pour qu’il n’y ait aucune interruption ? » Bonne nouvelle, le mécanisme est assez simple à comprendre une fois qu’on l’a vu une fois.
Kamal 2 embarque son propre reverse proxy : Kamal Proxy. C’est lui qui remplace Traefik (utilisé dans Kamal 1) et qui orchestre le basculement entre les versions. Léger, rapide, et bien intégré à la CLI Kamal — c’est clairement une amélioration bienvenue.
Voilà ce qui se passe concrètement lors d’un kamal deploy :
- Kamal démarre le nouveau container en parallèle de l’ancien
- Il attend que le health check réponde correctement (par défaut sur la route
/up) - Une fois le check validé, Kamal Proxy bascule le trafic vers le nouveau container
- L’ancien container est ensuite stoppé proprement
Résultat : vos visiteurs ne voient rien. Pas d’erreur 502, pas de page blanche. Le tout en quelques secondes.
Pour le health check, pensez à désactiver le cache sur la route /up côté WordPress. Si un plugin de cache intercepte cette route et renvoie une réponse en cache périmée, Kamal peut valider un container qui n’est pas encore prêt. Vous pouvez aussi définir une route dédiée dans votre deploy.yml :
healthcheck:
path: /health
port: 80
max_attempts: 10
interval: 3s
Et si quelque chose tourne mal après un déploiement ? C’est là que le rollback devient votre meilleur ami. Une seule commande suffit :
kamal rollback
Kamal rebascule automatiquement sur la version précédente en quelques secondes. Pas besoin de re-builder une image, pas besoin de se connecter manuellement au serveur — c’est immédiat.
Pour diagnostiquer un problème post-déploiement, la commande suivante est indispensable :
kamal app logs
Elle vous donne accès aux logs du container en cours d’exécution, directement depuis votre terminal. Pratique pour repérer une erreur PHP, un problème de connexion à la base de données, ou une config WordPress qui cloche.
Quelques conseils pratiques avant de conclure :
- Testez toujours en staging avant de pousser en production. Kamal supporte nativement les environnements multiples — c’est fait pour ça.
- Monitorez vos déploiements avec
kamal app detailspour vérifier l’état des containers en temps réel. - Configurez correctement votre health check : c’est le point critique. Un mauvais check peut soit bloquer un déploiement valide, soit — pire — valider un container défaillant.
Bref, le zéro downtime avec Kamal 2, c’est pas de la magie. C’est un mécanisme bien pensé, à condition de le configurer proprement. Et une fois en place, on ne revient pas en arrière.
