NAS Synology : mapper un répertoire du NAS sur un répertoire local sous Ubuntu photo 2

NAS Synology : mapper un répertoire du NAS sur un répertoire local sous Ubuntu

A la maison, je galère un peu avec les taux de transfert des fichiers entre ma machine fixe (The Reaper) et le NAS Synology.

Lors des transferts via le navigateur, la vitesse arrive à peu près à 2MB/s, ce qui, excusez-moi du peu, sonne comme une douce plaisanterie.

Pour pallier ce problème, nous allons donc “mapper” un des répertoires du NAS directement dans un répertoire local de ma machine.

Comme cette dernière tourne sous Ubuntu, il suffira dans Nautilus de copier des fichiers ou dossiers dans ce répertoire pour que tout soit uploadé directement dans le NAS. Un gain de temps en perspective !

Activation de NFS sur le NAS

Sur le NAS, nous allons avoir besoin du protocole NFS (Network File System).

Rendez vous dans Control Panel > File Sharing > File Services > cochez la case pour activer le service NFS et appliquez les changements:

NAS Synology : mapper un répertoire du NAS sur un répertoire local sous Ubuntu photo

Ensuite, cliquez sur l’icône qui se trouve juste au dessus, Shared folders :

  1. créez un nouveau dossier partagé. Je vais prendre NetBackup comme exemple pour ce tutoriel.
  2. sélectionnez le dossier > cliquez sur Edit > sélectionnez l’onglet NFS permissions.
  3. cliquez sur Create pour ajouter une nouvelle politique de droits NFS sur ce dossier.

Voici les droits à accorder:

NAS Synology : mapper un répertoire du NAS sur un répertoire local sous Ubuntu photo 1

Configuration :

Hostname/IP : on indique l’IP de la machine locale. Sur mon réseau local, 192.168.0.10 est l’adresse de ma machine fixe.

Privileges: Read/Write pour lecture et écriture.

Squash : Map root to admin. Cela permet de monter automatiquement le répertoire au démarrage de la machine.

Je laisse coché toutes les autres options, les transferts asynchrones ne me dérangent pas.

Lire la suite

Serveur dédié : mise à jour du kernel OVH pour combler les failles Spectre et Meltdown photo

Serveur dédié : mise à jour du kernel OVH pour combler les failles Spectre et Meltdown

Au début du mois de février, l’université de Graz et Google Project Zero ont annoncé avoir découvert deux failles de sécurité importantes s’appuyant sur les mécanismes de fonctionnement interne des processeurs.

Trois vulnérabilités permettant d’accéder à de la mémoire privilégiée ont été publiées, qui ont pour point commun d’exploiter les mécanismes d’exécution spéculative et les timings des caches mémoires.

Meltdown

La première faille, Meltdown (CVE-2017-5754), permet de bypasser les mécanismes d’isolation mémoire entre mémoire classique (utilisée par les applications) et mémoire kernel (utilisée par le noyau du système d’exploitation, et protégée normalement par des mécanismes hardware dans le CPU).

Meltdown est une attaque side channel permanent;qui s’attaque à une faille de certains processeurs OOO (Out Of Order, la plupart des processeurs performants modernes depuis le Pentium Pro) qui, dans leur mécanismes d’exécution spéculatifs, peuvent non seulement lire des données mémoires protégées mais aussi exécuter des instructions sur ces données mémoires.

Concrètement, avec Meltdown, il est possible de lire tout type de mémoire à partir d’un process malicieux, y compris côté serveur de bypasser toutes les protections de type VM/Hyperviseur/Docker. Meltdown touche spécifiquement les architectures d’Intel et ARM.

Spectre

En parallèle à Meltdown, une autre faille a été dévoilée baptisée Spectre. permanent;Pour Spectre, la situation est plus compliquée. Il s’agit toujours d’une variation sur le même thème, à savoir tenter d’exploiter les mécanismes d’exécution spéculative des processeurs. T

ous les processeurs modernes sont concernés a différents niveau et l’on retrouve, y compris chez un même constructeur, des différences d’une architecture à l’autre en fonction des mécanismes précis de fonctionnement de chaque génération.

Le papier décrit deux attaques distinctes. La première, connue sous le nom de CVE-2017-5753 (bounds check bypass) permet à un processus d’accéder, dans certains conditions un peu plus complexes, à la mémoire d’un autre processus.

Contrairement à Meltdown dont l’exploitation est triviale, il faut ici connaître les spécificités du programme que l’on attaque pour réussir à l’exploiter.

Le groupe Google Project Zero a montré que cette attaque était exploitable aussi bien sur les CPU Intel, AMD (FX et APU), et ARM (un Cortex A57 à été testé). Si tous les processeurs sont exploitables, c’est que tous les modèles OOO modernes reposent, dans les grandes lignes, sur l’algorithme de Tomasulo, du nom de l’ingénieur qui l’a développé en 1967 chez IBM.

Virtuellement, tous les systèmes (du serveur au smartphone) sont vulnérables à cette attaque pour laquelle des PoC existent même en Javascript (pour bypasser les barrières des VM qui isolent le code Javascript de vos différents onglets), ce qui la rend assez grave.

Des méthodes de mitigations, aussi bien au niveau des compilateurs, des navigateurs, et des systèmes d’exploitations sont en cours de développement et des patchs sont attendus rapidement pour limiter le problème.

Vous pouvez retrouver les détails techniques des failles Spectre et Meltdown chez OVH.

Mon machine est-elle touchée par ces failles?

Il vous suffit de tester votre processeur avec le script Spectre & Meltdown Checker:

curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
chmod +x spectre-meltdown-checker.sh
sh ./spectre-meltdown-checker.shCode language: JavaScript (javascript)

Résultat avant la mise à jour du kernel:

CVE-2017-5753 [bounds check bypass] aka 'Spectre Variant 1'
* Checking count of LFENCE opcodes in kernel:  NO 
> STATUS:  VULNERABLE  (only 46 opcodes found, should be >= 70, heuristic to be improved when official patches become available)

CVE-2017-5715 [branch target injection] aka 'Spectre Variant 2'
* Mitigation 1
*   Hardware (CPU microcode) support for mitigation:  NO 
*   Kernel support for IBRS:  NO 
*   IBRS enabled for Kernel space:  NO 
*   IBRS enabled for User space:  NO 
* Mitigation 2
*   Kernel compiled with retpoline option:  NO 
*   Kernel compiled with a retpoline-aware compiler:  NO 
> STATUS:  VULNERABLE  (IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability)

CVE-2017-5754 [rogue data cache load] aka 'Meltdown' aka 'Variant 3'
* Kernel supports Page Table Isolation (PTI):  NO 
* PTI enabled and active:  NO 
> STATUS:  VULNERABLE  (PTI is needed to mitigate the vulnerability)Code language: JavaScript (javascript)

Mise à jour du kernel OVH

Sur la Kimsufi, c’est le kernel OVH 4.9.87 qui intégre tous les correctifs Meltdown et Spectre, ainsi que la mise à jour du microcode pour les puces Intel.

Il suffit de suivre le tutoriel pour mettre à jour le noyau OVH.

Après mise à jour du noyau et redémarrage du serveur, les failles semblent maintenant comblées:

CVE-2017-5753 [bounds check bypass] aka 'Spectre Variant 1'
* Checking whether we're safe according to the /sys interface:  YES  (kernel confirms that the mitigation is active)
> STATUS:  NOT VULNERABLE  (Mitigation: __user pointer sanitization)

CVE-2017-5715 [branch target injection] aka 'Spectre Variant 2'
* Checking whether we're safe according to the /sys interface:  YES  (kernel confirms that the mitigation is active)
> STATUS:  NOT VULNERABLE  (Mitigation: Full generic retpoline)

CVE-2017-5754 [rogue data cache load] aka 'Meltdown' aka 'Variant 3'
* Checking whether we're safe according to the /sys interface:  YES  (kernel confirms that the mitigation is active)
> STATUS:  NOT VULNERABLE  (Mitigation: PTI)

Voilà, mettez vos noyaux à jour, c’est important.

Backup Manager : résoudre l'erreur "tar: file changed as we read it" lors de la création de la sauvegarde photo

Backup Manager : résoudre l’erreur “tar: file changed as we read it” lors de la création de la sauvegarde

Cela fait quelques jours que Backup Manager, qui me sert à sauvegarder automatiquement les fichiers et bases de données du site sur le serveur de sauvegarde, renvoie une erreur lors de la création d’un de mes fichiers de sauvegarde, alors que tout se passait sans encombres jusqu’alors.

C’est gênant dans le sens où on ne sait pas vraiment ce qui a empêché la bonne création du fichier et on ne peut vraiment être certain de l’intégrité du fichier de sauvegarde, ce qui est critique.

Voici le message d’erreur reçu par email à la fin de la sauvegarde :

Unable to create "/home/archives/mail.skyminds.net-home.20180208.master.tar.gz", check /tmp/bm-tarball.log.TZ2VAU
1 error occurred during the tarball generation.Code language: JavaScript (javascript)

Et voici le contenu du fichier log en question :

tar: /wp-content/ file changed as we read itCode language: JavaScript (javascript)

Étapes du débogage

Le moins que l’on puisse dire, c’est que tar ne nous donne pas vraiment d’indications sur la cause du problème. Un fichier qui change lors de la lecture, d’accord mais lequel ? De plus, il indique un répertoire et non un fichier précis.

Dans le fichier de configuration de Backup Manager, il est possible de choisir plusieurs formats de fichier pour compresser les fichiers de sauvegarde. J’utilise .tar.gz puisque tous mes machines tournent sous Unix mais là, j’ai changé la configuration pour utiliser le format zip.

On relance le script de sauvegarde : zip est beaucoup plus loquace dans ses messages d’erreur !

Voici ce qu’il nous indique :

zip warning: Not all files were readable
  files/entries read:  55621 (1.3G bytes)  skipped:  96 (414K bytes)

Très bien. Il ne nous reste plus qu’à trouver quels sont ces fichiers qui n’ont pas les droits de lecture.

A la racine du site, on lance donc une recherche pour trouver tous les fichiers et dossiers qui n’auraient pas les droits basiques de lecture (read) :

find . ! -perm -o=r

Résultat :

./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---internal-metadatas---B0089KSLUY
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---internal-metadatas---CustomerReviews_B004LS7G3G
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---CustomerReviews_B00B2OI0FU
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---B00JGYYQ24
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---CustomerReviews_B006H4R9LG
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---internal-metadatas---B005BHE48Q
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---internal-metadatas---B00H2O1YOI
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---CustomerReviews_B00MVQLMPI
./wp-content/plugins/amazonsimpleadmin/cache/zend_cache---B017EOYW9Y

Il s’agit donc de fichiers de cache de produits Amazon, qui sont absolument inutiles pour les sauvegardes: nous allons donc exclure ce répertoire de cache de nos fichiers de backup.

Suppression des répertoires de cache avant compression des archives

Dans la configuration de Backup Manager, ajoutez le chemin des répertoires de cache de quasiment tous les plugins WordPress :

export BM_TARBALL_BLACKLIST="/home/public_html/wp-content/plugins/*/cache/* /home/public_html/wp-content/*cache*"Code language: JavaScript (javascript)

Sauvegardez le fichier et relancez votre script de backup.

Méthode plus radicale : éditer le script

Si la méthode précédente ne porte pas ses fruits, en voici une autre. Il suffit de modifier la valeur du chmod dans ces deux fichiers :

/wp-content/plugins/amazonsimpleadmin/lib/AsaZend/Cache/Backend/File.php
/wp-content/plugins/amazonsimpleadmin/lib/AsaZend/Cache/Backend/Static.phpCode language: PHP (php)

Cherchez le chmod 600 :

'cache_file_umask' => 0600,Code language: PHP (php)

et remplacez-le par un chmod 644:

'cache_file_umask' => 0644,Code language: PHP (php)

Tada, plus d’erreur et des fichiers de sauvegarde propres, sans fichiers de cache inutiles !

Je suis assez content d’avoir trouvé une solution à ce problème assez récurrent.

Le fait d’avoir momentanément modifié le type d’archive à créer a bien aidé à isoler la cause du problème.

Serveur dédié : transférer et héberger un nouveau domaine sur votre serveur photo

Serveur dédié : transférer et héberger un nouveau domaine sur votre serveur

Aujourd’hui, nous allons voir comment héberger un nouveau domaine sur le serveur, en simplifiant au maximum les procédures.

Serveur dédié : transférer et héberger un nouveau domaine sur votre serveur photo

Le nom de domaine sera réservé chez OVH et le site hébergé sur notre serveur Debian. Nous allons servir le site avec NginX en HTTPS grâce à un certificat SSL fourni gratuitement par Let’s Encrypt.

Enfin, on utilisera le serveur email existant et on ajoutera la configuration OpenDKIM pour signer et authentifier tous les emails sortants du domaine.

Nom de domaine

J’achète mes noms de domaine chez OVH parce que le prix est relativement raisonnable (comparé à mon ancien registrar).

Au moment de la commande, faites pointer le nouveau domaine vers les DNS du serveur.

Si votre serveur n’est pas chez OVH, il suffit d’aller dans Domaines > Serveurs DNS et de renseigner le DNS primaire et secondaire de votre serveur.

Configuration DNS dans BIND

Une fois le domaine commandé, si vous vous rendez dans le Manager OVH, vous vous rendrez compte que le bouton DNS est en rouge : c’est normal puisqu’il nous faut paramétrer notre nouveau domaine dans BIND, notre serveur de noms.

On édite la configuration de BIND :

nano /etc/bind/named.conf.local

et on lui indique que nous créons une nouvelle zone :

zone "example.com" {
        type master;
        file "/etc/bind/example.com.hosts";
        allow-query { any; };
};Code language: JavaScript (javascript)

On crée maintenant notre fichier de zone:

nano /etc/bind/example.com.hosts
$ttl 84600
$ORIGIN example.com.

@       IN      SOA     XXXXXX.kimsufi.com. root.example.net. (
                        2018012801
                        14400
                        3600
                        604800
                        84600 )

; NAMESERVERS
 IN     NS      XXXXXX.kimsufi.com.
 IN     NS      ns.kimsufi.com.

example.com.   IN      A       XXX.XXX.XXX.XXX
example.com.   IN      AAAA    4001:41d0:1:4462::1
example.com.   IN      MX      10 mail.example.net.

www.example.com.       IN      A        XXX.XXX.XXX.XXX
www.example.com.       IN    AAAA    4001:41d0:1:4462::1
www       IN A          XXX.XXX.XXX.XXXCode language: PHP (php)

Ps: example.net est le domaine principal du serveur.

Pous vérifions la configuration BIND:

named-checkconf -z

et nous redémarrons BIND pour prendre en compte nos changements et activer notre nouveau fichier de zone:

service bind9 restart

Vous pouvez vérifier votre configuration DNS à l’aide de l’outil ZoneMaster.

Configuration du bloc serveur sous NginX

On commence par créer le répertoire qui va accueillir les fichiers du site et on lui attribue les bons droits:

mkdir -p /home/example/public_html
chown -R www-data:www-data /home/example/public_html
chmod 755 /home/example/public_html

On crée également un fichier index.php à la racine du site pour éviter une erreur 403 plus tard lors de la génération du certificat SSL :

echo "<!--?php echo 'hello world. Domain activated.'; ?-->" >> /home/example/public_html/index.phpCode language: HTML, XML (xml)

On crée maintenant le répertoire de cache du site, toujours avec les bons droits:

mkdir -p /home/nginx-cache/example
chown -R www-data:www-data /home/nginx-cache/example
chmod 755 /home/nginx-cache/example

Voici le server block de départ, en HTTP simple :

server {
       listen         80;
       listen    [::]:80;
       server_name    example.com www.example.com;
       #return         301 https://$server_name$request_uri;
        root /home/example/public_html;
        index index.php index.html;
}Code language: PHP (php)

On active le site :

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

On teste la configuration de NginX et on redémarre le service:

nginx -t
service nginx restart

On crée maintenant le certificat SSL avec Let’s Encrypt :

certbot certonly --webroot -w /home/example/public_html -d example.com -d www.example.com

Lire la suite

Serveur dédié : résoudre l'erreur "tail: inotify cannot be used, reverting to polling: Too many open files" photo

Serveur dédié : résoudre l’erreur “tail: inotify cannot be used, reverting to polling: Too many open files”

Ce matin, je me suis aperçu que le serveur était un peu moins réactif que d’habitude.

Ni une, ni deux, je lance le terminal et commence par vérifier les fichiers log. Un message attire alors mon attention :

tail: inotify cannot be used, reverting to polling: Too many open files Code language: HTTP (http)

C’est bien étrange puisque très peu de services sont censés lancer des tail. Nous allons donc lancer quelques commandes pour savoir qui est responsable de cet état.

Hotfix : à la recherche des anon_inode:inotify

1. Première méthode pour avoir un aperçu de tout ce qui tourne en ce moment sur le serveur :

ps -ef

La liste est très exhaustive (plusieurs pages chez moi) et ne permet pas vraiment de voir ce qui se passe, étant donné que rien n’est trié.

2. Changeons notre fusil d’épaule et trouvons la liste des processus qui font appel à inotify:

for foo in /proc/*/fd/*; do readlink -f $foo; done | grep inotify | sort | uniq -c | sort -nr

Résultat:

      8 /proc/25634/fd/anon_inode:inotify
      1 /proc/715/fd/anon_inode:inotify
      1 /proc/6146/fd/anon_inode:inotify
      1 /proc/330/fd/anon_inode:inotify
      1 /proc/32148/fd/anon_inode:inotify
      1 /proc/31695/fd/anon_inode:inotify
      1 /proc/31262/fd/anon_inode:inotify
      1 /proc/3067/fd/anon_inode:inotify
      1 /proc/3066/fd/anon_inode:inotify
      1 /proc/3065/fd/anon_inode:inotify
      1 /proc/3064/fd/anon_inode:inotify
      1 /proc/3063/fd/anon_inode:inotify
      1 /proc/3062/fd/anon_inode:inotify
      1 /proc/21853/fd/anon_inode:inotify
      1 /proc/2063/fd/anon_inode:inotify
      1 /proc/1924/fd/anon_inode:inotify
      1 /proc/1563/fd/anon_inode:inotify
      1 /proc/1196/fd/anon_inode:inotify

3. Maintenant, nous allons chercher dans cette liste de processus les commandes qui font appel à anon_inode:inotify :

ps -p $(find /proc/*/fd/* -type l -lname 'anon_inode:inotify' -print 2> /dev/null | sed -e 's/^\/proc\/\([0-9]*\)\/.*/\1/')Code language: JavaScript (javascript)

Résultat:

  PID TTY      STAT   TIME COMMAND
  330 ?        Ss     0:00 /lib/systemd/systemd-udevd --daemon
  715 ?        S      0:00 tail -f /tmp/bm-tarball.log.7lZV2O
 1196 ?        S      0:00 tail -f /tmp/bm-tarball.log.B1I64h
 1563 ?        S      0:00 tail -f /tmp/bm-tarball.log.hhDVas
 1924 ?        S      0:00 tail -f /tmp/bm-tarball.log.Ztuk8T
 2063 ?        Ss     0:06 /usr/bin/dbus-daemon --system
 3062 tty1     Ss+    0:00 /sbin/getty 38400 tty1
 3063 tty2     Ss+    0:00 /sbin/getty 38400 tty2
 3064 tty3     Ss+    0:00 /sbin/getty 38400 tty3
 3065 tty4     Ss+    0:00 /sbin/getty 38400 tty4
 3066 tty5     Ss+    0:00 /sbin/getty 38400 tty5
 3067 tty6     Ss+    0:00 /sbin/getty 38400 tty6
 6146 ?        Ss     0:00 gpg-agent --homedir /root/.gnupg --use-standard-socket --daemon
25634 ?        Sl     0:21 /usr/bin/python3 /usr/bin/fail2ban-server -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid -
31262 ?        S      0:00 tail -f /tmp/bm-tarball.log.82bIqR
31695 ?        S      0:00 tail -f /tmp/bm-tarball.log.6Hqw69
32148 ?        S      0:00 tail -f /tmp/bm-tarball.log.UMpkfiCode language: JavaScript (javascript)

Ah on y arrive, c’est déjà beaucoup plus clair. Le service qui pose problème est donc backup-manager (voir le tutoriel Serveur dédié : sauvegarde automatique des fichiers avec Backup Manager sur le serveur de sauvegarde), qui semble laisser ouvert tous ses fichiers de logs !

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

WordPress : changer le mot de passe d'un utilisateur depuis le serveur SQL photo

WordPress : changer le mot de passe d’un utilisateur depuis le serveur SQL

Il peut être nécessaire de changer le mot de passe d’un utilisateur WordPress par exemple lorsque l’on migre un compte, lorsque l’on repart de zéro avec une base de données vierge ou lorsque le mot de passe du site de développement diffère de celui du site de production.

Ou tout simplement pour en mettre un plus facile à retenir.

Voici donc comment changer le mot de passe d’un utilisateur WordPress directement depuis un terminal connecté sur le serveur de la base de données.

Changer le mot de passe d’un utilisateur WordPress depuis MariaDB

1. Connectez-vous au serveur de base de données :

mysql -u root -p

puis entrez votre mot de passe :

Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.Code language: JavaScript (javascript)

2. Sélectionnez la base de données qui contient l’installation WordPress concernée :

USE wordpress_wpdb;Code language: PHP (php)

Résultat :

Database changed

3. Vérifiez que votre utilisateur (ici : matt) est bien présent dans la base :

SELECT ID, user_login, user_pass FROM wp_users WHERE user_login LIKE '%matt%';Code language: JavaScript (javascript)

Résultat:

+----+-------------+------------------------------------+
| ID | user_login  | user_pass                          |
+----+-------------+------------------------------------+
| 78 | matt                | $P$BUZ6Uvu8aie2tBEWqwTu07qfzlKXc80 |
+----+-------------+------------------------------------+
1 row in set (0.00 sec)Code language: PHP (php)

4. Choisissez un mot de passe (ici: q8U@jM5uNMa*R66R), qui sera automatiquement chiffré en MD5 :

UPDATE wp_users SET user_pass = MD5('q8U@jM5uNMa*R66R') WHERE ID=78 LIMIT 1;Code language: JavaScript (javascript)

Résultat:

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0Code language: CSS (css)

Lire la suite

Créer un serveur High Availability : la réplication des bases de données photo

MariaDB : résoudre l’erreur 1062 (duplicate entry for key PRIMARY) lors de la réplication des bases de données

Si vous utilisez les fonctions de réplication de MySQL ou MariaDB, il peut arriver que votre slave bloque sur une instruction qui devrait avoir un identifiant unique mais que le serveur tente d’insérer deux fois.

Et quand c’est le cas, la réplication des données prend fin donc c’est un problème à corriger rapidement si vous voulez que votre système haute disponibilité perdure et soit vraiment efficace en cas de coup dur.

Identification du problème

Je me suis rendu compte du problème lorsque j’ai ajouté de nouvelles bases à répliquer : j’ai relancé la procédure d’installation, relancé les serveurs, ajouté les nouvelles positions, démarré les slaves.

On regarde le status du slave :

MariaDB [(none)]> SHOW SLAVE STATUS\GCode language: CSS (css)

Résultat :

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.134.23.164
                  Master_User: replicator
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mariadb-bin.000210
          Read_Master_Log_Pos: 2753885
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 103794
        Relay_Master_Log_File: mariadb-bin.000210
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1062
                   Last_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1563407
              Relay_Log_Space: 1296874
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1062
               Last_SQL_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
               Master_SSL_Crl:
           Master_SSL_Crlpath:
                   Using_Gtid: No
                  Gtid_IO_Pos:
      Replicate_Do_Domain_Ids:
  Replicate_Ignore_Domain_Ids:
                Parallel_Mode: conservative
1 row in set (0.00 sec)Code language: JavaScript (javascript)

Comme on peut le constater, plusieurs choses ne tournent pas rond et empêchent la synchronisation des données entre nos deux serveurs :

Slave_SQL_Running: No
Last_SQL_Errno: 1062
Last_SQL_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'Code language: JavaScript (javascript)

Solution : un RESET sur le slave

En me documentant sur le problème, j’ai lu pas mal de choses sur le net. Certains préfèrent cacher l’erreur, au risque de perdre des données. D’autres préfèrent tout effacer pour recommencer la réplication.

Aucune de ces “solutions” ne me conviennent donc nous allons procéder autrement. Comme l’erreur n’apparaît que sur le serveur BACKUP et non sur le serveur principal, c’est sur lui que nous travaillerons.

Sur le serveur BACKUP, dans MariaDB, on arrête notre slave :

MariaDB [(none)]> STOP SLAVE;
Query OK, 0 rows affected (0.01 sec)Code language: CSS (css)

On flush les privilèges et donc les utilisateurs connectés :

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)Code language: CSS (css)

On efface les fichiers logs de notre slave. C’est comme effacer une ardoise pour repartir sur des bases saines. Cela ne supprime aucune donnée – cf le manuel sur RESET :

MariaDB [(none)]> RESET SLAVE;
Query OK, 0 rows affected (0.00 sec)Code language: CSS (css)

Et on redémarre notre slave :

MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)Code language: CSS (css)

On vérifie de nouveau le status de notre slave :

MariaDB [(none)]> SHOW SLAVE STATUS\GCode language: CSS (css)

Résultat :

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.134.23.164
                  Master_User: replicator
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mariadb-bin.000196
          Read_Master_Log_Pos: 77900062
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 6318821
        Relay_Master_Log_File: mariadb-bin.000192
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 6318531
              Relay_Log_Space: 344030331
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 833890
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
               Master_SSL_Crl:
           Master_SSL_Crlpath:
                   Using_Gtid: No
                  Gtid_IO_Pos:
      Replicate_Do_Domain_Ids:
  Replicate_Ignore_Domain_Ids:
                Parallel_Mode: conservative
1 row in set (0.00 sec)Code language: CSS (css)

Nous avons bien :

Slave_IO_Running: Yes
Slave_SQL_Running: YesCode language: HTTP (http)

Et voilà, plus d’erreur et une réplication active dans les deux sens.

Linux : résoudre l'erreur "Cannot set LC_ALL to default locale" photo

Linux : résoudre l’erreur “Cannot set LC_ALL to default locale”

Récemment, j’ai installé un serveur en Chine, derrière le Great Firewall of China (GFW) pour un des mes clients.

Le code n’a pas de frontières mais la langue peut parfois poser problème – même pour un système d’exploitation, au niveau de la locale.

Les locales sont un ensemble de paramètres qui définissent la langue de l’utilisateur, sa région et les préférences régionales que l’utilisateur souhaire voir dans son interface.

Typiquement, une locale est identifiée par un code langue suivi d’un identifiant de région. Nous avons par exemple “en_US.UTF-8” pour l’anglais américain (en pour l’anglais, US pour les USA) ou “fr_FR.UTF-8” pour le français de France.

Dans le cas de mon serveur chinois, qui tourne sous Debian, les paramètres de la locale n’étaient pas uniformément remplis avec le même code langue et certains paramètres étaient manquants.

On obtenait donc ces messages lors d’un apt update :

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LANG = "fr_FR.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").Code language: PHP (php)

ou encore ces messages avec apt upgrade, après chaque installation ou mise à jour de paquets :

locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directoryCode language: JavaScript (javascript)

Pas de panique, j’ai quelques solutions pour régler le problème si vous aussi y êtes confronté.

Dans ce tutoriel, j’utilise “en_US.UTF-8” parce que j’aime tout avoir en anglais. Si vous préférez le français, remplacez tout par “fr_FR.UTF-8”.

Etape 1 : éditez le fichier locale

Editez votre fichier /etc/default/locale :

nano /etc/default/localeCode language: JavaScript (javascript)

et ajoutez ces lignes:

LC_ALL=en_US.UTF-8
LC_CTYPE=en_US.UTF-8
LC_MESSAGES=en_US.UTF-8
LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8

Enregistrez le fichier, quittez votre session SSH puis reconnectez-vous pour avoir une nouvelle session avec le changement de locale.

Etape 2 : reconfigurer les locales

On commence par générer la locale de notre choix :

locale-gen "en_US.UTF-8"Code language: JavaScript (javascript)

Et on la reconfigure :

dpkg-reconfigure locales

Il ne reste plus qu’à tester les locales du système:

locale

Résultat:

LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8Code language: JavaScript (javascript)

Et voilà, plus de messages d’avertissement ou d’erreur concernant les locales de votre système. Problème réglé.

Linux : créer un fichier d'échange (swap) pour optimiser un VPS photo

Linux : créer un fichier d’échange (swap) pour optimiser un VPS

De temps en temps, on me demande de configurer des serveurs dédiés ou des VPS. Dernièrement, j’ai travaillé sur un VPS qui n’avait pas de fichier swap et qui finissait par consommer toute la RAM disponible.

Ce tutoriel vous permet de mettre en place un fichier swap sous Ubuntu 16.04 Server.

Le fichier swap

Le moyen le plus simple d’avoir un serveur réactif et de le prémunir contre les erreurs out-of-memory des services est d’allouer un fichier swap.

Le swap est une zone du disque dur spécialement créée pour que le système d’exploitation y garde des données temporaires qu’il ne peut plus stocker dans la RAM.

Cet espace permet donc aux services du serveur de continuer de tourner même lorsque la RAM est épuisée et ne sera utilisé que dans ce cas de figure.

Les informations seront cependant écrites sur le disque beaucoup moins rapidement que via la RAM.

Vérification du swap sur le système

Commençons par vérifier si un fichier de swap est déjà en place :

swapon --show

Aucun résultat : le système n’a pas d’espace réservé pour le fichier d’échange.

On vérifie une nouvelle fois s’il existe un fichier de swap actif:

free -h

Résultat:

                        total        used        free      shared  buff/cache   available
Mem:           3.9G        517M        2.5G         76M        895M        3.0G
Swap:            0B          0B          0B

Pas de swap actif sur notre système, nous allons donc pouvoir en ajouter une.

Vérification de l’espace disponible

Il est très commun de créer une nouvelle partition qui contient le fichier d’échange mais comme il n’est pas toujours possible de changer le schéma de partition, nous allons créer un fichier d’échange qui résidera sur notre partition existante.

Vérifions l’espace disponible :

df -h

Résultat:

Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G     0  2.0G   0% /dev
tmpfs           396M  3.2M  393M   1% /run
/dev/vda1        59G   13G   45G  22% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
tmpfs           396M     0  396M   0% /run/user/0Code language: PHP (php)

Le disque dur se trouve sous /dev dans notre cas.

En ce qui concerne la taille de la partition swap : elle ne doit pas dépasser 4 Go (parce qu’au-delà, c’est inutile) et doit correspondre à peu près à la taille de votre RAM (ou le double de votre RAM suivant votre serveur).

Création du fichier d’échange

Nous allons donc créer un fichier d’échange nommé swapfile, d’une taille de 4 Go, à la racine du système (/).

sudo fallocate -l 4G /swapfile

Par souci de sécurité, ce fichier sera uniquement lisible par l’utilisateur root :

sudo chmod 600 /swapfile

Vérifions les permissions et l’espace réservé :

ls -lh /swapfile

Résultat:

-rw------- 1 root root 4.0G Jan 17 16:31 /swapfile

Lire la suite

BASH : supprimer les fichiers de session PHP obsolètes photo

BASH : supprimer les fichiers de session PHP obsolètes

Je vous ai déjà parlé du problème des fichiers de session PHP.

Or, je me suis aperçu que le problème n’est toujours pas réglé sous Debian : les fichiers de session de PHP ne sont jamais effacés et cela finit par saturer la partition /root.

Sur le serveur, ces fichiers prenaient 590 Mo, ce qui est énorme vu que ces fichiers ont la taille d’un fichier de cookies. Il y en a donc des milliers, dans un seul répertoire, ce qui consomme un maximum d’inodes.

A oneliner to rule ’em all

Voici le nombre d’inodes avant de lancer la commande de nettoyage :

df -i

Résultat:

Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/root        640K  212K  429K   34% /
devtmpfs         487K  1.5K  486K    1% /dev
tmpfs            487K   864  487K    1% /run
tmpfs            487K     4  487K    1% /run/lock
tmpfs            487K     2  487K    1% /run/shm
/dev/sda2         44M   75K   43M    1% /home

Voici donc comment régler le problème en une seule ligne, dans le terminal. On supprime tous les fichiers de sessions qui existent depuis plus de 24 minutes (TTL par défaut de PHP) :

find /var/lib/php/sessions -type f -cmin +24 -name 'sess_*' | xargs rmCode language: JavaScript (javascript)

Notez la rapidité d’exécution de la commande, grâce à xargs.

On relance le calcul d’inodes:

df -i

Résultat:

Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/root        640K   88K  553K   14% /
devtmpfs         487K  1.5K  486K    1% /dev
tmpfs            487K   864  487K    1% /run
tmpfs            487K     4  487K    1% /run/lock
tmpfs            487K     2  487K    1% /run/shm
/dev/sda2         44M   75K   43M    1% /home

Boom : 20% d’inodes en plus. Pas mal, surtout que ces sessions sont expirées depuis belle lurette et auraient dues être supprimées depuis bien longtemps.

Crontab pour supprimer les fichiers de session PHP

Le mieux reste encore de créer une tâche cron qui va vérifier chaque jour que le répertoire de sessions ne se remplit pas inutilement.

Nous allons toutefois faire les choses avec un peu plus de finesse : chercher le chemin de stockage des sessions ainsi que la durée de vie des sessions et supprimer chaque jour les fichiers expirés.

On crée notre script bash:

nano /etc/scripts/cleanup-php-sessions.sh
#!/bin/bash
# Script Name : cleanup-php-sessions.sh
# Author : Matt Biscay
# Author URL :  https://www.skyminds.net/?p=28992
# Hire me : https://www.skyminds.net/hire-me/

# Export bin paths
export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Get PHP Session Details
PHPSESSIONPATH=$(php -i 2>/dev/null | grep -w session.save_path | awk '{print $3}' | head -1);
PHPSESSIONLIFETIME=$(php -i 2>/dev/null | grep -w session.gc_maxlifetime | awk '{print $3}' | head -1);
PHPSESSIONLIFETIMEMINUTE=$( expr $PHPSESSIONLIFETIME / 60 );

# If PHPSESSIONPATH exists
if [ -d $PHPSESSIONPATH ];
then
    # Find and delete expired sessions files :

	# Sluggish way
	#find $PHPSESSIONPATH -type f -cmin +$PHPSESSIONLIFETIMEMINUTE -name "sess_*" -exec rm -f {} \;

	# Quick way
	find $PHPSESSIONPATH -type f -cmin +$PHPSESSIONLIFETIMEMINUTE -name 'sess_*' | xargs rm
fiCode language: PHP (php)

Il ne reste plus qu’à l’activer:

crontab -e

et on lance le script tous les jours à minuit :

@daily sh /etc/scripts/cleanup-php_sessions.sh #Cleanup PHP sessions dailyCode language: CSS (css)

Et voilà, mine de rien, vous venez de vous enlever une future épine du pied.

C’est typiquement le genre de fichiers que l’on ne surveille pas et qui peuvent un jour poser problème, notamment au niveau des inodes.

Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian photo

Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian

Aujourd’hui, nous sautons le pas et passons du serveur Apache au serveur NginX (à prononcer “engine X”) pour booster les performances générales du site.

Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian photo

Cela fait quelques serveurs que je monte pour d’autres en utilisant nginx et force est de constater que c’est beaucoup plus réactif qu’Apache et cela prend moins de temps à configurer pour optimiser les réglages.

Je pars du principe que c’est une nouvelle installation mais si vous aviez déjà votre site qui tournait sous Apache, certaines étapes seront juste optionnelles.

Ce tutoriel vise un serveur Debian mais est adaptable sans problème à ses dérivés comme Ubuntu ou Mint.

Etape 1 : NginX

Nous allons installer la dernière version du serveur nginx, avec le support pour HTTP2, depuis les dépôts Sury :

nano /etc/apt/sources.listCode language: PHP (php)

et nous ajoutons :

# SURY, post-Dotdeb
deb https://packages.sury.org/php/ stretch main
deb https://packages.sury.org/nginx-mainline/ stretch main
deb https://packages.sury.org/mariadb/ stretch mainCode language: PHP (php)

On rafraîchit les dépôts :

apt update

et on installe nginx et openssl :

apt install nginx openssl libssl1.0.2 libssl1.0.1 libssl-devCode language: CSS (css)

Etape 2 : MariaDB

Si vous ne l’avez pas déjà – cela remplace MySQL sans que vous n’ayez rien à changer au niveau du code ou de la configuration du serveur :

apt install mariadb-server

Etape 3 : PHP

Je vous conseille de suivre mon dernier guide pour installer PHP 7.1.

Etape 4 : configurer NginX

Nous allons d’abord configurer toutes les options qui nous sont primordiales : compression des fichiers statiques, implémentation SSL, types mime… afin de gagner du temps (et éviter les erreurs) dans l’étape suivante.

1. Nous voulons un site rapide donc nous allons compresser tout ce qui peut l’être. On crée un nouveau fichier :

nano /etc/nginx/snippets/gzip-config.conf

et on y met :

# MATT : add more mime-types to compress
types {
	application/x-font-ttf           ttf;
	font/opentype                    ott;
}

# MATT : gzip all the things!
 gzip on;
 gzip_disable "msie6";
 gzip_vary on;
 gzip_proxied any;
 gzip_comp_level 6;
 gzip_min_length 256;
 gzip_buffers 16 8k;
 gzip_http_version 1.1;
 #gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  # Compress all output labeled with one of the following MIME-types.
 gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/ld+json
    application/manifest+json
    application/rss+xml
    application/vnd.geo+json
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/bmp
    image/svg+xml
    image/x-icon
    text/cache-manifest
    text/css
    text/plain
    text/vcard
    text/vnd.rim.location.xloc
    text/vtt
    text/x-component
    text/x-cross-domain-policy;
# text/html is always compressed by gzip module
# don't compress woff/woff2 as they're compressed alreadyCode language: PHP (php)

J’ai ajouté deux types mime qui ne sont pas dans la configuration de base d’NginX et étendu la liste des types de fichiers à compresser. Certains types le sont déjà donc c’est inutile de gaspiller des ressources en essayant de les compresser.

Lire la suite