Auto Draft photo 1

Mise à jour du serveur vers Ubuntu Focal Fossa (20.04 LTS)

Ce soir, on lance la mise à jour du serveur: nous passons notre version d’Ubuntu Server de Bionic Beaver (18.04 LTS) à Focal Fossa (20.04 LTS).

On commence par les précautions d’usage: faire ses sauvegardes et vérifier qu’elles sont bien intègres avant de commencer la mise à jour. C’est votre bouée en cas de soucis!

Étape 1: avoir l’installation d’Ubuntu actuelle à jour

Assurez-vous d’avoir une installation à jour avant de commencer:

apt update && apt dist-upgrade

On reboot ensuite pour appliquer les changements:

shutdown -r now

Étape 2: installation de screen et ouverture du port 1022 pour SSH

Comme nous allons lancer la mise à jour via un terminal SSH, il est possible que pour une raison ou un autre la connexion soit coupée. Cela arrive et cela peut être vraiment tendu à certaines étapes de la mise à jour (kernel anyone?).

Pour prévenir cela, on vérifie que screen est bien installé:

apt install screen

On peut lancer une session screen avec:

screen

et si la connexion SSH est interrompue lors de la mise à jour, on peut se raccrocher à la session de mise à jour avec la commande:

screen -Dr

Ensuite, au niveau du pare-feu, on ouvre le port 1022. C’est via ce port que l’on pourra reprendre la MAJ en cas de pépin. Suivant la configuration du serveur, on peut utiliser iptables:

iptables -I INPUT -p tcp --dport 1022 -j ACCEPT

ou alors ufw:

ufw allow 1022

Lire la suite

Solution pour l'erreur cURL error 7: Failed to connect to XXX port 443: Connection refused photo 1

Solution pour l’erreur cURL error 7: Failed to connect to XXX port 443: Connection refused

Sur un serveur hébergé en Chine continentale, j’ai eu la surprise de ne pas être en mesure de mettre à jour wp-cli:

wp cli update

Error: Failed to get url 'https://api.github.com/repos/wp-cli/wp-cli/releases?per_page=100': cURL error 7: Failed to connect to api.github.com port 443: Connection refused.Code language: JavaScript (javascript)

Visiblement, certaines adresses sont injoignables, notamment lorsqu’elles utilisent le port 443 (https).

Evidemment, on peut télécharger wp-cli manuellement et le réinstaller mais si vous souhaitez une solution plus rapide, voilà comment j’ai procédé.

Première solution: édition de /etc/hosts

1. On récupère l’adresse IP de l’adresse api.github.com:

curl --ipv4 -v https://api.github.com

Résultat: 13.250.94.254 port 443Code language: JavaScript (javascript)

2. On édite le fichier /etc/hosts du serveur:

nano /etc/hosts

3. On y ajoute l’adresse IP correspondante à api.github.com:

13.250.94.254 api.github.comCode language: CSS (css)

Et voilà, le téléchargement depuis github est de nouveau accessible.

Lire la suite

PHP: résoudre l'erreur "file_get_contents(): SSL operation failed with code 1" photo

PHP: résoudre l’erreur “file_get_contents(): SSL operation failed with code 1”

J’ai récemment joué avec l’API de YouTube pour pouvoir récupérer diverses informations sur les vidéos afin d’ajouter au site les données structurées idoines.

Il se trouve qu’en local, lorsque l’on utilise file_get_contents(), on peut obtenir une erreur de ce type lorsque le serveur n’est pas configuré avec le bundle de certificats OpenSSL:

Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in ...php on line 2

Warning: file_get_contents(): Failed to enable crypto in ...php on line 2

Warning: file_get_contents(https://........f=json): failed to open stream: operation failed in ...php on line 2
Code language: JavaScript (javascript)

Si cela vous arrive, plusieurs solutions s’offrent à vous.

Méthode 1: configuration de PHP côté machine/serveur

1. Vérifiez qu’OpenSSL est bien installé sur votre machine (il devrait l’être sur le serveur!).

2. Ajoutez cette ligne à la configuration de PHP, dans votre php.ini:

openssl.cafile=/usr/local/etc/openssl/cert.pemCode language: JavaScript (javascript)

3. Redémarrez le service PHP.

Méthode 2 : une fonction qui utilise curl au lieu de file_get_contents()

Au lieu de m’embêter à configurer OpenSSL ou à toucher à PHP dans un conteneur docker (Local), il se trouve que l’on peut réécrire la fonction file_get_contents() avec une fonction maison qui utilise curl.

Voici la fonction en question:

/*
Custom CURL function that mimicks file_get_contents()
@returns false if no content is fetched
Matt Biscay (https://mattbiscay.com)
*/
function sky_curl_get_file_contents( $URL ){
	$c = curl_init();
	curl_setopt( $c, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt( $c, CURLOPT_URL, $URL );
	$contents = curl_exec( $c );
	curl_close( $c );
	if( $contents ) :
		return $contents;
	else:
		return false;
	endif;
}Code language: PHP (php)

La fonction retourne false si la requête échoue, ce qui est très utile pour éviter de faire des appels à des valeurs d’un tableau qui n’existe pas.

On peut alors réfléchir à un autre moyen de peupler les champs de données structurées (mais c’est un sujet à aborder une autre fois).

Javascript : afficher le contenu d'un bloc HTML après un délai variable photo

JavaScript : tester si un paramètre existe dans une URL

J’ai eu besoin de tester l’existence d’un paramètre GET dans une URL en utilisant JavaScript. Il se trouve que cela ne prend que quelques lignes.

Pour ce tutoriel, nous allons considérer l’adresse de la page suivante, avec preview=yes passé comme paramètre:

https://example.com/?preview=yesCode language: JavaScript (javascript)

URLSearchParams() à la rescousse

Il est très simple de récupérer les variables $_GET avec PHP mais avec JavaScript, nous allons utiliser la classe URLSearchParams pour faire cela proprement.

1. On récupère les paramètres passés dans l’URL de la page:

let searchParams = new URLSearchParams(window.location.search);Code language: JavaScript (javascript)

2. On vérifie si l’un des paramètres recherchés est présent. Ici, on souhaite savoir si le paramètre preview existe:

searchParams.has('preview'); // returns trueCode language: JavaScript (javascript)

3. On vérifie maintenant si preview est égal à yes:

let param = searchParams.get('sent');
param; // echoes 'yes'Code language: JavaScript (javascript)

Il ne nous reste plus qu’à utiliser la variable param pour l’utiliser ou la comparer.

PHP : solution pour l'erreur "preg_match(): Compilation failed: invalid range in character class" photo

PHP : solution pour l’erreur “preg_match(): Compilation failed: invalid range in character class”

Lors de la mise à jour d’un site vers PHP 7.4, je suis tombé sur cette erreur :

preg_match(): Compilation failed: invalid range in character class at offset 20 session.php on line 278Code language: JavaScript (javascript)

Depuis PHP 7.3, le moteur PCRE – qui est responsable de la gestion des expressions régulières – a été migré vers PCRE2.

Or, il s’avère que PCRE2 est plus strict dans la validation des pattern et c’est la raison pour laquelle, après la mise à jour de PHP, certaines expressions régulières ne peuvent plus être compilées correctement.

Voici un exemple d’expression régulière qui fonctionnait avant PHP7.3:

preg_match('/[\w-.]+/', ''); // this will not work in PHP7.3Code language: JavaScript (javascript)

Voici maintenant le même exemple mais qui sera désormais valide sous PHP 7.3 et les versions ultérieures :

preg_match('/[\w\-.]+/', ''); // the hyphen needs to be escapedCode language: JavaScript (javascript)

Comme vous pouvez le constater dans le deuxième exemple, il faut maintenant échapper le tiret (hyphen) avec un backslash.

Une fois la modification faite, plus d’erreur à ce niveau.

Redémarrer la machine virtuelle de Local by Flywheel photo

Local by Flywheel ne démarre plus à cause du renouvellement du certificat TLS de la machine virtuelle (docker) : une solution

J’utilise quotidiennement Local by Flywheel pour développer ou debugger des problèmes sur certains sites.

C’est une bonne alternative lorsque les hébergeurs ne proposent pas de site staging à leurs clients (les meilleurs hébergeurs proposent évidemment un staging, c’est la base).

L’autre jour, tournée de mises à jour suivie d’un reboot, je lance Local et patatras: il ne veut plus démarrer et visiblement reste bloqué sur une tentative de renouvellement de certificat TLS pour la machine virtuelle qui tourne sous Docker.

Si cela vous arrive, voici la marche à suivre. Il suffit de copier ces lignes d’instructions dans votre terminal. Concrètement, nous allons télécharger une nouvelle version du fichier ISO Boot2Docker et laisser le système se ré-provisionner.

Le processus implique de créer un alias (local-docker-machine) pour la machine virtuelle docker “Local by Flywheel”, et ensuite de lancer la série de commandes suivantes sur cet alias.

Voici les commandes à lancer dans le terminal:

alias local-docker-machine="/Applications/Local\ by\ Flywheel.app/Contents/Resources/extraResources/virtual-machine/vendor/docker/osx/docker-machine"
local-docker-machine stop local-by-flywheel
rm -rf ~/.docker/machine/certs
local-docker-machine create local-cert-gen
local-docker-machine start local-by-flywheel
local-docker-machine regenerate-certs -f local-by-flywheel
local-docker-machine rm -f local-cert-genCode language: JavaScript (javascript)

Voici le résultat de ces commandes:

Creating CA: /Users/matt/.docker/machine/certs/ca.pem
Creating client certificate: /Users/matt/.docker/machine/certs/cert.pem
Running pre-create checks...
(local-cert-gen) No default Boot2Docker ISO found locally, downloading the latest release...
(local-cert-gen) Latest release for github.com/boot2docker/boot2docker is v19.03.5
(local-cert-gen) Downloading /Users/matt/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v19.03.5/boot2docker.iso...
(local-cert-gen) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
Creating machine...
(local-cert-gen) Copying /Users/matt/.docker/machine/cache/boot2docker.iso to /Users/matt/.docker/machine/machines/local-cert-gen/boot2docker.iso...
(local-cert-gen) Creating VirtualBox VM...
(local-cert-gen) Creating SSH key...
(local-cert-gen) Starting the VM...
(local-cert-gen) Check network to re-create if needed...
(local-cert-gen) Found a new host-only adapter: "vboxnet1"
(local-cert-gen) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: /Applications/Local by Flywheel.app/Contents/Resources/extraResources/virtual-machine/vendor/docker/osx/docker-machine env local-cert-gen
Docker machine "local-by-flywheel" does not exist. Use "docker-machine ls" to list machines. Use "docker-machine create" to add a new one.
Regenerating TLS certificates
Docker machine "local-by-flywheel" does not exist. Use "docker-machine ls" to list machines. Use "docker-machine create" to add a new one.
About to remove local-cert-gen
WARNING: This action will delete both local reference and remote instance.
Successfully removed local-cert-genCode language: JavaScript (javascript)

Vous n’avez plus qu’à lancer Local by Flywheel: lancement maintenant impeccable et toutes les machines virtuelles sont bien là.

jQuery : sélectionner un élément dont l'ID ou la classe commence ou finit par une chaîne photo 1

jQuery : comment ajouter !important à une propriété CSS

jQuery possède une limitation qui peut s’avérer très gênante : on ne peut ajouter !important à une propriété CSS en utilisant un script jQuery.

Par exemple, ceci ne fonctionnera pas:

jQuery('.foo').css('border', '4px #000 solid !important');Code language: JavaScript (javascript)

alors que cette déclaration sera bien appliquée:

jQuery('.foo').css('border', '4px #000 solid');Code language: JavaScript (javascript)

Pour contourner cette limitation, je vous propose plusieurs solutions.

Première solution : utiliser la fonction addClass()

C’est probablement la solution la plus simple : il suffit d’ajouter une classe votre élément avec addClass(), puis de définir le code CSS relatif à cette classe.

Exemple:

jQuery('.foo').addClass('border-black');Code language: JavaScript (javascript)

et on ajoute le code CSS suivant:

.border-black{
    border: 4px #000 solid !important;
}Code language: CSS (css)

Deuxième solution : utiliser la fonction attr()

Une autre solution est d’utiliser la fonction attr(), avec une concaténation pour garder le style CSS inline s’il est déjà présent:

jQuery('.foo').attr('style', function(i,s) { return (s || '') + 'border:4px #000 solid !important;' });Code language: JavaScript (javascript)

Troisième solution : utiliser la propriété cssText

Toujours en utilisant la concaténation pour garder les styles inline existants, nous utilisons la propriété cssText de la fonction css() :

jQuery('.foo').css('cssText', jQuery('.foo').css('cssText')+'border: 4px #000 solid !important');Code language: JavaScript (javascript)

Quatrième solution : utiliser style.setProperty()

Ce n’est pas parce que l’on utilise jQuery que nous devons oublier le vanilla JavaScript.

En l’occurrence, JS offre nativement la fonction style.setProperty() qui nous permet d’appliquer notre style aisément:

jQuery('.foo').each(function(){
   this.style.setProperty( 'border', '4px #000 solid', 'important' );
});Code language: JavaScript (javascript)

Have fun!

Illustration montrant des fenêtres de navigateur web connectées par des lignes de réseau à une icône centrale de verrouillage au-dessus de "Net Neutrality", avec des icônes pour la vidéo, la localisation, les cartes, la conversation et le signal sur un fond sarcelle - évoquant la navigation sécurisée avec Freebox Revolution et les serveurs DNS.

Changer les serveurs DNS de la Freebox Revolution

Ces derniers temps, il n’est pas rare de constater que le serveur DNS de Free, utilisés par la Freebox, ne permettent plus de consulter certains sites. Or, l’utilisation d’un VPN permet d’accéder à ces sites sans problèmes.

Il est donc temps de changer l’adresse des serveurs DNS de la Freebox, on ne peut décemment pas utiliser un internet bridé par un tiers sans notre consentement.

Voici la marche à suivre, cela prend environ 1 minute à modifier. Nous allons utiliser les serveurs DNS de Cloudflare pour cet article:

Rendez-vous dans la console Freebox sur http://mafreebox.free.fr

Identifiez-vous.

Rendez-vous dans Paramètres de la Freebox > DHCP.

En serveur DNS1, mettez 1.1.1.1

En serveur DNS2, mettez 1.0.0.1

En serveur DNS3, gardez le DNS de Free en redondance: 192.168.0.254

Appliquez les changements pour sauvegarder la nouvelle configuration.

Voici ce que cela donne en image:

dns freebox cloudflare 1280x826

Une autre alternative est d’utiliser les DNS de Quad9:

DNS1: 9.9.9.9

DNS2: 149.112.112.112

Et voilà, les sites auparavant bloqués sont désormais accessibles.

Solution pour l'erreur 400 (bad request) lors d'un  renouvellement de certificat Let's Encrypt sous Plesk photo

Solution pour l’erreur 400 (bad request) lors d’un renouvellement de certificat Let’s Encrypt sous Plesk

Erreur 400 lors du renouvellement de certificat sous Plesk

Dernièrement, je suis tombé sur un os lors du renouvelement d’un certificat Let’s Encrypt d’un site qui tourne sur un serveur avec Plesk.

Il se trouve que le renouvellement était tout simplement impossible à cause d’une erreur 400 Bad Request:

Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Failed authorization procedure. www.example.com (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://www.example.com/.well-known/acme-challenge/2VQAX5eA_dSyl1RB5MjfcHr9YinF8T7nw3Z6OxU5Zu4: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>400 Bad Request</title>\n</head><body>\n<h1>Bad Request</h1", example.com (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://example.com/.well-known/acme-challenge/e4Y1e16A6e3czI1106dJiz6BMqsKjJxz21XaqvrHLZQ: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>400 Bad Request</title>\n</head><body>\n<h1>Bad Request</h1". Skipping.Code language: HTML, XML (xml)

Solution: décocher la redirection HTTP vers HTTPS

Après avoir passé pas mal de temps à auditer le site, les .htaccess, la configuration du serveur… il se trouve que la solution est très simple – mais encore faut-il le savoir car cela n’est marqué nulle part!

Sous Plesk:

1. rendez-vous dans le workspace du site en question.

2. cliquez sur SSL/TLS certificates.

3. décochez la case Redirect from http to https:

lets encrypt renew error 400 renewal 1280x790

Relancez maintenant le renouvellement du certificat Let’s Encrypt. Il devrait maintenant se renouveler sans aucun problème.

Linux et MacOS : lister tous les répertoires de plus de 500 Mo photo

Linux et MacOS : lister tous les répertoires de plus de 500 Mo

De temps en temps, il faut un peu faire le ménage sur nos disques durs et il est assez utile de chercher à savoir quels sont les dossiers qui prennent le plus d’espace disque.

Lister tous les répertoires de plus de 500 Mo

Sous Linux et MacOS, voici la commande que je lance pour trouver tous les répertoires de plus de 500 Mo, classés par ordre d’importance:

du -m ~/Downloads/* | awk '$1 > 500' | sort -nrCode language: JavaScript (javascript)

Voici le détail de la commande:

  • du signifie disk usage
  • -m signifie que l’on souhaite la taille en Mo
  • ~/Downloads/* est le chemin dans lequel se trouvent nos gros dossiers, là où se trouvent nos données
  • awk '$1 > 500' capture le chemin du dossier lorsqu’il dépasse 500 Mo
  • sort -nr permet de classer la liste du plus gros dossier au plus petit

Une petite commande à garder sous le coude, cela permet d’éviter de perdre trop de temps à trouver le dossier le plus gourmand du disque!

PHP Composer

Composer: solution pour l’erreur “Composer: file_put_contents(./composer.json): failed to open stream: Permission denied”

J’ai récemment joué avec Composer pour Login Redirect Pro et je dois dire que cela simplifie énormément la gestion des dépendances lorsque vous écrivez du code qui fait appel à du code tiers.

Lors du changement de Mac, et après import de mes anciennes données sur la nouvelle machine, j’ai obtenu le message d’erreur suivant:

Composer: file_put_contents(./composer.json): failed to open stream: Permission deniedCode language: HTTP (http)

Si cela vous arrive, il s’agit très probablement d’un problème de droits utilisateur sur le répertoire en question.

Comme j’ai migré mes données d’une machine à l’autre, les droits ne sont pas ceux du nouvel utilisateur de la machine.

Dans le terminal, il vous suffit donc de lancer:

sudo chown -R $USER ~/.composer/Code language: JavaScript (javascript)

Et voilà, Composer est de nouveau fonctionnel.

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;Code language: PHP (php)

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;Code language: JavaScript (javascript)

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!