1. Pré‑requis

  • Debian 12 (Bookworm) avec accès sudo.
  • Nginx installé (sinon, voir plus bas).
  • Ports 80 et 443 ouverts.
  • Nom de domaine pointant vers le serveur (recommandé pour HTTPS).
  • Astuce : si plusieurs versions de PHP sont installées, identifiez la version active avec la commande suivante.
php -v
# récupère 8.x.y → notez 8.2 ou 8.1, etc.

2. Mise à jour du système

Apadate : apt update + correctifs

sudo apt update && sudo apt -y full-upgrade
sudo reboot

3. Installer Nginx, PHP‑FPM et extensions

sudo apt install -y nginx php-fpm php-cli php-mbstring php-xml php-zip php-curl php-mysql php-gd php-intl php-bcmath php-json
sudo apt install -y php-imagick php-apcu

Vérifier le socket PHP‑FPM (remplacez 8.2 par votre version si besoin) :

ls -l /run/php/ | grep fpm
# Exemple: /run/php/php8.2-fpm.sock

4. Installer MariaDB/MySQL et sécuriser

sudo apt install -y mariadb-server mariadb-client
sudo mysql_secure_installation

Recommandations pendant l’assistant :

  • Définir un mot de passe root SQL (si non défini).
  • Supprimer utilisateurs anonymes.
  • Désactiver le login root distant.
  • Supprimer la base de test.
  • Recharger les privilèges.

5. Créer un utilisateur DB dédié à phpMyAdmin

phpMyAdmin n’a pas besoin d’un compte root. Créez un compte admin limité.

sudo mysql

Dans le shell SQL :

CREATE USER 'pma_admin'@'localhost' IDENTIFIED BY 'motdepasse-solideIci!';
GRANT ALL PRIVILEGES ON *.* TO 'pma_admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

6. Installer phpMyAdmin (2 méthodes)

6.A : via apt (simple)

sudo apt install -y phpmyadmin

Pendant l’installation :

  • Choisir nginx: Non (il ne sera pas configuré automatiquement) → la configuration Nginx se fera à la main.
  • Choisir dbconfig-common: Oui et définir le mot de passe de l’utilisateur phpMyAdmin pma (différent de pma_admin ci‑dessus).

Les fichiers sont généralement dans /usr/share/phpmyadmin.

6.B : via archive officielle (plus à jour)

cd /var/www
sudo mkdir -p pma && cd pma
# Téléchargez la dernière version depuis https://www.phpmyadmin.net/downloads/
# Exemple :
wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-all-languages.tar.gz
sudo tar xzf phpMyAdmin-*-all-languages.tar.gz
sudo mv phpMyAdmin-*-all-languages phpmyadmin
sudo chown -R www-data:www-data /var/www/pma/phpmyadmin

Créer le fichier de config si besoin :

sudo -u www-data cp /var/www/pma/phpmyadmin/config.sample.inc.php /var/www/pma/phpmyadmin/config.inc.php
sudo -u www-data nano /var/www/pma/phpmyadmin/config.inc.php

Dans config.inc.php, générer un blowfish_secret de 32 caractères aléatoires :

<?php
$cfg['blowfish_secret'] = 'MettezIciUnePhraseSecrèteLongueEtUnique!!!!';

7. Configurer Nginx : alias ou sous‑domaine dédié

Deux approches : /phpmyadmin comme alias sur un vhost existant, ou pma.domaine.tld dédié. La seconde facilite les ACL et le rate‑limit.

Option A — Alias /phpmyadmin sur un vhost existant

Dans votre bloc server, par exemple /etc/nginx/sites-available/mon-site.conf :

location /phpmyadmin {
    alias /usr/share/phpmyadmin;  # ou /var/www/pma/phpmyadmin si méthode 6.B
    index index.php;
    try_files $uri $uri/ /phpmyadmin/index.php?$args;
}

location ~ ^/phpmyadmin/(.+\.php)$ {
    alias /usr/share/phpmyadmin;  # alignez avec votre chemin réel
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock; # ajustez la version
    fastcgi_read_timeout 120s;
}

location ~* ^/phpmyadmin/(.+\.(?:png|jpg|jpeg|gif|css|js|ico|html|svg))$ {
    alias /usr/share/phpmyadmin;  # alignez avec votre chemin réel
    access_log off;
    log_not_found off;
    expires 7d;
}

Option B — Vhost dédié pma.domaine.tld

Créer le fichier /etc/nginx/sites-available/pma.conf :

server {
    listen 80;
    server_name pma.example.com;

    root /usr/share/phpmyadmin;   # ou /var/www/pma/phpmyadmin
    index index.php index.html;

    return 301 https://$host$request_uri; # redirige vers HTTPS après Certbot
}

server {
    listen 443 ssl http2;
    server_name pma.example.com;

    ssl_certificate /etc/letsencrypt/live/pma.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pma.example.com/privkey.pem;

    root /usr/share/phpmyadmin;   # ou /var/www/pma/phpmyadmin
    index index.php;

    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-Content-Type-Options nosniff always;
    add_header Referrer-Policy no-referrer-when-downgrade always;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock; # ajustez la version
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_read_timeout 120s;
    }

    location ~* \.(?:css|js|ico|gif|jpe?g|png|svg)$ {
        access_log off;
        expires 7d;
    }
}

Activer et tester :

sudo ln -s /etc/nginx/sites-available/pma.conf /etc/nginx/sites-enabled/pma.conf
sudo nginx -t && sudo systemctl reload nginx

8. Activer HTTPS avec Let’s Encrypt

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d pma.example.com
# Si alias: certbot --nginx -d mon-site.example.com

Vérifier le renouvellement automatique :

systemctl status certbot.timer

9. Durcissement de phpMyAdmin

  • Désactiver l’accès à /setup (deprecated). Exemple alias :
location ^~ /phpmyadmin/setup { deny all; }

Et si vhost dédié :

location ^~ /setup { deny all; }
  • Blowfish secret unique et long (voir plus haut).
  • Désactiver AllowArbitraryServer pour éviter les risques SSRF. Dans config.inc.php :
<?php
$cfg['AllowArbitraryServer'] = false;
  • Limiter aux connexions locales DB.
  • Désactiver le login root via réseau et préférer sudo mysql.

10. Ajuster PHP (upload, temps d’exécution)

Éditer le fichier /etc/php/8.2/fpm/php.ini (adaptez la version) :

upload_max_filesize = 512M
post_max_size = 512M
max_execution_time = 300
memory_limit = 512M

Puis redémarrer PHP‑FPM :

sudo systemctl restart php8.2-fpm

11. Optimisations (Opcache/APCu)

Dans /etc/php/8.2/fpm/php.ini :

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=100000
opcache.validate_timestamps=1
opcache.revalidate_freq=2

APCu (si installé) dans /etc/php/8.2/mods-available/apcu.ini :

apc.enabled=1
apc.shm_size=128M

12. Limiter l’accès : IP allowlist et HTTP Auth

IP Allowlist (exemple alias /phpmyadmin)

location /phpmyadmin {
    allow 203.0.113.10;   # votre IP fixe
    allow 2001:db8::/48;  # votre préfixe IPv6
    deny all;
    alias /usr/share/phpmyadmin;
    index index.php;
}

HTTP Auth (Basic)

sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd-pma admin

Ajouter dans le vhost :

location /phpmyadmin {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd-pma;
    alias /usr/share/phpmyadmin;
    index index.php;
    try_files $uri $uri/ /phpmyadmin/index.php?$args;
}

Combiner IP allowlist et HTTP Auth pour un meilleur niveau de sécurité.

13. Rate‑limit et Fail2ban

Rate‑limit Nginx

Dans le contexte http, par exemple /etc/nginx/nginx.conf :

limit_req_zone $binary_remote_addr zone=pma_limit:10m rate=5r/s;

Dans le bloc server :

location /phpmyadmin/ {
    limit_req zone=pma_limit burst=20 nodelay;
}

Fail2ban (filtre Nginx ciblé)

sudo apt install -y fail2ban
sudo tee /etc/fail2ban/filter.d/nginx-phpmyadmin.conf >/dev/null <<'EOF'
[Definition]
failregex = ^<HOST> - .* "(GET|POST) /phpmyadmin.*" .* (401|403) .*$
ignoreregex =
EOF

sudo tee /etc/fail2ban/jail.d/nginx-phpmyadmin.local >/dev/null <<'EOF'
[nginx-phpmyadmin]
enabled = true
port    = http,https
filter  = nginx-phpmyadmin
logpath = /var/log/nginx/access.log
maxretry = 8
findtime = 10m
bantime  = 1h
EOF

sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-phpmyadmin

14. Sauvegardes et mises à jour

  • Sauvegardes de configuration : /etc/nginx/, /etc/php/*/fpm/, /etc/phpmyadmin/ ou /var/www/pma/phpmyadmin/.
  • Mises à jour classiques :
sudo apt update && sudo apt -y upgrade
  • Méthode archive officielle (6.B) : retélécharger la nouvelle archive et remplacer le dossier.
  • Réaliser un snapshot VM ou conteneur avant une grosse modification.

15. Tests et Dépannage

  • Tester Nginx :
sudo nginx -t
sudo systemctl reload nginx
  • Logs : /var/log/nginx/access.log, /var/log/nginx/error.log, journalctl -u php8.2-fpm.
  • PHP‑FPM down : vérifier le socket /run/php/php8.2-fpm.sock ou passer en fastcgi_pass 127.0.0.1:9000 si vous utilisez TCP.
  • Erreur 403 sur alias : vérifier alias ou root, try_files et droits www-data.
  • Timeout import : augmenter client_max_body_size dans le bloc server et fastcgi_read_timeout.
  • CSRF token invalide : vérifier cookies, blowfish_secret, et l’horloge système (timedatectl).

16. Annexes utiles

Snippet sécurité Nginx (headers)

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# CSP minimale (testez vos assets avant de l’appliquer en prod)
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' data: blob: https:;" always;

Tuning PHP‑FPM (pool)

Fichier /etc/php/8.2/fpm/pool.d/www.conf :

pm = dynamic
pm.max_children = 32
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 16
pm.max_requests = 500

Adapter selon la RAM et la charge.

UFW (pare‑feu simple)

sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

Nettoyage de l’alias par défaut Debian

Si vous avez installé via apt, Debian peut créer une configuration Apache. Pour Nginx, ignorez‑la et maintenez vos vhosts dans /etc/nginx/sites-available/.


17. Check‑list finale

  • apt update et upgrade effectués
  • Nginx et PHP‑FPM opérationnels (page phpinfo de test)
  • MariaDB sécurisé avec mysql_secure_installation
  • phpMyAdmin installé (apt ou archive) et accessible
  • HTTPS actif (Let’s Encrypt)
  • ACL (IP et/ou HTTP Auth) en place
  • Rate‑limit et Fail2ban actifs
  • Sauvegardes prévues et logs surveillés

Fin du tutoriel. Besoin d’une variante adaptée à ton domaine, à ta version de PHP exacte ou d’un script Bash ou Ansible idempotent ?