Serveur dédié : résoudre l'erreur

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

Télécharger vos fichiers torrents automatiquement avec Flexget photo

Télécharger vos fichiers torrent automatiquement avec FlexGet et Transmission

Aujourd’hui, nouvelle étape dans l’automatisation de nos téléchargements : au lieu d’uploader un fichier .torrent ou magnet sous Transmission, nous allons installer FlexgGet qui va nous permettre de surveiller un flux RSS pour télécharger automatiquement les fichiers bittorrent.

Une fois le fichier graine téléchargé, Transmission se chargera de télécharger les fichiers immédiatement. Tout sera donc automatisé !

En prérequis, je vous conseille d’avoir Transmission installé et configuré sur votre serveur ou machine, cela vous fera gagner pas mal de temps.

Étape 1 : configuration de Transmission

Vous avez déjà Transmission qui tourne ? Parfait, on commence par arrêter le service :

service transmission-daemon stop

On crée un nouveau répertoire qui sera surveillé par Transmission – dès qu’un fichier .torrent sera ajouté dans ce répertoire, Transmission lancera le téléchargement :

mkdir /home/transmission/torrentwatch

On lui donne les bons droits et le bon utilisateur :

chown debian-transmission:debian-transmission /home/transmission/torrentwatch
chmod 777 /home/transmission/torrentwatch

Et on édite le fichier de configuration :

nano /etc/transmission-daemon/settings.json

Je me suis aperçu qu’il me manquait deux directives importantes dans ce fichier pour surveiller un répertoire donc on les ajoute à la suite des autres directives :

   "watch-dir": "/home/transmission/torrentwatch",
    "watch-dir-enabled": true,Code language: JavaScript (javascript)

On sauvegarde le fichier et on redémarre Transmission :

service transmission-daemon start

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

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.

Serveur dédié : mise à jour vers Debian 9 Stretch photo

Serveur dédié : mise à jour vers Debian 9 Stretch

Cette semaine, le système d’exploitation du serveur principal passe de Debian 8 Jessie à Debian 9 Stretch.

Mise à jour des paquets du système

La mise à jour s’est faite plutôt simplement pour la majeure partie des paquets :

apt update && apt upgrade

mais il a fallu s’y reprendre à plusieurs fois pour les paquets restants :

apt install 

Changements dans la configuration

Quelques changements notables sont à noter.

Configuration apt

On vérifie que tous nos dépôts pointent bien vers la version Stretch:

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

On sauvegarde et on lance les mises à jour:

apt update && apt upgrade

Configuration SSH

La configuration SSH a été modifiée et certaines directives ne sont plus valables. Avant de redémarrer le serveur SSH ou de rebooter et de perdre tout accès au serveur SSH, assurez-vous que la configuration est correcte :

sshd -t

Résultats :

/etc/ssh/sshd_config line 25: Deprecated option KeyRegenerationInterval
/etc/ssh/sshd_config line 26: Deprecated option ServerKeyBits
/etc/ssh/sshd_config line 44: Deprecated option RhostsRSAAuthentication

Il ne vous reste plus qu’à éditer le fichier de configuration SSH:

nano /etc/ssh/sshd_config

J’ai désactivé les lignes qui posaient problème et ai rajouté de nouveaux protocoles de clé :

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

Sauvegardez le fichier puis lancez cette commande pour créer les couples de clés privées/publiques dans /etc/ssl:

ssh-keygen -A

Résultat:

ssh-keygen: generating new host keys: ECDSA ED25519Code language: JavaScript (javascript)

Vérifiez une dernière fois qu’il n’y a aucun problème avec le fichier de configuration SSH:

sshd -t

et redémarrez le service SSH:

service ssh restart

Configuration de Courier

C’est le bon moment de revoir la configuration IMAP et POP de Courier.

On commence par renouveler notre fichier Diffie-Hellman en 4096 bits:

cd /etc/courier
openssl dhparam -out dhparams4096.pem 4096

et on revoit la configuration de /etc/courier/imap-ssl :

SSLPORT=993

SSLADDRESS=0

SSLPIDFILE=/run/courier/imapd-ssl.pid

SSLLOGGEROPTS="-name=imapd-ssl"

IMAPDSSLSTART=YES

IMAPDSTARTTLS=YES

IMAP_TLS_REQUIRED=1

COURIERTLS=/usr/bin/couriertls

TLS_PROTOCOL=TLS1_2:TLS1_1:TLS1

TLS_STARTTLS_PROTOCOL=TLS1_2:TLS1_1:TLS1

TLS_CIPHER_LIST="ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"

TLS_KX_LIST=ALL

TLS_COMPRESSION=ALL

TLS_CERTS=X509

TLS_DHCERTFILE=/etc/courier/dhparams4096.pem

TLS_CERTFILE=/etc/courier/skyminds-cert.pem

TLS_TRUSTCERTS=/etc/ssl/certs

TLS_VERIFYPEER=NONE

TLS_CACHEFILE=/var/lib/courier/couriersslcache
TLS_CACHESIZE=524288

MAILDIRPATH=MaildirCode language: JavaScript (javascript)

Le chemin de SSLPIDFILE a changé donc pensez à le vérifier.

Certificat TLS pour Courier

Depuis que j’utilise les certificats TLS de Let’s Encrypt, il y a une petite modification a exécuter pour que le certificat s’applique aussi à notre serveur de mail : créer automatiquement un certificat pour Courier dès que notre certificat principal est généré.

On crée un script bash pour compiler notre clé privée et notre certificat Let’s Encrypt :

nano /home/scripts/letsencrypt-skyminds-mailserver.sh

avec :

#!/bin/bash
cat /etc/letsencrypt/live/skyminds.net/privkey.pem /etc/letsencrypt/live/skyminds.net/fullchain.pem > /etc/courier/skyminds-cert.pemCode language: JavaScript (javascript)

et on édite notre fichier Let’s Encrypt pour le renouvellement :

nano /etc/letsencrypt/renewal/skyminds.net.conf

et on ajoute la directive renew_hook avec notre nouveau script:

[renewalparams]
account = ...
renew_hook = /home/scripts/letsencrypt-skyminds-mailserver.shCode language: JavaScript (javascript)

Il ne reste plus qu’à éditer la configuration IMAP:

nano /etc/courier/imapd-ssl

et y mettre :

TLS_CERTFILE=/etc/courier/skyminds-cert.pemCode language: JavaScript (javascript)

puis redémarrez le service:

service courier-imap-ssl restart

Voilà, ce sont les principales modifications a effectuer lors de la mise à jour vers Debian 9.

Linux : résoudre l'erreur

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 : donner les privilèges sudo à un utilisateur sur une instance Amazon Web Service EC2 photo

Linux : donner les privilèges sudo à un utilisateur sur une instance Amazon Web Service EC2

Amazon Elastic Compute Cloud ou EC2 est un service proposé par Amazon Web Services (AWS) permettant à des tiers de louer des serveurs sur lesquels exécuter leurs propres applications web.

Linux : donner les privilèges sudo à un utilisateur sur une instance Amazon Web Service EC2 photo

Si vous avez déjà travaillé sur une instance Amazon EC2 sous linux, vous avez très certainement essayé d’utiliser sudo pour lancer des commandes qui nécessitent une élévation des privilèges de votre utilisateur.

Or, la configuration Amazon ne le permet pas par défaut mais utilise une implémentation du fichier sudoers qui n’est pas standard pour une installation linux.

Une implémentation du fichier sudoers différente

Normalement, lorsque l’on lance visudo, on obtient une version éditable du fichier /etc/sudoers qui nous permet de modifier les comptes utilisateurs pour leur donner la permission d’exécuter la commande sudo et donc contrôler quelles commandes ces utilisateurs peuvent lancer.

Anatomie du fichier sudoers

Voici un exemple de fichier sudoers classique :

# User privilege specification
root ALL=(ALL:ALL) ALL# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL# See sudoers(5) for more information on “#include” directives:#includedir /etc/sudoers.dCode language: PHP (php)

Les membres des groupes admin et sudo bénéficient des privilèges sudo, tout comme le compte root. Toutefois, aucune de ces lignes ne s’appliquent à un compte EC2 qu’un utilisateur AWS peut utiliser.

C’est la dernière ligne, avec la directive #includedir, qui permet de charger le bon fichier avec les privilèges utilisateur. Il est vital de noter que le signe # dans #includedir n’est pas un commentaire mais indique qu’il faut charger les fichiers contenus dans le répertoire /etc/sudoers.d – cela peut prêter à confusion mais c’est comme cela que le fichier sudoers fonctionne.

EC2 : donner les droits sudo à un utilisateur

Sur une instance EC2, il suffit de lister le contenu du répertoire /etc/sudoers.d pour trouver le bon fichier:

ls /etc/sudoers.d

Dans la plupart des cas et des distributions, le nom du fichier débute par un nombre élevé tel que 90. Ces fichiers sont chargés par ordre décroissant, à la manière du lancement d’une fusée, donc un fichier qui commence par 90 sera exécuté avant un fichier qui commence par 10.

Lire la suite

MacOS : résoudre le problème d'encodage Unicode des accents photo

MacOS : résoudre le problème d’encodage Unicode des accents sous WordPress (ou autre CMS)

Des espaces après chaque caractère accentué

Pour le site du Kriya Yoga France, on me transmet régulièrement des fichiers PDF que je dois transformer en articles. Je fais donc la plupart du temps un copié-collé et ensuite je m’attèle à la mise en page dans l’éditeur WordPress.

MacOS : résoudre le problème d'encodage Unicode des accents photo

Le hic, c’est que depuis l’année dernière, je travaille sous MacOS pour tout ce qui est développement web.

J’ouvre donc chaque PDF avec Preview – la visionneuse PDF installée par défaut – mais lorsque l’on colle le contenu du PDF dans un autre document, tous les caractères accentués sont suivis d’une espace (oui, on dit bien une espace en typographie) et des sauts de ligne apparaissent de nulle part. Clairement improductif.

Un conflit Unicode

Le problème réside entre un conflit lors de l’encodage Unicode entre caractères précomposés et caractères décomposés.

Un caractère précomposé ou caractère composite ou caractère décomposable est une entité Unicode qui peut aussi être définie comme une combinaison de plus de deux caractères.

Un caractère précomposé peut typiquement représenter une lettre surplombée d’un accent, comme é (lettre e avec accent aigu).

Techniquement, é (U+00E9) est un caractère qui peut être décomposé en son équivalent unicode à base de la lettre e (U+0065) et du caractère combinant accent aigu (U+0301).

La solution : UnicodeChecker

Heureusement, il existe un petit utilitaire, UnicodeChecker, qui permet de régler le problème très simplement. Voici la marche à suivre.

1. Lancez UnicodeChecker > File > New Utilities Window.

2. Copiez le texte de votre fichier PDF en mémoire (sélectionnez le texte puis Cmd+C ou Ctrl+C au clavier).

3. Dans UnicodeChecker, choississez l’option Normalize (6ème icône) et collez votre texte dans le champ Input puis appuyez sur Entrée. Cela donne :

MacOS : résoudre le problème d'encodage Unicode des accents sous Preview photo

Quatre champs sont proposés avec le résultat de la normalisation. Les deux champs qui nous importent sont NFC et NFKC, qui utilisent tout deux de l’Unicode précomposé, dans lequel l’accent fait partie intégrante du caractère accentué et non une entité à part.

4. Sélectionnez et copiez le texte contenu dans le champ NFC:

MacOS : résoudre le problème d'encodage Unicode des accents sous Preview photo 1

5. Collez maintenant le texte précédemment copié dans votre document ou l’éditeur de texte de votre CMS. A l’œil nu, rien ne change mais dans le rendu, votre texte est désormais correctement accentué, sans espaces inopportunes.

Lire la suite

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

Serveur dédié : mise à jour vers PHP7.1 sous Debian photo

Serveur dédié : mise à jour vers PHP7.1 sous Debian

Aujourd’hui, le serveur passe à PHP7.1 !

Ce tutoriel aborde le passage de PHP7.0 à PHP7.1 sur une Debian stable (Jessie).

L’opération prend une vingtaine de minutes, en comptant les opérations de vérifications (pre-flight checks en anglais).

La retraite PHP chez Dotdeb

Guillaume Plessis, qui maintient Dotdeb, a récemment annoncé que pour des raisons personnelles et professionnelles, Dotdeb ne fournira plus les mises à jour de PHP passé la version 7.0.

Je comprends sa décision : c’est chronophage et il faut pouvoir être en mesure de répondre aux commentaires et attentes d’une foule de personnes qui utilisent ce dépôt. Pas toujours simple. Merci Guillaume pour tout le travail accompli !

Vérification de la compatibilité PHP7.x sous WordPress

Si votre site tourne sous WordPress, il existe un plugin très utile – PHP Compatibility Checker – qui permet de vérifier que la mise à jour n’impactera pas votre site.

Je pense notamment aux plugins dont certains peuvent être assez vieillots et dont les fonctions peuvent être maintenant obsolètes.

Lancez-le avant de faire la mise à jour. S’il rapporte des warnings, ce n’est pas un problème. Si ce sont des erreurs par contre, mieux vaut y jeter un oeil avant de mettre à jour votre serveur.

Nouveau dépôt PHP : Ondrey Sury

Si l’on veut PHP7.1, il faut donc changer de dépôt et utiliser celui d’Ondrey Sury.

On installe donc ce nouveau dépôt :

apt install apt-transport-https lsb-release ca-certificates
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" >> /etc/apt/sources.listCode language: PHP (php)

Installation de PHP7.1

On met à jour et on installe PHP7.1 :

apt update && apt upgrade

Résultat :

The following NEW packages will be installed:
  libzip4 php7.1-cli php7.1-common php7.1-curl php7.1-fpm php7.1-gd php7.1-json php7.1-mbstring php7.1-mcrypt php7.1-opcache php7.1-readline php7.1-xml php7.1-xmlrpc
The following packages will be upgraded:
  libssl-doc libssl1.0.2 php-common php-curl php-fpm php-gd php-mbstring php-mcrypt php-xml php-xmlrpc php7.0 php7.0-bcmath php7.0-cli php7.0-common php7.0-curl php7.0-fpm php7.0-gd php7.0-json php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-opcache php7.0-readline php7.0-soap php7.0-xml php7.0-xmlrpc php7.0-zipCode language: CSS (css)

On installe les paquets manquants :

php7.1-mysql php7.1-soapCode language: CSS (css)

Lire la suite