Update MySQL client and server versions using apt config.

Mettre à jour MySQL client, server et apt-config

Un an après mon article sur l’erreur APT : the following packages have been kept back, voici que cela recommence : impossible d’installer les mises à jour de mysql-client et mysql-server parce que mysql-apt-config n’est plus à jour.

J’ai tendance à oublier la solution parce que je n’y suis confronté que depuis peu donc j’ai écris un petit script bash que je pourrai lancer la prochaine fois, histoire de gagner du temps.

Pré-requis: installation de pup

pup est un outil en ligne de commande pour traiter le HTML. Il lit à partir de stdin, imprime vers stdout, et permet à l’utilisateur de filtrer des parties de la page en utilisant des sélecteurs CSS.

Nous téléchargeons pup depuis son repo sur Github, on extraie le binaire et on le déplace dans /usr/local/bin/ :

wget https://github.com/ericchiang/pup/releases/download/v0.4.0/pup_v0.4.0_linux_amd64.zip

unzip pup_v0.4.0_linux_amd64.zip

sudo mv pup /usr/local/bin/

Script bash pour mettre à jour MySQL avec mysql-apt-config

Nous créons notre nouveau script, et nous le rendons exécutable:

cd /home/scripts

nano install-latest-mysql-apt.sh

chmod +x install-latest-mysql-apt.sh

Et voici le contenu du script:

#!/bin/bash
# ----------------------------------------- #
# Script Name: install-latest-mysql-apt.sh  #
# Author: Matt Biscay                       #
# URL: https://www.skyminds.net/?p=613967   #
# ----------------------------------------- #

# Color codes
RED=$(tput bold; tput setaf 1)
GREEN=$(tput bold; tput setaf 2)
YELLOW=$(tput bold; tput setaf 3)
MAGENTA=$(tput bold; tput setaf 5)
NC=$(tput sgr0) # No Color

# Function to print the header
function print_header() {
  echo -e "${YELLOW}# ----------------------------------------- #${NC}"
  echo -e "${YELLOW}# Script Name: install-latest-mysql-apt.sh  #${NC}"
  echo -e "${YELLOW}# Author: Matt Biscay                       #${NC}"
  echo -e "${YELLOW}# URL: https://www.skyminds.net/?p=613967   #${NC}"
  echo -e "${YELLOW}# ----------------------------------------- #${NC}"
}

# Print the header
print_header

# Function to check if the command exists
function check_command() {
  command -v "$1" &> /dev/null || {
    echo -e "${RED}$1 is not installed. Please install it and try again.${NC}"
    exit 1
  }
}

# Check if wget, unzip are installed
check_command wget
check_command unzip

# Check if pup is installed
if ! command -v pup &> /dev/null; then
  read -p $"${MAGENTA}The \"pup\" tool is not installed, would you like to install it now? (Y/N) ${NC}" INSTALL_PUP
  case ${INSTALL_PUP:0:1} in
    [Yy]* )
      TMP_DIR=$(mktemp -d)
      wget https://github.com/ericchiang/pup/releases/download/v0.4.0/pup_v0.4.0_linux_amd64.zip -O "$TMP_DIR/pup.zip"
      unzip "$TMP_DIR/pup.zip" -d "$TMP_DIR"
      mv "$TMP_DIR/pup" /usr/local/bin/
      rm -r "$TMP_DIR"
      echo -e "${GREEN}Package pup has been installed.${NC}"
      ;;
    [Nn]* )
      echo "Exiting since pup is not installed."
      exit 1
      ;;
    * )
      echo -e "${RED}Invalid input. Please enter Y or N.${NC}"
      exit 1
      ;;
  esac
fi

BASE_URL="https://dev.mysql.com"
INITIAL_URL="${BASE_URL}/downloads/repo/apt/"

# Create temporary files
TMP_INITIAL=$(mktemp)
TMP_SECONDARY=$(mktemp)

echo "Fetching initial page... $INITIAL_URL"
wget -qO- "$INITIAL_URL" > "$TMP_INITIAL"

# Extract the secondary download page URL from the main page
echo "Extracting secondary page URL..."
SECONDARY_URL=$(cat "$TMP_INITIAL" | pup 'div.button03 a attr{href}')
echo "Secondary URL: ${BASE_URL}${SECONDARY_URL}"

# Fetch the secondary page and store its content for debugging
echo "Fetching secondary page..."
wget -qO- "${BASE_URL}${SECONDARY_URL}" > "$TMP_SECONDARY"

# Extract the download link from the secondary page
echo "Extracting download link..."
DOWNLOAD_URL=$(cat "$TMP_SECONDARY" | pup 'a:contains("No thanks, just start my download.") attr{href}')
echo "Download URL: ${BASE_URL}${DOWNLOAD_URL}"

# Ask user if they want to install mysql-apt-config
read -p $"${MAGENTA}Do you want to download and install the package? (Y/N) ${NC}" DOWNLOAD_MYSQL_APT_CONFIG
case ${DOWNLOAD_MYSQL_APT_CONFIG:0:1} in
    [Yy]* )
        wget "${BASE_URL}${DOWNLOAD_URL}" -O mysql-apt-config.deb
        dpkg -i mysql-apt-config.deb

        echo -e "${GREEN}Package mysql-apt-config has been updated.${NC}"

        read -p $"${MAGENTA}Are you ready to install updates with \"apt update && apt upgrade\"? (Y/N) ${NC}" UPDATE_UPGRADE
        case ${UPDATE_UPGRADE:0:1} in
            [Yy]* )
                apt update && apt upgrade
                ;;
            [Nn]* )
                echo "Exiting without installing updates."
                ;;
            * )
                echo -e "${RED}Invalid input. Please enter Y or N.${NC}"
                ;;
        esac
        ;;
    [Nn]* )
        echo "Exiting without installing."
        ;;
    * )
        echo -e "${RED}Invalid input. Please enter Y or N.${NC}"
        ;;
esac

# Trap to clean up temporary files
trap 'rm -f "$TMP_INITIAL" "$TMP_SECONDARY" mysql-apt-config.deb' EXIT

Fonctionnement du script

Le script commence par vérifier que pup est installé. S’il ne l’est pas, on prompte l’utilisateur pour l’installer:

The "pup" tool is not installed, would you like to install it now? (Y/N) y

Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.109.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1718186 (1.6M) [application/octet-stream]
Saving to: ‘/tmp/tmp.4buPXeejfo/pup.zip’

Archive:  /tmp/tmp.4buPXeejfo/pup.zip
  inflating: /tmp/tmp.4buPXeejfo/pup
Package pup has been installed.

Le script effectue deux requêtes sur le site de MySQL: lors de la première requête, il identifie le lien du bouton “Download”.

Lire la suite

wordpress rocketstack

WordPress Rocket Stack : envoyez WordPress sur orbite !

Sur Orion, j’ai installé ma WordPress Rocket Stack qui est configurée avec la stack suivante:

  • Ubuntu Server 22.04 LTS
  • MySQL 8+
  • NginX 1.25+
  • PHP 8.3
  • Redis
  • Nginx FastCGI Cache
  • Fail2ban
  • LetsEncrypt avec acme.sh

Hébergement

L’hébergement est la base de votre site, c’est tout simplement la fondation sur laquelle va reposer votre code.

Vous avez tout intérêt à avoir un très bon hébergeur : il doit être rapide dès le départ et offrir de bonnes garanties en termes de performance et de sécurité.

Si vous avez un site WordPress ou WooCommerce, je ne peux que vous recommander Kinsta, WPEngine ou Nexcess. Tous trois sont de très bons hébergeurs, particulièrement orientés vers la performance avec des ressources garanties et un support technique réactif et efficace en cas de besoin.

Personnellement, j’utilise un serveur dédié chez OVH parce que j’héberge pas mal de sites et j’ai besoin d’avoir un contrôle fin sur la configuration de chacun des services.

Ubuntu Server

J’étais auparavant sous Debian mais j’ai finalement opté pour Ubuntu Server 22.04 LTS pour ce nouveau serveur.

L’avantage d’Ubuntu est de pouvoir disposer des mises à jour plus rapidement que sous Debian.

Lire la suite

Redémarrer la machine virtuelle de Local by Flywheel photo

Local : résoudre les problèmes d’importation de la base de données

Aujourd’hui, on importe la base de données d’un site existant dans la nouvelle version de Local Lightning, estampillée 5.4.1.

D’habitude, je lance Adminer > Import, je sélectionne mon fichier de base de données et boom, la base est importée. Mais aujourd’hui, rien ne se passe comme prévu: Adminer mouline, mouline, perd la moitié du design de sa page et n’importe pas la base.

SSH à la rescousse

Je me dis qu’on aura peut-être plus de chance depuis la console SSH. Dans Local, faites un clic droit sur le site > Open Site Shell. Une fenêtre de terminal apparaît alors.

Utilisation de WP-CLI

On commence d’abord par la méthode wp-cli. On copie notre fichier adminer.sql sous /app/public et on lance la commande suivante:

wp db import ./adminer.sql

Résultat:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

Cela commence bien. La version 5 de Local utilise MySQL 8 donc certaines choses ne sont peut-être pas tout à fait au point. Comme il n’y a pas de socket mysql dans /tmp/mysql.sock, nous allons manuellement spécifier notre socket MySQL dans notre commande. Local nous donne l’adresse du socket dans l’onglet Database:

wp db import ./adminer.sql --socket="/Users/matt/Library/Application Support/Local/run/rvrb6Ce-Z/mysql/mysqld.sock"

Résultat:
ERROR 1067 (42000) at line 23841 in file: './adminer.sql': Invalid default value for 'comment_date'

La bonne nouvelle, c’est que l’on peut se connecter à la base de données MySQL. Mais tiens donc, nous sommes déjà tombés sur cette erreur Invalid default value for comment_date !

Configuration de MySQL

Pour régler le problème sous Local, la marche à suivre diffère un peu de ce que nous avions lancé sur notre serveur puisqu’il n’y a pas une mais deux variables de configuration de mysqld à modifier.

On se connecte au serveur mysql:

mysql -u root -proot

Commençons par voir ce que les variables sql_mode contiennent:

SELECT @@GLOBAL.sql_mode; SELECT @@SESSION.sql_mode; 

Résultat:

+------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                        |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

+------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                       |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+

Le problème est, comme la dernière fois, la présence de ces deux instructions: NO_ZERO_IN_DATE,NO_ZERO_DATE.

On enlève donc ces deux instructions de nos deux directives:

SET @@GLOBAL.sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";
SET @@SESSION.sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Voilà ce que nous obtenons au final:

+------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                        |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

+------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                       |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

On peut désormais importer notre fichier SQL:

mysql -u root -proot local < ./adminer.sql 

Hop l’import de la base de données se passe maintenant sans aucun problème.

Réinitialiser le mot de passe root de MySQL ou MariaDB sous Debian photo

Réinitialiser le mot de passe root de MySQL ou MariaDB sous Debian

Chez l’un de mes clients, nous avons eu besoin de réinitialiser le mot de passe MySQL de l’utilisateur root, qui a été oublié.

Je vous avais déjà décrit comment réinitialiser le mot de passe root d’un serveur MySQL ou MariaDB sous Ubuntu.

Comme le serveur tourne sous Debian, nous avons un moyen très simple d’avoir accès à la base mysql pour modifier le mot de passe root. Cela ne prend que quelques secondes.

L’utilisateur debian-maintenance à la rescousse

Sous les systèmes à base Debian, il existe par défaut un utilisateur nommé debian-sys-maint, qui se charge de routines de maintenance sur la base SQL et qui possède tous les droits d’administration sur toutes les bases de données.

Il se trouve que le mot de passe de l’utilisateur debian-sys-maint est visible, en clair dans ce fichier:

nano /etc/mysql/debian.cnf

Copiez le mot de passe. Ensuite, connectez-vous avec debian-sys-maint au serveur de base de données:

mysql -u debian-sys-maint -p

Vous êtes maintenant connecté au serveur de base de données, en tant qu’administrateur, sous l’utilisateur debian-sys-maint.

Tous les utilisateurs de la base de données sont stockés dans la base mysqldonc on commence par la sélectionner:

use mysql;

Et on peut maintenant changer le mot de passe de l’utilisateur root avec une simple mise à jour du mot de passe:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('^*p4!_BHLn6Q&xuft*^5tjyby7^_$)d7_fgf&zec8#ExV@xY');
flush privileges;

Il ne reste plus qu’à quitter MySQL monitor:

quit;

Voilà, le mot de passe de l’utilisateur rootest désormais changé. Vous pouvez vous identifier normalement avec le nouveau mot de passe que vous venez de définir plus haut:

mysql -u root -p
Enter password:

Une astuce toujours utile à garder sous le coude!

MySQL: résoudre l'erreur

MySQL: résoudre l’erreur “Incorrect datetime value” lors d’opérations sur les tables

mysql logo compressor 1280x662

Depuis le passage du site sur le nouveau serveur, ORION, j’utilise MySQL 8 en lieu et place de MariaDB, histoire de tester les les gains de performance.

Or, avec la nouvelle configuration de MySQL par défaut, vous pouvez obtenir cette erreur lors de simples opération de maintenance comme l’optimisation des tables:

example.wp_comments: Table does not support optimize, doing recreate + analyze instead
example.wp_comments: Invalid default value for 'comment_date'
example.wp_comments: Operation failed
example.wp_et_social_stats: Incorrect datetime value: '0000-00-00 00:00:00' for column 'comment_date' at row 1
example.wp_et_social_stats: Invalid default value for 'comment_date'
example.wp_et_social_stats: Table does not support optimize, doing recreate + analyze instead
example.wp_et_social_stats: Invalid default value for 'sharing_date'
example.wp_et_social_stats: Operation failed

Cela est dû à un changement de configuration, notamment dans la directive sql_mode depuis MySQL 5.7.

Voyons-donc ce que contient la directive par défaut. Identifiez-vous sur le serveur MySQL:

mysql -u root -p

Puis vérifiez le contenu de la variable de configuration sql_mode:

show variables like 'sql_mode';

Résultat:

+---------------+-----------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                 |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

Ce qui pose problème, ce sont ces deux directives: NO_ZERO_IN_DATE et NO_ZERO_DATE.

Deux solutions s’offrent à nous : éditer la valeur directement depuis la console mysql ou alors depuis le fichier de configuration my.cnf.

Méthode 1 : éditer la valeur de sql_mode depuis la console MySQL

Si vous vous trouvez toujours dans la console mysql, vous pouvez lancer la reqête suivante, qui enlève les drapeaux NO_ZERO_IN_DATE et NO_ZERO_DATE à notre directive sql_mode:

SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

Relancez ensuite le serveur:

service mysql restart

Méthode 2 : éditer la valeur de sql_mode depuis le fichier de configuration MySQL (my.cnf)

Nous allons donc éditer notre fichier de configuration MySQL:

nano /etc/mysql/mysql.conf.d/mysqld.cnf

Et ajouter (ou modifier) la variable de configuration sql_mode en l’amputant des valeurs NO_ZERO_IN_DATE et NO_ZERO_DATE:

sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

Enregistrez le fichier puis redémarrez le serveur mysql:

service mysql restart

Vous pouvez désormais lancer des requêtes de maintenance ou de modification de la structure des tables de la base de données sans problèmes.

Serveur dédié : installation de MariaDB 10.3 photo

MariaDB ne veut plus redémarrer : quelques solutions

MariaDB ne veut plus se lancer

Sur le serveur chinois que j’ai monté pour un de mes clients sur Codeable, le site a commencé à afficher des erreurs étranges : erreur 502 pour nginx sur certaines pages et des nombres étranges en lieu et place des données de la base de données.

Après un redémarrage des services PHP, nginx et mysql, je constate que MariaDB veut bien s’arrêter mais ne veut plus de lancer.

Voici ce que donne:

systemctl status mariadb.service

Résultat:

● mariadb.service - MariaDB database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2019-04-22 18:14:22 CST; 59s ago
  Process: 721 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 718 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
  Process: 12274 ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION (code=exited, status=1/FAILURE)
  Process: 12179 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`/usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited,
  Process: 12176 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 12173 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
 Main PID: 12274 (code=exited, status=1/FAILURE)
   Status: "MariaDB server is down"
systemd[1]: Starting MariaDB database server…
mysqld[12274]: 2019-04-22 18:14:19 140194687476288 [Note] /usr/sbin/mysqld (mysqld 10.1.26-MariaDB-0+deb9u1) starting as process 12274 …
systemd[1]: mariadb.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: Failed to start MariaDB database server.
systemd[1]: mariadb.service: Unit entered failed state.
systemd[1]: mariadb.service: Failed with result 'exit-code'.

Bon, chou blanc. Cela ne nous donne aucune information exploitable quand à l’erreur qui empêche le démarrage du service de base de données.

Solution: vérifier l’espace disponible sur le disque du serveur

On regarde ensuite ce que nous donnent les logs de MariaDB:

tail -f /var/log/mysql/error.log

Résultat:

2019-04-22 18:14:19 140194687476288 [Note] InnoDB: Completed initialization of buffer pool
2019-04-22 18:14:19 140194687476288 [Note] InnoDB: Highest supported file format is Barracuda.
2019-04-22 18:14:19 140194687476288 [Note] InnoDB: 128 rollback segment(s) are active.
2019-04-22 18:14:19 140194687476288 [Note] InnoDB: Waiting for purge to start
2019-04-22 18:14:19 140194687476288 [Note] InnoDB:  Percona XtraDB (http://www.percona.com) 5.6.36-82.1 started; log sequence number 11397472969
2019-04-22 18:14:19 140194687476288 [Note] Plugin 'FEEDBACK' is disabled.
2019-04-22 18:14:19 140194687476288 [ERROR] mysqld: Can't change size of file (Errcode: 28 "No space left on device")
2019-04-22 18:14:19 140194687476288 [ERROR] Can't init tc log
2019-04-22 18:14:19 140194687476288 [ERROR] Aborting

Là, c’est beaucoup plus intéressant. Visiblement, deux erreurs majeures sont à l’origine du non-démarrage du service:

  • il n’y a plus d’espace disponible sur le disque dur du serveur,
  • le fichier /var/lib/mysql/tc.log ne peut pas être initialisé.

Après un petit df, il s’avère que le client a installé un plugin de sauvegarde qui a littéralement saturé tout l’espace disponible.

Après un petit ménage, il ne reste plus qu’à gérer la seconde erreur, Can’t init tc log.

Le fichier /var/lib/mysql/tc.log peut parfois souffrir d’un problème de permission.

Dans le cas du client, on l’archive par précaution:

mv /var/lib/mysql/tc.log /var/lib/mysql/tc_bakup.log

Puis on relance le serveur MariaDB:

service mysql start

On vérifie le statut du service:

service mysql status

qui nous retourne:

service mysql status
● mariadb.service - MariaDB database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-04-22 18:17:22 CST; 1h 37min ago
  Process: 12467 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 12464 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
  Process: 12340 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`/usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited,
  Process: 12337 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 12334 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
 Main PID: 12437 (mysqld)
   Status: "Taking your SQL requests now..."
    Tasks: 29 (limit: 4915)
   CGroup: /system.slice/mariadb.service
           └─12437 /usr/sbin/mysqld

Apr 22 18:17:20 iZuf6aj6jz83uxa0jgbgcrZ systemd[1]: Starting MariaDB database server...
Apr 22 18:17:21 iZuf6aj6jz83uxa0jgbgcrZ mysqld[12437]: 2019-04-22 18:17:21 139940495544896 [Note] /usr/sbin/mysqld (mysqld 10.1.26-MariaDB-0+deb9u1) starting as process 12437 ...
Apr 22 18:17:22 iZuf6aj6jz83uxa0jgbgcrZ systemd[1]: Started MariaDB database server.

A noter que l’erreur 502 de nginx n’était pas due à une mauvaise configuration du server block mais bien d’un manque d’espace disque.

C’est important à vérifier, avant de se lancer dans la dissection du fichier de configuration d’nginx (qui n’aurait pas réglé le problème dans ce cas précis).

WordPress : nettoyer les tables wp_options et wp_postmeta photo

WordPress : nettoyer les tables wp_options et wp_postmeta

Nous allons aujourd’hui examiner deux tables importantes de votre base de données WordPress, wp_options et wp_postmeta.

C’est un domaine qui est souvent négligé en ce qui concerne les performances globales de WordPress et de la base de données.

Cela est très visible sur les sites les plus anciens et les plus gros et peut être la cause des temps de requête lents sur votre site en raison des données à chargement automatique laissées par les plugins et les thèmes tiers.

Voici quelques conseils pour vérifier, dépanner et nettoyer vos tables wp_options et wp_postmeta.

Que contient la table wp_options ?

La table wp_options contient toutes les données relatives aux options et paramètres de votre site WordPress telles que:

  • URL du site, URL de la page d’accueil, adresse électronique de l’administrateur, catégorie par défaut, publications par page, format d’heure, etc.
  • Paramètres pour les plugins, les thèmes, les widgets,
  • Données temporairement mises en cache.

La table wp_options contient plusieurs champs :

  • option_id
  • option_name
  • option_value
  • autoload

Le champ qui nous intéresse particulièrement est le champ autoload, qui contient un drapeau qui peut être soit “yes”, soit “no”. Cela contrôle essentiellement si la valeur est chargée ou non par la fonction wp_load_alloptions().

Les données à chargement automatique sont des données qui sont chargées sur chaque page de votre site WordPress. L’attribut autoload est défini sur «yes» par défaut pour les développeurs, mais tous les plugins ne doivent théoriquement pas charger leurs données sur chaque page.

Le problème que les sites WordPress peuvent rencontrer est celui où la table wp_options contient une grande quantité de données auto-chargées. Cependant, la table wp_options n’a pas non plus été conçue pour contenir des milliers de lignes.

Combien coûte trop de données autoloadées? Cela peut varier, bien sûr, mais idéalement, vous voulez que la taille de votre ordinateur soit comprise entre 300 Ko et 1 Mo.

Une fois que vous commencez à approcher la plage de 3 à 5 Mo ou plus, il existe très probablement des éléments pouvant être optimisés ou supprimés du chargement automatique.

Et tout ce qui dépasse 10 Mo doit être traité immédiatement. Cela ne signifie pas toujours que cela posera un problème, mais c’est un bon point de départ.

Vérifier la taille totale des données auto-chargées

On peut calculer la taille totale des données auto-chargées d’un site WordPress en effectuant la requête suivante sous MySQL:

SELECT SUM(LENGTH(option_value)) as autoload_size FROM wp_options WHERE autoload='yes';

La valeur d’autoload_size est exprimée en octets. Il y a 1024 octets dans un KB et 1024 KB dans un MB. Dans notre cas, 622 138 octets sont donc égaux à 0,62 MB. Donc pour ce site, c’est une bonne taille! Si vous restituez moins de 1 Mo, ne vous inquiétez pas. Cependant, si le résultat était beaucoup plus grand, passez à l’étape suivante.

Lire la suite

Désactiver les binary logs sous MySQL 8 photo

Désactiver les binary logs sous MySQL 8

mysql 8

J’ai récemment monté un nouveau serveur qui utilise MySQL 8 et après quelques jours d’utilisation, je me suis rendu compte que l’espace disque avait considérablement augmenté.

La cause ? Une multitude de fichiers logs binaires dans le répertoire d’exécution de MySQL 8 : il y en avait pour plus de 260 Go !

Les fichiers logs binaires enregistrent toutes les requêtes qui ont été effectuées par le serveur de bases de données. Inutile de dire qu’il est assez improbable que vous cherchiez à savoir quelles requêtes ont été lancées le mois dernier!

Désactivation des logs binaires

Sous MySQL 8, voici comment désactiver les logs binaires : éditez le fichier de configuration de MySQL:

nano /etc/mysql/mysql.conf.d/mysqld.cnf

et ajoutez cette ligne sous [mysqld] :

skip-log-bin

Vous pouvez également vous connecter au serveur MySQL en ligne de commande:

mysql -u root -p

et lancer la commande suivante dans l’invite de commande MySQL:

SET sql_log_bin = 0;
PURGE BINARY LOGS BEFORE '2019-03-31';

Relancez ensuite le serveur MySQL:

service mysql restart

Il ne vous reste plus qu’à vous rendre dans le dossier d’exécution de MySQL – /etc/mysql par défaut, sauf si vous l’avez modifié – et supprimer les fichiers binlog*.

MySQL : résoudre le message

MySQL : résoudre “Warning: Using a password on the command line interface can be insecure.”

J’ai récemment écrit un petit script bash qui me permet de sauvegarder rapidement toutes les bases de données d’un serveur. Le script est lancé par une tâche cron automatiquement, tous les jours.

Si l’on passe l’utilisateur et le mot de passe SQL dans la requête, avec mysql ou mysqldump, vous obtiendrez très certainement le message d’avertissement suivant:

Warning: Using a password on the command line interface can be insecure.

Et pour cause : cela veut dire que n’importe qui ayant accès au serveur pourra voir, dans les logs ou avec un simple ps, vos informations de connexion à vos bases de données. Ce n’est pas ce qui se fait de mieux en matière de sécurité !

Une solution est de passer en argument un fichier qui contiendra vos données de connexion à la base de données.

Donc, au lieu d’écrire :

mysqldump -u $USER -p$PASSWORD --databases $db > $BACKUP_PATH/$date-$db.sql

Il vaut mieux écrire:

mysqldump --defaults-extra-file=/etc/mysql/mysql-backup-script.cnf --databases $db > $BACKUP_PATH/$date-$db.sql

Note: L’argument --defaults-extra-file doit venir en premier, sinon il ne sera pas interprété.

Le fichier /etc/mysql/mysql-backup-script.cnf contient les identifiants de votre utilisateur SQL qui aura les droits sur chacune des bases de données à sauvegarder. Voici à quoi il ressemble:

[client]
user = 'backup'
password = 'GIGANTIC_SECURE_PASSWORD'

Par sécurité, on restreint les droits d’accès au fichier pour qu’il ne soit pas lisible par tout le monde:

chmod 400 /etc/mysql/mysql-backup-script.cnf

Il ne vous reste qu’à créer votre cron avec votre nouvelle commande, sans montrer les identifiants SQL en clair.

Installer Redis pour accélérer WordPress sous Debian photo

Installer Redis pour accélérer WordPress sous Debian

Aujourd’hui, nous installons le serveur Redis pour accélérer les temps de chargement de tous les sites présents sur le serveur.

Redis (de l’anglais REmote DIctionary Server qui peut être traduit par « serveur de dictionnaire distant » et jeu de mot avec Redistribute1) est un système de gestion de base de données clef-valeur scalable, très hautes performances, écrit en C ANSI.

Il fait partie de la mouvance NoSQL et vise à fournir les performances les plus élevées possibles.

Redis permet de manipuler des types de données simples : chaînes de caractères, tableaux associatifs, listes, ensembles et ensembles ordonnés.

Une des principales caractéristiques de Redis est de conserver l’intégralité des données en RAM. Cela permet d’obtenir d’excellentes performances en évitant les accès disques, particulièrement coûteux sur ce plan.

Lorsqu’une page WordPress est chargée par exemple, des requêtes sur la base de données sont lancées et cela prend un certain temps pour récupérer ces informations.

Lorsque Redis est activé, il garde ces requêtes SQL en mémoire, ce qui permet de gagner en temps de chargement des pages.

Voici donc le tutoriel pour mettre en place Redis sur votre serveur. Cela prend environ 15 minutes.

Installation du serveur Redis

Nous installons le serveur Redis et le paquet PHP associé:

apt install redis-server php-redis

Nous vérifions que Redis est bien actif, il nous suffit de lancer redis-cli:

redis-cli

On tape ping dans l’invite:

127.0.0.1:6379> ping

Réponse:

PONG

Parfait, le serveur Redis est bien installé et actif.

Configuration de Redis

Editons le fichier de configuration de Redis :

nano /etc/redis/redis.conf

Changez les valeurs suivantes :

maxmemory 256mb # max memory 
maxmemory-policy allkeys-lru # replace old keys with fresher ones
requirepass VOTRE-MOT-DE-PASSE

Enregistrez et relancez le serveur pour prendre en charge la nouvelle configuration:

service redis-server restart

Lire la suite

Serveur dédié : réinitialiser le mot de passe root d'un serveur MySQL ou MariaDB photo

Serveur dédié : réinitialiser le mot de passe root d’un serveur MySQL ou MariaDB

Pour les besoins d’un de mes clients préférés, j’ai eu la grande joie de paramétrer un VPS aux petits oignons avec réplication des données à la volée.

C’est un projet fascinant que j’ai déjà abordé dans la série réplication de données.

Serveur dédié : réinitialiser le mot de passe root d'un serveur MySQL ou MariaDB photo

Au moment de la réalisation des bases de données, je demande à mon client le mot de passe root du serveur de base de données pour y créer de nouveaux utilisateurs. La réponse ne se fait pas attendre : “je n’ai pas ce mot de passe mais j’ai confiance en toi Matt, tu pourras aisément contourner le problème!”.

Challenge accepted.

Voici donc un mini-tutoriel pour réinitialiser le mot de passe root quand vous ne l’avez jamais eu vous en souvenez plus.

Vous aurez besoin de deux fenêtres de terminal, que je nomme ici terminal1 et terminal2.

Etape 1 : lancer mysqld_safe

Voici le principe de la manipulation : nous allons “occuper” le serveur MySQL ou MariaDB en lançant le daemon mysqld_safe dans un terminal et nous allons lancer un second terminal qui nous permettre de réinitialiser le mot de passe root.

C’est parti : dans le terminal1, nous commençons par arrêter le serveur SQL:

service mysql stop

puis lançons mysqld_safe :

mysqld_safe --skip-grant-tables --skip-syslog --skip-networking

Le terminal semble arrêté ou attendre quelque chose : c’est bon signe, laissez-le comme ça pour le moment.

Lire la suite

Serveur dédié : migration de MySQL vers MariaDB photo

Serveur dédié : migration de MySQL vers MariaDB

Aujourd’hui, on aborde la migration du serveur de base de données : nous passons de l’historique MySQL à son fork libre MariaDB.

Les raisons de remplacer Oracle MySQL avec MariaDB sont nombreuses.

MySQL vs MariaDB

Tout d’abord, MariaDB assure la compatibilité et la continuité de service avec MySQL. Les librairies sont exactement équivalentes et permettent d’utiliser les APIs et commandes de MySQL.

Les performances de MariaDB sont souvent meilleures que celles de MySQL, notamment grâce à l’amélioration de l’optimiseur de requêtes et l’intégration du moteur XtraDB de Percona, qui vise à remplacer InnoDB.

Un nouveau moteur de stockage, Aria, a été écrit pour devenir un moteur à la fois transactionnel et non-transactionnel pour remplacer MyISAM. Il pourrait même être inclus dans de prochaines versions de MySQL.

Dans un autre registre, Oracle semble ne pas vouloir garder le modèle libre de MySQL : pas mal de choses (rapports de bugs, scénarios de test) sont maintenant disponibles uniquement pour les grands comptes payants.

Michael “Monty” Widenius, le fondateur de MySQL AB, a quitté Sun Microsystems lors de son rachat par Oracle pour créer Monty Program AB puis la Fondation MariaDB. Il est rapidement rejoint par de nombreux développeurs originaux de MySQL.

Ces développeurs maîtrisent donc parfaitement le code source du système de gestion de base de données, cela promet encore de nombreuses nouveautés et optimisations pour les versions suivantes.

Installation de MariaDB

Avant toute chose, faîtes une sauvegarde de vos bases de données. On ne sait jamais.

Notre serveur dédié tourne toujours sur Debian stable et les paquets de MariaDB sont disponibles dans les dépôts officiels.

mariadb-seal-logo

MariaDB est un “drop-in replacement” pour MySQL, c’est -à-dire qu’il suffit de désinstaller MySQL et d’installer MariaDB : rien ne change, pas de pertes de données, pas de lignes de code à changer, tout est compatible.

L’installation est donc très simple :

apt-get install mariadb-server

Résultat:

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  mariadb-client-10.0 mariadb-client-core-10.0 mariadb-common
  mariadb-server-10.0 mariadb-server-core-10.0
Suggested packages:
  mariadb-test tinyca
The following packages will be REMOVED:
  mysql-client-5.6 mysql-client-core-5.6 mysql-server mysql-server-5.6
  mysql-server-core-5.6
The following NEW packages will be installed:
  mariadb-client-10.0 mariadb-client-core-10.0 mariadb-common mariadb-server
  mariadb-server-10.0 mariadb-server-core-10.0
0 upgraded, 6 newly installed, 5 to remove and 0 not upgraded.
Need to get 11.8 MB of archives.
After this operation, 18.4 MB disk space will be freed.

L’installation vous demandera de donner un mot de passe pour l’utilisateur root. De manière à assurer la continuité avec MySQL, j’ai redonné le même mot de passe que pour mon utilisateur root sous MySQL.

Lire la suite