Le processus de mise en production et les mesures de suivi/maintenance pour notre application web (Laravel 11 en backend / React 19 en frontend, avec Axios, Bootstrap, base MySQL, hébergement O2Switch). L’objectif est de garantir un déploiement fluide, sécurisé et évolutif, même si plusieurs domaines cohabitent sur le même espace d’hébergement.
Table des matières : [Masquer]
- 1 Spécifications Techniques
- 2 1. Infrastructure de Production
- 3 2. Procédures de Déploiement Optimisées
- 4 3. Maintenance et Surveillance
- 5 4. Optimisations Avancées
- 6
Spécifications Techniques
- Backend: Laravel 11
- Frontend: React 19
- Bibliothèques clés: Axios pour les requêtes API, Bootstrap pour l’interface
- Base de données: MySQL
- Hébergement: O2Switch (mutualisé)
Ce guide détaille les procédures optimisées pour le déploiement et la maintenance d’une application web moderne utilisant Laravel et React dans un environnement d’hébergement mutualisé avec plusieurs domaines.
1. Infrastructure de Production
1.1 Configuration de l’Hébergement
Analyse de l’environnement O2Switch
O2Switch propose un hébergement mutualisé avec certaines spécificités à prendre en compte:
- Type d’accès: CPanel pour la gestion des domaines et sous-domaines
- Limites potentielles: Ressources partagées, contraintes PHP sur hébergement mutualisé
- Avantages: Support PHP récent, possibilité d’accès SSH, certificats SSL inclus
Prérequis techniques validés
Vérifiez systématiquement ces points avant tout déploiement:
# Pour PHP, vérifiez la version via SSH (si disponible) ou via un phpinfo()
php -v # Doit retourner PHP 8.1+ pour Laravel 11
# Vérifiez les extensions PHP requises
php -m | grep -E 'openssl|pdo|mbstring|tokenizer|xml|ctype|json|bcmath|fileinfo'
Configuration multi-domaines recommandée
Pour une architecture multi-domaines efficace:
/home/[user]/
├── public_html/ # Domaine principal
│ ├── index.php # Point d'entrée Laravel (symlink)
│ ├── .htaccess # Configuration Apache
│ ├── ...
│ └── build/ # Build React pour domaine principal
│
├── [domain2.com]/ # Second domaine
│ ├── index.php
│ └── build/ # Build React pour second domaine
│
├── app/ # Code Laravel mutualisé (hors racine web)
│ ├── laravel-core/ # Code source Laravel
│ ├── storage/ # Stockage partagé
│ └── vendor/ # Dépendances
│
└── logs/ # Logs centralisés
├── apache/
├── php/
└── mysql/
1.2 Optimisation de l’environnement
Configuration PHP spécifique
Créez un fichier .user.ini
dans chaque répertoire web:
memory_limit = 256M
upload_max_filesize = 32M
post_max_size = 32M
max_execution_time = 120
max_input_vars = 3000
Configuration Apache optimisée
Fichier .htaccess
à la racine de chaque domaine:
# Performance et cache
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType application/x-font-woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
</IfModule>
# Compression GZIP
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE font/opentype font/ttf font/eot font/otf
</IfModule>
# Redirection vers HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Laravel
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Sécurité
<FilesMatch "^\.">
Order allow,deny
Deny from all
</FilesMatch>
# Protection des fichiers sensibles
<FilesMatch "(^\.env|composer\.json|package\.json|package-lock\.json|composer\.lock)$">
Order allow,deny
Deny from all
</FilesMatch>
2. Procédures de Déploiement Optimisées
2.1 Préparation de l’environnement local
Configuration du pipeline de développement
- Structure Git recommandée:
├── .github/ # CI/CD workflows (si GitHub) │ └── workflows/ │ ├── test.yml │ └── deploy.yml ├── backend/ # Code Laravel │ └── ... ├── frontend/ # Code React │ └── ... └── scripts/ # Scripts de déploiement ├── deploy.sh └── rollback.sh
- Scripts d’automatisation:
scripts/deploy.sh
:
#!/bin/bash
# Variables
ENV=${1:-production} # Permet de spécifier l'environnement (par défaut: production)
# Préparation Backend
echo "Building Laravel application..."
cd backend
composer install --no-dev --optimize-autoloader
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Préparation Frontend
echo "Building React application..."
cd ../frontend
npm ci # Installation précise des dépendances selon package-lock.json
npm run build
# Préparation du package de déploiement
echo "Creating deployment package..."
mkdir -p ../deploy
cp -r ../backend/app ../deploy/
cp -r ../backend/bootstrap ../deploy/
cp -r ../backend/config ../deploy/
cp -r ../backend/database ../deploy/
cp -r ../backend/public ../deploy/
cp -r ../backend/resources ../deploy/
cp -r ../backend/routes ../deploy/
cp -r ../backend/storage ../deploy/
cp -r ../backend/vendor ../deploy/
cp ../backend/.env.${ENV} ../deploy/.env
cp ../backend/artisan ../deploy/
mkdir -p ../deploy/public/build
cp -r ../frontend/build/* ../deploy/public/build/
# Archive pour déploiement
cd ../deploy
zip -r ../deploy-package.zip .
echo "Deployment package ready: deploy-package.zip"
-
- Configuration des environnements: Créez plusieurs fichiers d’environnement pour différents contextes:
.env.development
– Variables pour environnement de développement.env.staging
– Variables pour environnement de préproduction.env.production
– Variables pour environnement de production
Exemple de
.env.production
:APP_NAME="MyApp" APP_ENV=production APP_KEY=base64:votreclé APP_DEBUG=false APP_URL=https://votredomaine.com LOG_CHANNEL=stack LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=error DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=dbname DB_USERNAME=dbuser DB_PASSWORD=dbpassword BROADCAST_DRIVER=log CACHE_DRIVER=file FILESYSTEM_DISK=local QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 # Optimisations de performance CACHE_PREFIX=myapp_cache # Sécurité SESSION_SECURE_COOKIE=true SANCTUM_STATEFUL_DOMAINS=votredomaine.com
- Configuration des environnements: Créez plusieurs fichiers d’environnement pour différents contextes:
2.2 Optimisation du build frontend
Pour des performances optimales du build React:
// Dans package.json, ajoutez ces optimisations:
{
"scripts": {
"build": "GENERATE_SOURCEMAP=false react-scripts build && npm run postbuild",
"postbuild": "node ./scripts/optimize-build.js"
}
}
Créez frontend/scripts/optimize-build.js
:
const fs = require('fs');
const path = require('path');
// Fonction pour parcourir récursivement et optimiser
function processFiles(directory) {
const files = fs.readdirSync(directory);
files.forEach(file => {
const fullPath = path.join(directory, file);
if (fs.statSync(fullPath).isDirectory()) {
processFiles(fullPath);
return;
}
// Traitement des JS
if (file.endsWith('.js')) {
console.log(`Optimizing JS: ${fullPath}`);
// Ici vous pourriez intégrer une minification supplémentaire si nécessaire
}
// Traitement des CSS
if (file.endsWith('.css')) {
console.log(`Optimizing CSS: ${fullPath}`);
// Ici vous pourriez intégrer une optimisation CSS supplémentaire
}
});
}
// Point d'entrée
console.log('Post-build optimization starting...');
processFiles(path.resolve(__dirname, '../build'));
console.log('Post-build optimization complete');
2.3 Déploiement vers O2Switch
Méthode 1: Déploiement via SFTP (Basique)
- Connectez-vous via SFTP (FileZilla ou autre client)
- Uploadez les fichiers du package de déploiement
- Exécutez les migrations et commandes post-déploiement via SSH
Méthode 2: Déploiement automatisé (Recommandée)
- Préparation: Configurer l’accès SSH avec clés
- Script de déploiement distant:
#!/bin/bash
# Variables
REMOTE_USER="o2switch_user"
REMOTE_HOST="ssh.cluster0XX.hosting.ovh.net" # À adapter selon votre serveur O2Switch
REMOTE_PATH="/home/user/app"
PACKAGE_PATH="./deploy-package.zip"
# Transfert du package
echo "Uploading deployment package..."
scp $PACKAGE_PATH $REMOTE_USER@$REMOTE_HOST:/tmp/
# Exécution à distance
ssh $REMOTE_USER@$REMOTE_HOST << 'EOF'
# Création d'un backup
timestamp=$(date +%Y%m%d%H%M%S)
if [ -d "$REMOTE_PATH" ]; then
echo "Creating backup..."
mkdir -p ~/backups
zip -r ~/backups/app-backup-$timestamp.zip $REMOTE_PATH
fi
# Déploiement
echo "Deploying new version..."
mkdir -p $REMOTE_PATH.new
cd $REMOTE_PATH.new
unzip /tmp/deploy-package.zip
# Vérification et configuration des permissions
chmod -R 755 storage bootstrap/cache
# Mise à jour des liens symboliques
if [ -d "$REMOTE_PATH" ]; then
# Préserver les uploads et données persistantes
if [ -d "$REMOTE_PATH/storage/app" ]; then
cp -rp $REMOTE_PATH/storage/app $REMOTE_PATH.new/storage/
fi
fi
# Switch vers la nouvelle version
if [ -d "$REMOTE_PATH" ]; then
mv $REMOTE_PATH $REMOTE_PATH.old
fi
mv $REMOTE_PATH.new $REMOTE_PATH
# Configuration des domaines
# Ces commandes sont à adapter selon votre structure
cd $REMOTE_PATH
ln -sf $REMOTE_PATH/public ~/public_html
# Migrations et cache
cd $REMOTE_PATH
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan storage:link
# Nettoyage
rm /tmp/deploy-package.zip
rm -rf $REMOTE_PATH.old
echo "Deployment complete!"
EOF
- Intégration à GitHub Actions (si utilisé):
.github/workflows/deploy.yml
:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mbstring, intl, pdo_mysql
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install Dependencies
run: |
composer install --no-dev --optimize-autoloader
cd frontend
npm ci
- name: Build
run: |
cd frontend
npm run build
- name: Prepare Deployment
run: bash ./scripts/deploy.sh production
- name: Deploy to O2Switch
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "deploy-package.zip"
target: "/tmp"
- name: Execute Remote Commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# Script de déploiement distant
# Copier le contenu du script SSH ci-dessus
2.4 Vérifications Post-Déploiement
Mettez en place un processus systématique de vérification:
- Vérification de base:
# Vérifier le statut HTTP
curl -Is https://votredomaine.com | head -1
# Vérifier les redirections
curl -Is http://votredomaine.com | grep -i location
- Vérification API:
# Tester un endpoint API
curl -s https://votredomaine.com/api/status | grep -i success
- Liste de contrôle complète:
- ✅ Site accessible via HTTPS
- ✅ Redirection HTTP vers HTTPS fonctionnelle
- ✅ Chargement des assets JS/CSS sans erreur
- ✅ Connexion à la BDD opérationnelle
- ✅ API fonctionnelle
- ✅ Formulaires fonctionnels
- ✅ Page d’accueil correctement rendue
- ✅ Logs sans erreurs critiques
3. Maintenance et Surveillance
3.1 Stratégie de sauvegarde
Mettez en place une stratégie de sauvegarde robuste:
#!/bin/bash
# backup.sh - À exécuter via cron
# Variables
BACKUP_DIR="/home/user/backups"
SITE_DIR="/home/user/app"
DB_NAME="nom_database"
DB_USER="user_database"
DB_PASS="password_database"
DATE=$(date +"%Y-%m-%d")
# Création du répertoire si nécessaire
mkdir -p $BACKUP_DIR/$DATE
# Sauvegarde des fichiers
echo "Backing up files..."
zip -r $BACKUP_DIR/$DATE/files-$DATE.zip $SITE_DIR -x "*/node_modules/*" -x "*/vendor/*"
# Sauvegarde de la base de données
echo "Backing up database..."
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/$DATE/db-$DATE.sql
gzip $BACKUP_DIR/$DATE/db-$DATE.sql
# Rotation (garder 30 jours)
find $BACKUP_DIR -type d -mtime +30 -exec rm -rf {} \;
echo "Backup completed successfully!"
Configuration cron
# Sauvegarde quotidienne à 3h du matin
0 3 * * * /home/user/scripts/backup.sh >> /home/user/logs/backup.log 2>&1
3.2 Monitoring et alertes
Solution de base avec UptimeRobot
- Créez un compte sur UptimeRobot
- Configurez des moniteurs pour:
- Disponibilité du site:
https://votredomaine.com
- API health check:
https://votredomaine.com/api/health
- Certificat SSL (expiration)
- Disponibilité du site:
Solution avancée avec NewRelic ou Datadog
Pour une surveillance plus complète, intégrez:
// Dans AppServiceProvider.php
public function boot()
{
// Ajout de l'observateur de base de données pour le monitoring
DB::listen(function ($query) {
// Enregistrement des requêtes lentes (>100ms)
if ($query->time > 100) {
Log::channel('performance')->info('Slow query: ' . $query->sql, [
'time' => $query->time,
'bindings' => $query->bindings
]);
}
});
}
3.3 Processus de mise à jour
Mises à jour de sécurité
Mettez en place un processus régulier de vérification:
# Vérification des dépendances PHP
composer audit
# Vérification des dépendances JS
cd frontend
npm audit
Mises à jour logicielles
Procédure recommandée pour les mises à jour:
- Créez une branche dédiée:
git checkout -b update/laravel-security-fix
- Mettez à jour les dépendances:
composer update --with-dependencies symfony/http-kernel
- Exécutez les tests:
php artisan test
- Déployez en préproduction et validez
- Fusionnez via Pull Request et déployez en production
3.4 Gestion des incidents
Préparez un plan de réponse aux incidents:
- Détection:
- Alertes automatisées (UptimeRobot, logs)
- Retours utilisateurs
- Évaluation:
# Vérifier les erreurs récentes
tail -n 100 /home/user/logs/laravel.log
# Vérifier la charge serveur
top -b -n 1
- Résolution:
- Rollback rapide si nécessaire:
# Script de rollback
cd /home/user
unzip -o backups/app-backup-TIMESTAMP.zip -d /home/user/
cd app
php artisan migrate:status # Vérifier l'état des migrations avant rollback
- Documentation et post-mortem: Documentez chaque incident pour analyse et amélioration continue
4. Optimisations Avancées
4.1 Mise en cache des requêtes API
Implémentez un système de cache pour les requêtes API fréquentes:
// Dans un contrôleur API
public function getProducts()
{
return Cache::remember('products.all', now()->addHours(1), function () {
return Product::with('categories')->get();
});
}
// Invalidation du cache lors de modifications
public function updateProduct(Request $request, $id)
{
$product = Product::findOrFail($id);
$product->update($request->validated());
Cache::forget('products.all');
Cache::forget("product.{$id}");
return response()->json($product);
}
4.2 Configuration Nginx (si disponible)
Si O2Switch permet la configuration Nginx personnalisée (à vérifier), utilisez ce modèle:
# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Browser caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000";
}
# PHP handling
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
4.3 Configuration optimisée de la base de données
Ajoutez ces optimisations à votre fichier config/database.php
:
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
// Nouvelles optimisations
PDO::ATTR_EMULATE_PREPARES => false, // Requêtes préparées côté serveur
PDO::ATTR_PERSISTENT => true, // Connexions persistantes
]) : [],
],
Lexique
Terme | Description |
---|---|
CI/CD | Continuous Integration/Continuous Deployment – Processus d’automatisation du déploiement |
Build | Processus de compilation et préparation du code pour la production |
Artefact | Fichier ou ensemble de fichiers résultant d’un build (ex: ZIP de déploiement) |
Rollback | Retour à une version précédente en cas de problème |
Zero-downtime deployment | Méthode de déploiement sans interruption de service |
Blue-Green Deployment | Technique de déploiement utilisant deux environnements identiques |
Environnement | Contexte d’exécution (dev, staging, production) |
Canary Release | Déploiement progressif sur un sous-ensemble d’utilisateurs |
Health Check | Vérification automatique de la santé d’une application |
Caching | Stockage temporaire de données pour améliorer les performances |