Guide de déploiement

Héberger MySQL sur un VPS : guide complet

Déployer sur un VPS Cloud →

Tutoriel

Héberger MySQL sur un VPS : guide complet

Bases de données9 min de lecture6 étapes

MySQL fait tourner une immense partie du web : WordPress, Magento, Laravel et des milliers d'applications PHP. L'auto-héberger sur un VPS vous offre des performances dédiées, un contrôle complet de la configuration InnoDB et des coûts maîtrisés, loin des limites des hébergements mutualisés.

Sommaire· Pourquoi auto-héberger MySQL sur un VPS1/9
  1. 01Pourquoi auto-héberger MySQL sur un VPS
  2. 02Les bénéfices concrets d'un MySQL auto-hébergé
  3. 03Prérequis chiffrés avant de commencer
  4. 04Déployer MySQL 8.4 avec Docker en production
  5. 05Sécurisation : les gestes indispensables
  6. 06Optimiser les performances InnoDB
  7. 07Accès distant sécurisé : le tunnel SSH
  8. 08Sauvegardes automatisées : stratégie complète
  9. 09Dépannage : 5 erreurs fréquentes

Pourquoi auto-héberger MySQL sur un VPS

Sur un hébergement mutualisé, votre base MySQL partage la RAM et l'I/O avec des centaines d'autres sites, et vous ne pouvez modifier ni innodb_buffer_pool_size, ni les modes SQL, ni la version du moteur. Sur un VPS, vous disposez de ressources dédiées, vous choisissez entre MySQL 8.4 LTS et MariaDB, et vous accédez au fichier my.cnf pour optimiser chaque paramètre. C'est le bon choix pour une boutique e-commerce, un CMS à fort trafic ou une API qui a besoin de transactions rapides et d'un buffer pool généreux. Vous gérez aussi vos propres utilisateurs, vos grants au niveau table, et votre stratégie de réplication maître-esclave.

Les bénéfices concrets d'un MySQL auto-hébergé

  • Ressources dédiées : tout le buffer pool InnoDB pour vos données, sans voisins bruyants.
  • Accès complet à my.cnf : innodb_buffer_pool_size, max_connections, modes SQL stricts.
  • Choix du moteur : MySQL 8.4 LTS pour la stabilité long terme, ou MariaDB pour ses moteurs additionnels.
  • Réplication maître-esclave configurable pour la lecture déportée ou la reprise après incident.
  • Backups logiques (mysqldump) ou physiques (xtrabackup) selon votre volume.
  • Pas de quota arbitraire sur la taille des bases ou le nombre de connexions simultanées.

Prérequis chiffrés avant de commencer

Version recommandée : MySQL 8.4 LTS (version actuelle : 8.4.11), la branche LTS officielle, stable jusqu'en 2032. Évitez MySQL 8.0 sur de nouvelles installations : son support actif se termine en 2025.

RAM : 1 Go minimum pour un environnement de test ou un blog léger. Comptez 2 Go pour un WordPress ou une petite application en production, et 4 à 8 Go pour Magento, PrestaShop ou une API à fort trafic. La règle de base : allouez 60 à 70 % de la RAM disponible à innodb_buffer_pool_size.

CPU : 2 vCPU suffisent pour la majorité des cas. Montez à 4 vCPU dès que vos requêtes sont nombreuses ou que vous activez la réplication.

Stockage : 30 Go de SSD NVMe comme point de départ ; réservez de l'espace supplémentaire pour les binlogs si vous activez la réplication ou la restauration point-in-time.

Ports : MySQL écoute par défaut sur le port 3306. Ce port ne doit jamais être ouvert sur l'interface publique. Le paramètre bind-address dans my.cnf doit pointer sur 127.0.0.1 ou sur l'adresse du réseau privé inter-VPS, pas sur 0.0.0.0.

Système : Ubuntu 22.04 ou 24.04 LTS, Docker et Docker Compose v2, un volume persistant dédié.

Déployer MySQL 8.4 avec Docker en production

  1. Sécuriser le VPS

    Mettez le système à jour (apt update && apt upgrade -y), installez Docker, désactivez la connexion SSH par mot de passe au profit des clés (PasswordAuthentication no dans sshd_config), et fermez le port 3306 vers l'extérieur :

    ufw deny 3306
    ufw allow OpenSSH
    ufw enable

    MySQL ne doit écouter que sur le réseau interne du conteneur Docker.

  2. Définir le docker-compose.yml

    Déclarez un service mysql:8.4, montez un volume sur /var/lib/mysql, et passez les variables d'environnement via un fichier .env :

    # .env
    MYSQL_ROOT_PASSWORD=motdepasse_root_fort
    MYSQL_DATABASE=ma_base
    MYSQL_USER=app_user
    MYSQL_PASSWORD=motdepasse_app
    # docker-compose.yml
    services:
      mysql:
        image: mysql:8.4
        restart: unless-stopped
        env_file: .env
        volumes:
          - mysql_data:/var/lib/mysql
          - ./conf.d:/etc/mysql/conf.d:ro
        ports:
          - "127.0.0.1:3306:3306"
    volumes:
      mysql_data:

    Notez le bind sur 127.0.0.1 dans ports : le port ne sera accessible que depuis le VPS lui-même.

  3. Créer une base et un utilisateur dédié

    Après docker compose up -d, connectez-vous au conteneur :

    docker exec -it mysql mysql -u root -p

    Créez ensuite la base et l'utilisateur applicatif :

    CREATE DATABASE ma_base CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    CREATE USER 'app_user'@'%' IDENTIFIED BY 'motdepasse_app';
    GRANT SELECT, INSERT, UPDATE, DELETE ON ma_base.* TO 'app_user'@'%';
    FLUSH PRIVILEGES;

    Limitez les grants au strict nécessaire : jamais GRANT ALL PRIVILEGES pour un compte applicatif.

  4. Durcir l'installation

    Exécutez l'équivalent de mysql_secure_installation manuellement :

    -- Supprimer les utilisateurs anonymes
    DELETE FROM mysql.user WHERE User='';
    -- Interdire le login root distant
    DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
    -- Supprimer la base de test
    DROP DATABASE IF EXISTS test;
    FLUSH PRIVILEGES;

    N'utilisez jamais le compte root depuis votre application. Vérifiez que bind-address = 127.0.0.1 est bien présent dans votre conf.d/custom.cnf.

  5. Exposer en TLS si nécessaire

    Si une application externe doit se connecter à distance, ne jamais exposer le port 3306 directement sur Internet. Utilisez un tunnel SSH :

    ssh -L 3306:127.0.0.1:3306 [email protected] -N

    La connexion depuis votre poste cible alors 127.0.0.1:3306, chiffrée par SSH. Pour un accès inter-VPS permanent, configurez un réseau privé entre vos serveurs et laissez MySQL écouter uniquement sur cette interface privée. Activez le chiffrement TLS natif MySQL uniquement pour les connexions applicatives qui traversent ce réseau privé.

  6. Planifier les sauvegardes

    Programmez un mysqldump --single-transaction quotidien via cron pour des dumps cohérents sans verrou :

    # /etc/cron.d/mysql-backup
    0 2 * * * root docker exec mysql mysqldump -u root -p"${MYSQL_ROOT_PASSWORD}" --single-transaction --all-databases | gzip > /backups/mysql-$(date +\%Y\%m\%d).sql.gz

    Conservez au moins 7 jours de rétention, et archivez les dumps hors du VPS (stockage objet, SFTP distant). Testez la restauration une fois par mois : un backup non testé n'est pas un backup. Pour les grosses bases, basculez sur Percona XtraBackup pour des sauvegardes physiques rapides sans interrompre le service.

Sécurisation : les gestes indispensables

mysql_secure_installation en conteneur. L'image Docker officielle ne l'exécute pas automatiquement : faites-le à la main après le premier démarrage (étape 4 ci-dessus).

Suppression du root distant. Le compte root ne doit être accessible que depuis localhost. Un compte root accessible depuis % est la première faille exploitée lors d'un scan de ports.

Utilisateur dédié par application. Chaque application connectée reçoit son propre compte MySQL avec des droits restreints à sa propre base. Une application compromise ne peut alors pas lire ni modifier les données des autres.

UFW + bind-address. La double protection est obligatoire : ufw deny 3306 au niveau du pare-feu système, et bind-address = 127.0.0.1 dans my.cnf côté MySQL. L'une ne dispense pas de l'autre.

Mots de passe forts. Utilisez caching_sha2_password (plugin par défaut sous MySQL 8.x) et des mots de passe générés (au moins 20 caractères, alphanumérique + symboles). Stockez-les dans des secrets gérés, jamais dans le code source.

Optimiser les performances InnoDB

Ces paramètres s'ajoutent dans votre fichier conf.d/custom.cnf monté en lecture seule dans le conteneur.

innodb_buffer_pool_size : paramètre le plus important. Réglez-le à 60–70 % de la RAM du VPS. Sur un VPS de 4 Go, comptez 2,5 à 2,8 Go. Trop petit = lectures disque fréquentes ; trop grand = swap.

innodb_flush_log_at_trx_commit : la valeur 2 offre un bon compromis performance / durabilité pour la plupart des applications. La valeur 1 (par défaut) est plus sûre mais plus lente ; la valeur 0 est la plus rapide mais risquée en cas de crash.

max_connections : ajustez selon votre charge réelle. La valeur par défaut (151) est souvent trop basse pour une application à fort trafic, trop haute pour un petit blog. Chaque connexion consomme ~1 Mo de RAM, tenez-en compte.

slow_query_log : activez-le avec slow_query_log = 1 et long_query_time = 1 pour capturer toutes les requêtes dépassant 1 seconde. C'est votre premier outil d'optimisation.

Exemple de custom.cnf pour un VPS de 4 Go :

[mysqld]
innodb_buffer_pool_size = 2G
innodb_flush_log_at_trx_commit = 2
max_connections = 200
slow_query_log = 1
long_query_time = 1
log_bin = /var/lib/mysql/binlog
binlog_format = ROW

Accès distant sécurisé : le tunnel SSH

Exposer le port 3306 sur l'interface publique de votre VPS est une erreur de sécurité grave : les scanners automatisés tentent des attaques par force brute sur ce port en permanence. La bonne pratique est le tunnel SSH.

Connexion ponctuelle depuis votre poste :

ssh -L 3306:127.0.0.1:3306 [email protected] -N

Ouvrez ensuite votre client MySQL sur 127.0.0.1:3306 — le trafic transite chiffré par SSH.

Connexion permanente inter-VPS : si votre application tourne sur un second VPS du même réseau privé, configurez MySQL pour écouter sur l'adresse réseau privée uniquement (bind-address = 10.0.0.X), et autorisez uniquement l'IP du serveur applicatif dans UFW :

ufw allow from 10.0.0.5 to any port 3306

À proscrire : bind-address = 0.0.0.0 sans pare-feu, port 3306 ouvert en public, ou comptes MySQL avec Host='%' sans restriction IP.

Sauvegardes automatisées : stratégie complète

Une stratégie de sauvegarde MySQL repose sur deux niveaux complémentaires.

Niveau 1 — dump logique quotidien (mysqldump) : cohérent grâce à --single-transaction (pas de verrou en lecture sur InnoDB), portable entre versions. Convient aux bases jusqu'à quelques dizaines de Go.

Niveau 2 — binlogs pour la restauration point-in-time : activez log_bin dès le départ. Combinés à un dump hebdomadaire complet, les binlogs permettent de rejouer chaque transaction jusqu'à la seconde précédant un incident.

Pour les grandes bases — Percona XtraBackup : sauvegarde physique sans interrompre le service, restauration rapide (copie de fichiers plutôt que re-exécution SQL).

Rétention et archivage : ne stockez pas les sauvegardes uniquement sur le VPS. Un VPS corrompu emporte ses propres backups. Exportez vers un stockage objet ou un serveur SFTP distant, et conservez au minimum 7 jours.

Tester la restauration : un backup non testé n'est pas un backup. Planifiez un test mensuel : restaurez sur un conteneur temporaire et vérifiez que vos données sont intactes.

# Restauration depuis un dump compressé
zcat /backups/mysql-20260917.sql.gz | docker exec -i mysql mysql -u root -p

Dépannage : 5 erreurs fréquentes

Access denied for user 'app'@'...'
Le compte existe mais le Host ne correspond pas. MySQL vérifie l'IP source exacte. Si l'application se connecte depuis un conteneur Docker, l'IP source peut être 172.17.0.x et non localhost. Vérifiez avec :

SELECT User, Host FROM mysql.user;

Solution : créez le compte avec 'app_user'@'%' (ou l'IP exacte du conteneur) et relancez FLUSH PRIVILEGES.

Too many connections
max_connections est atteint. Vérifiez le nombre de connexions actives avec :

SHOW STATUS LIKE 'Threads_connected';

Augmentez max_connections dans custom.cnf et vérifiez que votre application utilise un pool de connexions (pas une nouvelle connexion par requête).

Table '...' is marked as crashed
Corruption InnoDB, souvent après un arrêt brutal. Tentez une réparation :

mysqlcheck -u root -p --auto-repair --all-databases

Si la table ne se répare pas, restaurez depuis votre dernier backup cohérent. C'est pour cela qu'un backup testé est obligatoire.

Can't connect to MySQL server on '127.0.0.1' (111)
MySQL n'écoute pas sur l'interface attendue. Vérifiez bind-address dans custom.cnf et relancez le conteneur. Vérifiez aussi que le conteneur est bien démarré avec docker compose ps.

ERROR 1819 (HY000): Your password does not satisfy the current policy
Le plugin de validation de mot de passe MySQL 8 refuse les mots de passe trop simples. Utilisez un mot de passe d'au moins 8 caractères avec majuscules, chiffres et symboles, ou ajustez validate_password.policy = LOW dans custom.cnf pour un environnement de développement uniquement.

Activez les binlogs (log_bin + binlog_format=ROW) dès le départ : ils sont la clé de la restauration point-in-time. Combinés à un mysqldump complet hebdomadaire, ils permettent de rejouer toutes les transactions jusqu'à la seconde précédant un incident. Et si vous montez un esclave en réplication sur un second VPS, ces mêmes binlogs alimentent la réplica en temps réel pour vos lectures déportées.

Hébergez votre MySQL sur un VPS performant

Le VPS Cloud ServOrbit avec template Docker prêt à l'emploi vous offre SSD et ressources garanties pour faire tourner MySQL sans compromis.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet