Erreur 503 sur Apache
Le guide complet pour les administrateurs Apache
MPM, mod_proxy, .htaccess : maîtrisez votre serveur web.
Apache et les erreurs 503
Apache HTTP Server reste le serveur web le plus déployé, notamment sur les hébergements mutualisés, les environnements cPanel/Plesk, et de nombreuses infrastructures d’entreprise.
Les erreurs 503 sur Apache surviennent généralement dans ces contextes :
- Le backend PHP-FPM ou mod_php est down/surchargé
- Les workers MPM sont tous occupés
- Un reverse proxy (mod_proxy) ne peut joindre le backend
- Une règle .htaccess retourne explicitement 503
- Les limites système sont atteintes (connexions, fichiers)
Ce guide couvre chaque scénario avec les solutions appropriées.
Besoin d’aide pour votre infrastructure ? Foxop propose des audits serveur et de l’infogérance haute disponibilité.
Comprendre l’architecture Apache
Les différents modes de traitement (MPM)
Apache peut fonctionner avec différents MPM (Multi-Processing Modules) :
| MPM | Description | Usage recommandé |
|---|---|---|
| prefork | 1 processus par requête, pas de threads | mod_php (legacy), compatibilité maximale |
| worker | Processus + threads | Performance, mémoire optimisée |
| event | Comme worker + gestion async des keepalives | Recommandé avec PHP-FPM |
# Voir le MPM actif
$ apachectl -V | grep MPM
Server MPM: event
# Ou
$ apache2ctl -M | grep mpm
mpm_event_module (shared)
Architecture avec PHP-FPM (recommandé)
flowchart LR
A[Client] --> B[Apache
Port 80/443]
B --> C{Type de requête ?}
C -->|Fichier statique| D[Servir directement]
C -->|PHP| E[mod_proxy_fcgi
→ PHP-FPM]
E --> F[Socket/Port 9000]
F --> G{PHP-FPM répond ?}
G -->|Oui| H[200 OK]
G -->|Down| I[503 Service Unavailable]
G -->|Timeout| J[504 Gateway Timeout]Architecture avec mod_php (legacy)
flowchart LR
A[Client] --> B[Apache + mod_php
Port 80/443]
B --> C{Type de requête ?}
C -->|Fichier statique| D[Servir directement]
C -->|PHP| E[mod_php
Dans le processus Apache]
E --> F{Ressources OK ?}
F -->|Oui| G[200 OK]
F -->|Mémoire épuisée| H[503]
F -->|Workers épuisés| I[503]mod_php est déprécié pour les nouvelles installations. Préférez PHP-FPM avec mod_proxy_fcgi pour de meilleures performances et une meilleure isolation.
Diagnostic : Identifier la cause
Étape 1 : Vérifier les logs Apache
# Logs d'erreur (le plus important)
$ tail -100 /var/log/apache2/error.log
# Sur CentOS/RHEL
$ tail -100 /var/log/httpd/error_log
# Filtrer les erreurs 503
$ grep "503" /var/log/apache2/access.log | tail -50
# Erreurs en temps réel
$ tail -f /var/log/apache2/error.log
Messages d’erreur courants
Erreurs Apache typiques
# PHP-FPM down
[proxy_fcgi:error] [pid 1234] (111)Connection refused: AH01079:
failed to make connection to backend: /run/php/php8.2-fpm.sock
→ PHP-FPM n'écoute pas sur le socket
# Backend timeout
[proxy_fcgi:error] [pid 1234] AH01075: Error dispatching request to :
(polling) backend connection timed out
→ PHP-FPM ne répond pas assez vite
# Tous les workers occupés
[mpm_event:error] [pid 1234] AH00485: scoreboard is full, not at MaxRequestWorkers
→ Plus de workers disponibles
# Limite de fichiers atteinte
[core:error] [pid 1234] (24)Too many open files: AH00024:
Couldn't create accept lock
→ Limite système ulimit atteinte
# mod_php memory exhausted
[core:notice] [pid 1234] PHP Fatal error: Allowed memory size exhausted
→ Script PHP dépasse la limite mémoire
Étape 2 : Vérifier l’état d’Apache
# État du service
$ systemctl status apache2
# ou sur CentOS/RHEL
$ systemctl status httpd
# Processus Apache
$ ps aux | grep apache2 | head -10
# Connexions actives
$ ss -tlnp | grep apache2
# Workers actifs (si mod_status activé)
$ curl -s http://localhost/server-status?auto | grep -E "^(Busy|Idle)Workers"
BusyWorkers: 45
IdleWorkers: 5
Étape 3 : Vérifier les backends
# PHP-FPM
$ systemctl status php8.2-fpm
$ ps aux | grep php-fpm
# Socket existe ?
$ ls -la /run/php/php8.2-fpm.sock
# Test de connexion au socket
$ php -r "var_dump(stream_socket_client('unix:///run/php/php8.2-fpm.sock'));"
Problème 1 : Backend PHP-FPM down
La cause la plus fréquente avec les configurations modernes Apache + PHP-FPM.
Diagnostic
$ grep "proxy_fcgi" /var/log/apache2/error.log | tail -20
[proxy_fcgi:error] AH01079: failed to make connection to backend: /run/php/php8.2-fpm.sock
# Vérifier PHP-FPM
$ systemctl status php8.2-fpm
Active: inactive (dead) ❌
Solutions
Solution 1 : Redémarrer PHP-FPM
$ systemctl restart php8.2-fpm
# Vérifier
$ systemctl status php8.2-fpm
Active: active (running) ✅
# Tester
$ curl -I https://monsite.com
HTTP/1.1 200 OK ✅
Solution 2 : Vérifier la configuration proxy
/etc/apache2/sites-available/monsite.conf
<VirtualHost *:443>
ServerName monsite.com
DocumentRoot /var/www/monsite
# Configuration PHP-FPM via socket Unix
<FilesMatch \\.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
# Ou via TCP
# <FilesMatch \\.php$>
# SetHandler "proxy:fcgi://127.0.0.1:9000"
# </FilesMatch>
</VirtualHost>
Solution 3 : Vérifier que les modules sont chargés
# Modules nécessaires pour PHP-FPM
$ apache2ctl -M | grep -E "proxy|fcgi"
proxy_module (shared)
proxy_fcgi_module (shared)
# Si manquants
$ a2enmod proxy proxy_fcgi
$ systemctl restart apache2
Solution 4 : Permissions du socket
# Vérifier les permissions
$ ls -la /run/php/php8.2-fpm.sock
srw-rw---- 1 www-data www-data 0 Dec 26 14:30 /run/php/php8.2-fpm.sock
# Apache doit pouvoir y accéder
$ ps aux | grep apache2 | head -1
www-data 1234 ... /usr/sbin/apache2
# Si Apache ne tourne pas en www-data, ajuster dans PHP-FPM :
# /etc/php/8.2/fpm/pool.d/www.conf
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Problème 2 : Workers MPM épuisés
Tous les workers Apache sont occupés, les nouvelles requêtes sont refusées.
Diagnostic
# Voir les workers actifs
$ curl -s http://localhost/server-status?auto 2>/dev/null | grep Workers
BusyWorkers: 150
IdleWorkers: 0 # ← Aucun worker libre !
# Ou via les processus
$ ps aux | grep apache2 | wc -l
152
# Logs
$ grep "scoreboard is full" /var/log/apache2/error.log
[mpm_event:error] AH00485: scoreboard is full, not at MaxRequestWorkers
Solutions
Solution 1 : Augmenter les workers MPM Event
/etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
# Processus serveur
StartServers 4
MinSpareThreads 75
MaxSpareThreads 250
# Threads par processus
ThreadsPerChild 25
# Maximum total de connexions simultanées
# MaxRequestWorkers = ServerLimit * ThreadsPerChild
MaxRequestWorkers 400
ServerLimit 16
# Connexions en file d'attente
ListenBacklog 511
# Recyclage des processus (évite memory leaks)
MaxConnectionsPerChild 10000
</IfModule>
$ systemctl restart apache2
Solution 2 : Augmenter les workers MPM Prefork (si mod_php)
/etc/apache2/mods-available/mpm_prefork.conf
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
# Maximum de processus simultanés
# Attention : chaque processus consomme ~50-100 Mo avec mod_php
MaxRequestWorkers 150
ServerLimit 150
MaxConnectionsPerChild 3000
</IfModule>
Avec mod_php (prefork), chaque worker consomme beaucoup de RAM. 150 workers × 100 Mo = 15 Go de RAM. Calculez selon votre serveur.
Solution 3 : Passer à MPM Event + PHP-FPM
Si vous êtes encore en prefork + mod_php, la migration vers event + PHP-FPM améliore drastiquement les performances :
# Désactiver mod_php et prefork
$ a2dismod php8.2
$ a2dismod mpm_prefork
# Activer event et proxy_fcgi
$ a2enmod mpm_event
$ a2enmod proxy_fcgi
# Configurer PHP-FPM
$ a2enconf php8.2-fpm
$ systemctl restart apache2
Problème 3 : Timeout backend
Le backend répond mais trop lentement.
Diagnostic
$ grep -i "timeout" /var/log/apache2/error.log | tail -20
[proxy_fcgi:error] AH01075: Error dispatching request: (polling) backend connection timed out
Solutions
Solution 1 : Augmenter les timeouts proxy
/etc/apache2/sites-available/monsite.conf
<VirtualHost *:443>
ServerName monsite.com
# Timeouts proxy globaux
ProxyTimeout 300
# Ou par location
<LocationMatch "^/(import|export|backup)">
ProxyTimeout 600
</LocationMatch>
# Configuration PHP-FPM avec timeout
<FilesMatch \\.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
# Timeout spécifique pour PHP
ProxySet timeout=300
</FilesMatch>
</VirtualHost>
Solution 2 : Timeouts globaux Apache
/etc/apache2/apache2.conf
# Timeout général (défaut: 60)
Timeout 300
# Timeout keepalive
KeepAliveTimeout 5
Solution 3 : Le vrai problème est côté PHP
# Activer le slow log PHP-FPM
# /etc/php/8.2/fpm/pool.d/www.conf
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
$ systemctl restart php8.2-fpm
# Voir les scripts lents
$ tail -50 /var/log/php-fpm/slow.log
Problème 4 : Configuration .htaccess
Le fichier .htaccess peut retourner explicitement une 503 ou créer des boucles.
Diagnostic
# Vérifier les .htaccess récemment modifiés
$ find /var/www -name ".htaccess" -mtime -1
# Chercher des règles 503
$ grep -r "503\\|maintenance" /var/www/*/.htaccess
Configuration maintenance via .htaccess
.htaccess
# ============================================
# MODE MAINTENANCE
# Décommenter pour activer
# ============================================
RewriteEngine On
# 1. Exclure votre IP
RewriteCond %{REMOTE_ADDR} !^123\\.456\\.789\\.012$
# Ajouter d'autres IPs si besoin
# RewriteCond %{REMOTE_ADDR} !^111\\.222\\.333\\.444$
# 2. Exclure les fichiers statiques (optionnel)
RewriteCond %{REQUEST_URI} !\\.(css|js|png|jpg|gif|svg|ico|woff2?)$ [NC]
# 3. Exclure la page maintenance elle-même
RewriteCond %{REQUEST_URI} !^/maintenance\\.html$
# 4. Rediriger vers 503
RewriteRule ^(.*)$ /maintenance.html [R=503,L]
# 5. Header Retry-After
<IfModule mod_headers.c>
Header always set Retry-After "3600"
Header always set Cache-Control "no-store, no-cache, must-revalidate"
</IfModule>
# 6. ErrorDocument personnalisé
ErrorDocument 503 /maintenance.html
Attention : Le RewriteRule avec [R=503,L] fonctionne mais certaines versions d’Apache ne renvoient pas correctement le code 503. Testez avec curl -I.
Méthode alternative plus fiable
.htaccess
# Méthode avec ErrorDocument (plus fiable)
<IfModule mod_rewrite.c>
RewriteEngine On
# Créer une condition de maintenance
RewriteCond %{DOCUMENT_ROOT}/maintenance.enable -f
RewriteCond %{REMOTE_ADDR} !^123\\.456\\.789\\.012$
RewriteCond %{REQUEST_URI} !^/maintenance\\.html$
RewriteCond %{REQUEST_URI} !\\.(css|js|png|jpg|gif)$ [NC]
RewriteRule ^ - [E=MAINTENANCE:1]
</IfModule>
<IfModule mod_headers.c>
<If "%{ENV:MAINTENANCE} == '1'">
Header always set Retry-After "3600"
</If>
</IfModule>
# Si variable MAINTENANCE définie, retourner 503
<If "%{ENV:MAINTENANCE} == '1'">
ErrorDocument 503 /maintenance.html
# Forcer le 503
RedirectMatch 503 ^/(?!maintenance\\.html)
</If>
Activation :
# Créer le fichier flag pour activer
$ touch /var/www/monsite/maintenance.enable
# Supprimer pour désactiver
$ rm /var/www/monsite/maintenance.enable
Problème 5 : Limites système atteintes
Trop de fichiers ouverts
$ grep "Too many open files" /var/log/apache2/error.log
[core:error] (24)Too many open files: AH00024: Couldn't create accept lock
Solution :
# Voir la limite actuelle
$ ulimit -n
1024 # Trop bas !
# Augmenter pour Apache
$ cat >> /etc/security/limits.conf << EOF
www-data soft nofile 65535
www-data hard nofile 65535
apache soft nofile 65535
apache hard nofile 65535
EOF
# Pour systemd
$ mkdir -p /etc/systemd/system/apache2.service.d/
$ cat > /etc/systemd/system/apache2.service.d/limits.conf << EOF
[Service]
LimitNOFILE=65535
EOF
$ systemctl daemon-reload
$ systemctl restart apache2
# Vérifier
$ cat /proc/$(cat /var/run/apache2/apache2.pid)/limits | grep "open files"
Max open files 65535 65535 files
Mémoire insuffisante
$ dmesg | grep -i "out of memory"
$ grep -i "killed process" /var/log/syslog | grep apache
Solution :
/etc/apache2/mods-available/mpm_event.conf
# Réduire les workers pour économiser la RAM
<IfModule mpm_event_module>
MaxRequestWorkers 150 # Réduire si OOM
MaxConnectionsPerChild 5000 # Recycler plus souvent
</IfModule>
Connexions TCP saturées
# Voir les connexions
$ ss -s
TCP: 8234 (estab 4521, closed 2100, orphaned 45, timewait 1568)
# Si beaucoup de TIME_WAIT
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
# Réduire
$ echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
# Permanent
$ echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf
$ sysctl -p
Problème 6 : Reverse Proxy (mod_proxy)
Si Apache sert de reverse proxy vers d’autres backends.
Configuration type
/etc/apache2/sites-available/monsite.conf
<VirtualHost *:443>
ServerName monsite.com
# Activer le proxy
ProxyPreserveHost On
ProxyRequests Off
# Backend principal
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
# Timeouts
ProxyTimeout 60
# Health check passif
ProxyPass / http://127.0.0.1:3000/ retry=5 timeout=60
</VirtualHost>
Diagnostic
$ grep "proxy:" /var/log/apache2/error.log | tail -20
[proxy:error] AH00959: ap_proxy_connect_backend disabling worker for (127.0.0.1)
# → Backend marqué comme down
[proxy_http:error] AH01114: HTTP: failed to make connection to backend: 127.0.0.1
# → Impossible de se connecter
Solutions
Solution 1 : Load balancing avec failover
/etc/apache2/sites-available/monsite.conf
<VirtualHost *:443>
ServerName monsite.com
# Pool de backends
<Proxy "balancer://mycluster">
BalancerMember http://192.168.1.10:3000 loadfactor=5
BalancerMember http://192.168.1.11:3000 loadfactor=3
BalancerMember http://192.168.1.12:3000 status=+H # Hot standby
ProxySet lbmethod=byrequests
ProxySet failontimeout=on
ProxySet timeout=30
</Proxy>
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
</VirtualHost>
Solution 2 : Page d’erreur personnalisée
/etc/apache2/sites-available/monsite.conf
<VirtualHost *:443>
# Page 503 personnalisée
ErrorDocument 503 /errors/maintenance.html
# Alias pour servir les erreurs même si proxy down
Alias /errors /var/www/errors
<Directory /var/www/errors>
Require all granted
</Directory>
# Headers SEO sur les erreurs
<Location /errors/maintenance.html>
Header always set Retry-After "3600"
</Location>
ProxyPass /errors ! # Ne pas proxifier les erreurs
ProxyPass / http://backend:3000/
</VirtualHost>
Solution 3 : Réactiver un backend désactivé
# Si un backend est marqué comme "in error state"
# Il faut attendre le retry ou redémarrer Apache
$ systemctl reload apache2
# ou forcer avec
$ systemctl restart apache2
Configuration Apache optimisée complète
/etc/apache2/apache2.conf
# === IDENTIFICATION ===
ServerTokens Prod
ServerSignature Off
# === TIMEOUTS ===
Timeout 60
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
# === DIRECTORIES ===
<Directory />
AllowOverride None
Require all denied
</Directory>
<Directory /var/www/>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# === LOGGING ===
LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# === MODULES ===
# Charger les modules nécessaires via a2enmod
/etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
StartServers 4
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
ServerLimit 16
MaxConnectionsPerChild 10000
ListenBacklog 511
</IfModule>
/etc/apache2/sites-available/monsite.conf
<VirtualHost *:80>
ServerName monsite.com
ServerAlias www.monsite.com
Redirect permanent / https://monsite.com/
</VirtualHost>
<VirtualHost *:443>
ServerName monsite.com
DocumentRoot /var/www/monsite
# === SSL ===
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/monsite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/monsite.com/privkey.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# === SECURITY HEADERS ===
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# === PHP-FPM ===
<FilesMatch \\.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
# === STATIC FILES ===
<FilesMatch "\\.(jpg|jpeg|png|gif|ico|css|js|woff2?|svg|webp)$">
ExpiresActive On
ExpiresDefault "access plus 30 days"
Header set Cache-Control "public, immutable"
</FilesMatch>
# === MAINTENANCE MODE ===
# Méthode via fichier flag
<IfModule mod_rewrite.c>
RewriteEngine On
# Si fichier .maintenance existe
RewriteCond %{DOCUMENT_ROOT}/.maintenance -f
# Exclure votre IP
RewriteCond %{REMOTE_ADDR} !^VOTRE_IP$
# Exclure la page maintenance
RewriteCond %{REQUEST_URI} !^/maintenance\\.html$
RewriteCond %{REQUEST_URI} !\\.(css|js|png|jpg|gif)$ [NC]
# Retourner 503
RewriteRule ^ - [R=503,L]
</IfModule>
ErrorDocument 503 /maintenance.html
<Location /maintenance.html>
Header always set Retry-After "3600"
Header always set Cache-Control "no-store"
</Location>
# === RATE LIMITING ===
<IfModule mod_ratelimit.c>
<Location /api/>
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 500
</Location>
</IfModule>
# === PROTECTION ===
# Bloquer xmlrpc.php (WordPress)
<Files xmlrpc.php>
Require all denied
</Files>
# Limiter accès admin
<LocationMatch "^/(wp-admin|admin|administrator)">
# Rate limiting via mod_evasive ou fail2ban
</LocationMatch>
# === LOGS ===
ErrorLog ${APACHE_LOG_DIR}/monsite-error.log
CustomLog ${APACHE_LOG_DIR}/monsite-access.log combined
</VirtualHost>
Commandes Apache essentielles
# === GESTION DU SERVICE ===
# Démarrer / Arrêter / Redémarrer
$ systemctl start apache2
$ systemctl stop apache2
$ systemctl restart apache2
# Recharger la config (graceful, sans couper les connexions)
$ systemctl reload apache2
# ou
$ apachectl graceful
# === TEST ET DIAGNOSTIC ===
# Tester la configuration
$ apachectl configtest
# ou
$ apache2ctl -t
Syntax OK
# Voir la configuration effective
$ apachectl -S
# Voir les modules chargés
$ apachectl -M
# Version et compilation
$ apachectl -V
# === MODULES ===
# Activer un module
$ a2enmod rewrite
$ a2enmod headers
$ a2enmod proxy_fcgi
$ a2enmod ssl
# Désactiver un module
$ a2dismod php8.2
# === SITES ===
# Activer un site
$ a2ensite monsite.conf
# Désactiver un site
$ a2dissite 000-default.conf
# === LOGS ===
# Erreurs en temps réel
$ tail -f /var/log/apache2/error.log
# Accès en temps réel
$ tail -f /var/log/apache2/access.log
# Filtrer les erreurs 5xx
$ grep " 50[0-9] " /var/log/apache2/access.log | tail -50
# === MONITORING ===
# Server status (si mod_status activé)
$ curl -s http://localhost/server-status?auto
# Processus Apache
$ ps aux | grep apache2
# Ports écoutés
$ ss -tlnp | grep apache2
# === PERFORMANCE ===
# Benchmark simple
$ ab -n 1000 -c 50 https://monsite.com/
Activer mod_status pour le monitoring
/etc/apache2/mods-available/status.conf
<IfModule mod_status.c>
<Location /server-status>
SetHandler server-status
# Accès local uniquement
Require local
# Ou depuis IP spécifique
# Require ip 192.168.1.0/24
</Location>
# Statistiques étendues
ExtendedStatus On
</IfModule>
$ a2enmod status
$ systemctl reload apache2
# Consulter
$ curl http://localhost/server-status?auto
Total Accesses: 123456
Total kBytes: 456789
Uptime: 86400
ReqPerSec: 1.42
BytesPerSec: 5432
BytesPerReq: 3809
BusyWorkers: 12
IdleWorkers: 38
Script de surveillance
/usr/local/bin/check-apache.sh
#!/bin/bash
# Surveillance Apache + PHP-FPM
ALERT_EMAIL="[email protected]"
SITE_URL="https://monsite.com"
# Vérifier Apache
if ! systemctl is-active --quiet apache2; then
echo "CRITICAL: Apache is down" | mail -s "[ALERT] Apache down" $ALERT_EMAIL
systemctl restart apache2
exit 1
fi
# Vérifier PHP-FPM
if ! systemctl is-active --quiet php8.2-fpm; then
echo "CRITICAL: PHP-FPM is down" | mail -s "[ALERT] PHP-FPM down" $ALERT_EMAIL
systemctl restart php8.2-fpm
exit 1
fi
# Vérifier le site
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$SITE_URL")
if [ "$HTTP_CODE" != "200" ]; then
echo "Site returned HTTP $HTTP_CODE" | mail -s "[ALERT] Site HTTP $HTTP_CODE" $ALERT_EMAIL
exit 1
fi
# Vérifier les workers (si mod_status)
BUSY=$(curl -s "http://localhost/server-status?auto" 2>/dev/null | grep "BusyWorkers" | awk '{print $2}')
IDLE=$(curl -s "http://localhost/server-status?auto" 2>/dev/null | grep "IdleWorkers" | awk '{print $2}')
if [ -n "$IDLE" ] && [ "$IDLE" -lt 5 ]; then
echo "WARNING: Only $IDLE idle workers (Busy: $BUSY)" | mail -s "[WARN] Apache workers low" $ALERT_EMAIL
fi
exit 0
# Cron toutes les minutes
$ crontab -e
* * * * * /usr/local/bin/check-apache.sh >> /var/log/apache-check.log 2>&1
Migration de mod_php vers PHP-FPM
Si vous êtes encore sur une configuration legacy avec mod_php :
Étape 1 : Installer PHP-FPM
$ apt install php8.2-fpm
$ systemctl enable php8.2-fpm
$ systemctl start php8.2-fpm
Étape 2 : Configurer Apache
# Désactiver mod_php
$ a2dismod php8.2
# Désactiver MPM prefork
$ a2dismod mpm_prefork
# Activer MPM event et proxy_fcgi
$ a2enmod mpm_event
$ a2enmod proxy
$ a2enmod proxy_fcgi
# Activer la configuration PHP-FPM
$ a2enconf php8.2-fpm
Étape 3 : Mettre à jour les vhosts
Avant (mod_php)
<VirtualHost *:80>
# PHP géré automatiquement par mod_php
</VirtualHost>
Après (PHP-FPM)
<VirtualHost *:80>
<FilesMatch \\.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
Étape 4 : Redémarrer
$ apache2ctl configtest
$ systemctl restart apache2
Avantages de la migration
| Aspect | mod_php (prefork) | PHP-FPM (event) |
|---|---|---|
| RAM par worker | ~100-150 Mo | ~10-20 Mo |
| Connexions simultanées | Limitées | Beaucoup plus |
| Isolation | Aucune | Process séparés |
| Redémarrage PHP | Redémarre Apache | Indépendant |
| Performance | Correcte | Nettement meilleure |
Infrastructure haute disponibilité
Audit, optimisation, migration, monitoring 24/7.
Questions fréquentes
Quelle est la différence entre apachectl graceful et systemctl restart ?
apachectl graceful (ou systemctl reload apache2) recharge la configuration sans interrompre les connexions en cours : les workers existants terminent leurs requêtes avant de mourir. systemctl restart arrête et redémarre complètement Apache, coupant toutes les connexions. Utilisez graceful en production sauf si un redémarrage complet est nécessaire.
Comment savoir si je dois utiliser prefork, worker ou event ?
Event est recommandé pour la plupart des cas avec PHP-FPM. Worker est une alternative si event pose problème. Prefork est obligatoire uniquement si vous utilisez mod_php ou des modules non thread-safe. Si vous partez de zéro, choisissez event + PHP-FPM.
Mon .htaccess ne fonctionne pas, pourquoi ?
Vérifiez que AllowOverride All est configuré pour votre DocumentRoot dans la config Apache. Vérifiez aussi que mod_rewrite est activé (a2enmod rewrite). Enfin, vérifiez la syntaxe avec apachectl configtest et regardez les logs d’erreur.
Apache ou Nginx, lequel choisir ?
Les deux sont excellents. Nginx est généralement plus performant pour les fichiers statiques et comme reverse proxy. Apache est plus flexible avec .htaccess et mod_rewrite, et mieux supporté sur les hébergements mutualisés. Pour de nouvelles installations, Nginx est souvent préféré. Pour des migrations ou des environnements existants, Apache reste un excellent choix.