Réalisation de votre projet web photo

Réalisons votre projet WordPress ou WooCommerce

Nos compétences au service de vos besoins

Stratégie

Nous étudions le parcours de votre site et vos besoins pour vous fournir une solution à long-terme, qui correspond à votre vision.

Développement

Vous souhaitez ajouter de nouvelles fonctionnalités à votre site ou boutique? Nous pouvons coder la solution!

Performance

Votre site doit être rapide et optimisé sur tous supports afin de convertir vos visiteurs. Nous auditons votre site et proposons la solution adaptée.

Hébergement

Vos projets ont besoin d’un hébergement de qualité, c’est la fondation de votre site web et elle doit être solide car c’est sur elle que tout repose.

Maintenance

Votre site a besoin d’une maintenance régulière afin de toujours utiliser la dernière mouture du code et rester sécurisé face aux menaces.

Assistance

Vous avez besoin d’aide ponctuelle? Pas de problème, nous sommes à votre écoute pour vous dépanner rapidement et sereinement.

Lire la suite

An automatic computer screen displaying the message "sorry you have been blocked".

Contourner le blocage du WAF Cloudflare pour les uploads de zip dans WordPress

Le blocage des fichiers zip par le WAF (Web Application Firewall) de Cloudflare est un casse-tête pour de nombreux développeurs WordPress, surtout lors de la mise à jour de plugins et de thèmes. Heureusement, il existe une solution pour contourner ce problème sans compromettre la sécurité de votre site WordPress.

Pourquoi le WAF bloque-t-il les fichiers Zip ?

Cloudflare met régulièrement à jour ses Managed Rules pour renforcer la sécurité. Un upload de fichier zip peut être un vecteur pour des attaques malveéillantes, comme l’installation de shells. Ainsi, Cloudflare bloque ces requêtes pour protéger votre site.

Dans notre cas, par contre, cela nous empêche de faire nos mises à jour et c’est quand même plus simple de mettre à jour les plugins et thèmes payants avec un fichier zip, plutôt que de passer par SFTP ou wp-cli.

Solution #1: créer une exception dans le WAF de Cloudflare

Évidemment, nous n’allons pas désactiver ces règles qui fonctionnent si bien et ajoutent une couche de protection à notre site. Non, nous allons simplement créer une exception aux Managed Rules, que nous placerons avant tous les autres set de règles pour qu’elle soit prise en compte en priorité.

Étape 1: rendez-vous dans le Dashboard de Cloudflare

Allez dans Security > WAF > Managed Rules.

Voici ce que vous obtenez:

A screenshot of the WAF settings in Google Analytics showcasing blocked zip files.

Cliquez ensuite sur le bouton Add exception à droite.

Lire la suite

viewport overflow

Vanilla JS : identifier l’élément plus large que le viewport

Aujourd’hui, je régle un petit souci d’affichage sur un une boutique WooCommerce propulsée par Astra.

Le problème est le suivant: lorsqu’on visite le site depuis un mobile, il est possible de faire bouger le contenu de la page vers la gauche, ce qui dévoile une hideuse colonne grise/verte sur le côté droit. Pourtant, aucun élément ne semble dépasser la largeur du contenu.

L’identification de l’élément causant ce défaut d’affichage n’est pas vraiment une chose aisée, car visuellement, on ne distingue rien qui dépasse.

Vanilla JS à la rescousse

Voici un petit script en Vanilla JS qui permet de trouver l’élément qui dépasse la largeur du viewport de votre page:

/**
 * Identify elements that exceed the viewport width
 * by Matt Biscay
 * https://www.skyminds.net/?p=614036
 */
document.addEventListener("DOMContentLoaded", function() {
  const elements = document.querySelectorAll('body *');
  elements.forEach(element => {
    if (element.offsetWidth > document.documentElement.clientWidth) {
      console.log('Element causing overflow: ', element);
    }
  });
});

CSS: couvrez cet overflow que je ne saurais voir

Une fois votre ou vos éléments identifiés, il ne vous reste plus qu’à cacher son overflow-x :

#element {
  overflow-x: hidden;
}

Rafraîchissez la page. Hop, problème résolu.

wordpress rocketstack

WordPress Rocket Stack : envoyez WordPress sur orbite !

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

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

Hébergement

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

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

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

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

Ubuntu Server

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

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

Installation de la WordPress Rocket Stack

# MySQL
# Latest link is always on the apt page: https://dev.mysql.com/downloads/repo/apt/
wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.23-1_all.deb
dpkg -i mysql-apt-config_0.8.23-1_all.deb

# Packages
apt install software-properties-common tmux curl wget zip unzip git
add-apt-repository ppa:ondrej/php
add-apt-repository ppa:ondrej/nginx-mainline
apt update -y
apt upgrade -y
apt install mysql-server -y # accept all defaults

# PHP 8.0
# Note: the json module is now part of PHP core
apt install php8.0 php8.0-bcmath php8.0-curl php8.0-gmp php8.0-imap php8.0-mbstring php8.0-readline php8.0-xml php8.0-apcu php8.0-cli php8.0-fpm php8.0-igbinary php8.0-intl php8.0-mysql php8.0-redis php8.0-zip php8.0-common php8.0-gd php8.0-imagick php8.0-opcache php8.0-soap -y

# Run installs
apt install nginx -y
apt install fail2ban -y
apt install redis -y

# Get NginX config files
git clone https://github.com/skyminds/wordpress-rocketstack
cp wordpress-rocketstack/nginx/* /etc/nginx/ -R
rm wordpress-rocketstack

DNS : ajout du site sur le serveur

Mon serveur est hébergé chez OVH donc il faut ajouter le domaine aux DNS secondaires du serveur.

Sur l’interface Kimsufi, cela se fait très simplement:

Ajouter le domaine au serveur (dns secondaire)
Ajouter le domaine au serveur (dns secondaire)

Configurer Cloudflare

Si vous utilisez Cloudflare – ce que je vous recommande fortement – et que vous obtenez une erreur 403 ou alors une page “Welcome to NginX” en lieu et place de votre nouveau site, veillez bien à sélectionner la bonne option SSL dans Cloudflare > Example.com > SSL/TLS > Overview : il faut sélectionner Full ou Full (Strict) mais surtout pas “Flexible“:

Choisissez toujours l'option SSL/TLS Full (Strict) chez Cloudflare
Choisissez toujours l’option SSL/TLS Full (Strict) chez Cloudflare

Ensuite, il ne nous reste qu’à faire pointer le CNAME vers l’adresse IP du serveur et d’ajouter le champs TXT qui a été indiqué par OVH dans l’étape précédente:

Ajout de l'enregistrement DNS au format TXT pour valider le DNS secondaire chez OVH
Ajout de l’enregistrement DNS au format TXT pour valider le DNS secondaire chez OVH

Ajout du server block NginX

DOMAIN="example.com"
DOMAINDIR="example"

mkdir -p /home/www/$DOMAINDIR
chown www-data:www-data /home/www/$DOMAINDIR

mkdir -p /home/nginx-cache/$DOMAINDIR
chown -R www-data:www-data /home/nginx-cache/

cp /etc/nginx/sites-available/wprocketstack.conf /etc/nginx/sites-available/$DOMAINDIR.conf

rm /etc/nginx/sites-enabled/default
rm /etc/nginx/sites-available/default

On édite ensuite la configuration:

nano /etc/nginx/sites-available/$DOMAINDIR.conf

Mettez l’adresse du site dans la directive server_name:

server_name example.com

Lire la suite

PHP8

WordPress : tester la compatibilité avec PHP 8

Aujourd’hui, nous allons tester la compatibilité avec PHP 8 de tous les sites WordPress du serveur, en ligne de commande et de manière automatisée.

Fin du support pour PHP 7.4 pour novembre 2022

Le cycle de vie de PHP 7.4 est atteint et il n’y aura plus de mises à jour ni de support à la fin du mois de novembre 2022. Cela signifie qu’il est désormais temps de passer sous PHP 8 pour bénéficier des dernières améliorations techniques de PHP et des mises à jour de sécurité.

Et mieux vaut s’y prendre un peu plus tôt, notamment si vous possédez une boutique WooCommerce pour ne pas être pris au dépourvu en pleine période de fêtes (Black Friday, Noël…).

Tester votre code avec php-parallel-lint

Nous allons créer un nouveau projet composer avec php-parallel-lint qui se chargera de scanner notre code et de remonter toutes les incompatibilités, fonctions obsolètes ou problématiques susceptibles de donner des avertissements ou des erreurs lors du basculement vers PHP 8.

Commençons par installer php-parallel-lint:

composer create-project php-parallel-lint/php-parallel-lint php-parallel-lint --no-dev

# ou avec un user :
# sudo su -l www-data -s /bin/bash -c "composer create-project php-parallel-lint/php-parallel-lint php-parallel-lint --no-dev"

Résultat de la commande:

Creating a "php-parallel-lint/php-parallel-lint" project at "./php-parallel-lint"
Installing php-parallel-lint/php-parallel-lint (v1.3.2)
  - Installing php-parallel-lint/php-parallel-lint (v1.3.2): Extracting archive
Created project in /Users/matt/Downloads/project-ACTAGIS-php8-202208/php-parallel-lint
Loading composer repositories with package information
Updating dependencies
Lock file operations: 4 installs, 0 updates, 0 removals
  - Locking nette/tester (v2.4.2)
  - Locking php-parallel-lint/php-console-color (v1.0.1)
  - Locking php-parallel-lint/php-console-highlighter (v1.0.0)
  - Locking squizlabs/php_codesniffer (3.7.1)
Writing lock file
Installing dependencies from lock file
Nothing to install, update or remove
2 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files

Installons maintenant l’outil qui permet de coloriser le code dans notre console:

composer require --dev php-parallel-lint/php-console-highlighter

Résultat:

Info from https://repo.packagist.org: #StandWithUkraine
Using version ^1.0 for php-parallel-lint/php-console-highlighter
./composer.json has been created
Running composer update php-parallel-lint/php-console-highlighter
Loading composer repositories with package information
Updating dependencies
Lock file operations: 2 installs, 0 updates, 0 removals
  - Locking php-parallel-lint/php-console-color (v1.0.1)
  - Locking php-parallel-lint/php-console-highlighter (v1.0.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 2 installs, 0 updates, 0 removals
  - Downloading php-parallel-lint/php-console-color (v1.0.1)
  - Downloading php-parallel-lint/php-console-highlighter (v1.0.0)
  - Installing php-parallel-lint/php-console-color (v1.0.1): Extracting archive
  - Installing php-parallel-lint/php-console-highlighter (v1.0.0): Extracting archive
Generating autoload files

Scanner le code avec php-parallel-lint

Voici la syntaxe pour scanner votre code:

 ./php-parallel-lint/parallel-lint FOLDER_TO_SCAN -p PHP_VERSION

Lire la suite

WordPress Using WP CLI

wp-cli : importer et exporter les utilisateurs WP

Voici une méthode simple pour exporter tous les utilisateurs d’une base de données WordPress, pour les réimporter sur un autre site, à l’aide de l’excellent wp-cli.

Nous ferons référence à la base de données source en tant que source-db et à la base de données cible en tant que target-db et je supposerai que vous avez accès aux deux instances WordPress via wp-cli.

Étape 1 : exporter les utilisateurs WordPress

Cette étape fonctionnera avec la base de données source-db:

wp db export --tables = $(wp db tables 'wp_*_users') users.sql
  • notez l’astérisque dans le nom de la table – utilisez-le pour éviter de taper le nom exact de la table pour votre base de données WordPress spécifique
  • notez le nom du fichier exporté, users.sql – cela permet d’identifier clairement le contenu de ce fichier.

Étape 2 : exporter la méta utilisateur WordPress

Cette étape fonctionnera avec la base source-db. Comme ci-dessus, notez le caractère générique et le nom de fichier:

wp db export --tables = $(wp db tables 'wp_*_usermeta') usermeta.sql

Étape 3 : sauvegarde facultative des utilisateurs et usermeta

Cette étape fonctionnera avec la base target-db. Il s’agit d’une sauvegarde facultative des utilisateurs et des tables usermeta avant d’importer les nouvelles données:

  • répétez l’étape 1 (mais en travaillant avec target-db)
  • nommez le fichier backup-users.sql
  • répétez l’étape 2 (mais en travaillant avec target-db)
  • nommez le fichier backup-usermeta.sql

Cela nous donne donc:

wp db export --tables = $(wp db tables 'wp_*_users') backup-users.sql
wp db export --tables = $(wp db tables 'wp_*_usermeta') backup-usermeta.sql

Lire la suite

Group photo of all devs at Cloudfest Hackathon 2022

Le Hackathon du CloudFest 2022

Cette année, j’ai eu la chance et le grand honneur d’être invité au CloudFest 2022 pour le hackathon: 3 jours de code sur un projet web en mode open-source pour faire avancer les choses.

Le Cloudfest

Le Cloudfest est une convention de développeurs et d’acteurs du web qui peuvent être extrêmement variés: cela va des hébergeurs web aux plateformes comme Codeable mais aussi avec de gros acteurs comme Airbus, Intel, Automattic, HP, Cpanel, Plesk…

Les conférences sont très variées: intelligence artificielle, business… et il est très facile de rencontrer des gens très connus sur le web pour se faire un réseau.

Le Cloudfest se tient à Rust, en Allemagne, à l’Europa Park.

Le Hackathon

Cette année le hackathon proposait plusieurs projets mais j’ai opté pour travailler sur wp-cli pour ajouter une nouvelle commande qui permettre de sécuriser 80% des attaques contre les instances WordPress, en appliquant simplement les meilleures pratiques de sécurité courantes.

Les devs du Hackathon 2022
Les devs du Hackathon 2022

Concrètement, nous avons identifié les problèmes de sécurité courants et nous avons développé une extension de l’interface de ligne de commande WordPress (wp-cli) pour offrir une alternative sécurisée et facile à utiliser aux plugins de sécurité WordPress généralement non sécurisés.

Avec la simple commande wp secure all, les meilleures pratiques courantes sont appliquées automatiquement à votre instance WordPress, et en moins de 60 secondes, vous attenuez la grande majorité des vecteurs d’attaque WordPress actuels : permissions de fichiers et de dossiers, entêtes de sécurité, bloquer l’accès aux fichiers sensibles…

Lire la suite

WordPress : rediriger la page d'attachement vers l'article auquel les fichiers médias appartiennent photo

WordPress : rediriger la page d’attachement vers l’article parent

WordPress publie par défaut une page d’attachement pour chaque fichier média que vous publiez sur votre site.

En règle générale, un fichier média (image, vidéo, autre) appartient à un article: on attache souvent ce type de fichier lors de la rédaction des articles, pour les insérer dans le corps des billets.

Le problème est donc que WordPress crée gentiment une page dédiée à chaque média publié. Cette page ne contient aucun contenu, à part afficher le média en question, ce qui n’est pas vraiment idéal au point de vue SEO puisque l’on se retrouve avec énormément de pages mais qui ne seront jamais indexées au vu du contenu inexistant. S’il est donc superflu d’avoir ces pages, autant s’en séparer!

C’est là que nous allons tenter d’être malin : pourquoi ne pas rediriger ces pages d’attachement vers l’article auquel ces fichiers media appartiennent?

Jusqu’à très récemment, j’utilisais le module Origin de The SEO Framework, qui fonctionne très bien si le média a été uploadé sur un article. La page d’attachement est alors automatiquement redirigée vers l’article.

Le hic, c’est que si le fichier média a été uploadé directement depuis la page WP Admin > Média, alors nous sommes redirigé vers /wp-admin, ce qui ne fait aucun sens.

Voici donc la solution que j’utilise sur le site:

<?php
/*
Script Name: Redirect attachment page to parent post.
Script URI: https://www.skyminds.net/?p=32314
Description: Redirects attachment to parent post (if it exists), or redirects to the homepage otherwise.
Version: 2.6.0
Author: Matt Biscay
Author URI: https://mattbiscay.com
*/
add_action( 'template_redirect', 'sky_redirect_attachment_to_post' );
function sky_redirect_attachment_to_post(){
  // if not an attchment, bail out early
  if( !is_attachment() ) {
    return;
  }
  // check if parent post is defined
  if( isset( $post ) && isset( $post->post_parent ) && is_numeric( $post->post_parent ) && ( $post->post_parent != 0 ) ) :
    // redirect to parent post
    wp_redirect( esc_url( get_permalink( $post->post_parent ) ) ); exit;
  else: // media has been uploaded through the Media page or is unattached to a specific post
    // redirect to homepage
    wp_redirect( esc_url( home_url( '/' ) ) ); exit;
    // or redirect to the media itself
    // wp_redirect( esc_url( wp_get_attachment_url() ) ); exit;
  endif;
}

Ce code est à copier-coller dans le fichier functions.php de votre thème enfant. Vous pouvez également l’enregistrer en tant que plugin.

Une fois activé, si vous visionnez l’adresse d’une page d’attachement, vous devriez être redirigé sur l’article parent.

Notez que je vous ai mis 2 possibilités pour la redirection lorsque le media n’a pas été attaché à un article: une redirection vers la page d’accueil ou alors vers le fichier média directement.

A vous de choisir ce qui vous correspond le mieux :)

Ajouter un lien avec le nombre d'articles et le total du panier WooCommerce photo

Rendre la page panier WooCommerce réactive

Lors de mon dernier projet WooCommerce, j’ai remarqué que la page panier de WooCommerce n’était pas vraiment réactive sous Safari (iPhone, iOS) : le tableau ne s’empile pas comme il le devrait et toutes les colonnes sont comprimées. Les dernières colonnes sont hors du viewport.

Safari sous iOS (iPhone) semble être le seul concerné – je n’ai pas réussi à reproduire ce comportement sur FireFox, Chrome ou Opera.

Le site en question utilise Astra, qui est vraiment bien éprouvé, ainsi qu’Elementor comme constructeur de page.

Voici comment rendre le tableau du panier WooCommerce réactif, en utilisant quelques lignes de CSS.

Forcer la réactivité du panier WooCommerce

J’ai opté pour une solution propre, en CSS, en ne ciblant que les iPhones puisqu’ils sont les seuls concernés (Safari + résolution d’écran).

Voici donc le code utilisé pour rendre le panier WooCommerce réactif:

/*
Plugin Name: Sky WooCommerce Responsive Cart
Plugin URI: https://mattbiscay.com
Description: Make WooCommerce cart responsive
Version: 1.1
Author: Matt Biscay
Author URI: https://mattbiscay.com
*/

/* responsive cart */
@media only screen and ( max-width: 479px ) {
  
  .short-description, .product_meta, body.woocommerce div.product .woocommerce-tabs, body.woocommerce #content div.product .woocommerce-tabs { display: none; }
  body.woocommerce .images { float: none !important; width: auto !important; margin-bottom: 40px !important; clear: both !important; }
  
  table .product-thumbnail { display: none; }
  
  .woocommerce-page #content div.product form.cart .variations { margin-left: 0; }
  
  table.cart th, #content table.cart th, table.cart td, #content table.cart td, table.cart tr, #content table.cart tr, #content-area table tr, #content-area table td, #content-area table th { padding: .857em 0.287em; }
  
  .woocommerce .woocommerce .col2-set .col-1, .woocommerce-page .col2-set .col-1, .woocommerce .col2-set .col-2, .woocommerce-page .col2-set .col-2 { width: 100% !important; }
  .woocommerce .woocommerce form .form-row, .woocommerce-page form .form-row { width: auto !important; float: none !important; }
  
  #order_review .shop_table { margin-left: 0; }
  
  /* cart: tax on its own line */
  .includes_tax { display: block; }
  
}

/* cart weird bug on Safari: cart table is not collapsing */
/* this corrects the bug on iphones */

@media (max-width: 768px){
  .iphone .woocommerce table.shop_table_responsive tr,
  .iphone .woocommerce-page table.shop_table_responsive tr {
    display: flex;
    flex-direction: column;
    flex-basis: 100%;
    flex: 1;
  }
  
  .woocommerce table.shop_table_responsive tr td::before, .woocommerce-page table.shop_table_responsive tr td::before {
    content: attr(data-title) ' ';
    font-weight: 700;
    float: left;
  }
  
  p.no-shipping-options {
    clear: both;
    margin-top: 3rem;
  }
}

Lire la suite

Créer un site staging pour WordPress sur un sous-domaine photo

Créer un site staging pour WordPress sur un sous-domaine

Le Centre de Kriya Yoga France n’avait pas de site staging, ce site de développement et de test qui permet de tester, développer ou mettre à jour de nouvelles extensions, sans affecter le site principal.

Une des extensions a eu besoin d’être débugguée par ses concepteurs mais pour des raisons de confidentialité, il nous est apparu intéressant et plus sécurisé de donner accès à un site de développement, fraîche copie du site original, pour le débuggage.

Si vous avez besoin de créer un site staging pour votre site WordPress et que votre hébergeur ne le propose pas, voici comment faire.

Étape 1 : créer un sous-domaine au niveau DNS

Nous choisissons la solution la plus simple: servir le site STAGING depuis un sous-domaine. Il suffit de créer un nouvel enregistrement DNS sous la forme:

staging IN A xxx.xxx.xxx.xxx

staging represente le sous-domaine et xxx.xxx.xxx.xxx représente l’adresse IPv4 du serveur.

Étape 2 : créer le server block sous NginX

Le domaine étant déjà actif, j’ai uniquement rajouté ce server block:

### STAGING ###
 server {
 listen              443 ssl http2;
 listen              [::]:443 ssl http2;
 server_name staging.kriyayoga.fr;
 root /home/www/kriyayoga/staging/public_html;
 set $root /home/www/kriyayoga/staging/public_html;
 index index.php index.htm index.html;
 error_log /var/log/nginx/kriyayoga_staging_error.log;
 #SSL
 ssl_certificate        /etc/nginx/ssl/kriyayoga.fr/fullchain.pem;
 ssl_certificate_key    /etc/nginx/ssl/kriyayoga.fr/privkey.pem;
 include snippets/mime-types.conf;
 #Exclusions
 include snippets/exclusions.conf;
 #Security
 include snippets/security.conf;
 #Static Content
 include snippets/static-files.conf;
 #Fastcgi cache rules
 include snippets/fastcgi-cache.conf;
 include snippets/limits.conf;
 include snippets/nginx-cloudflare.conf;
 #Gzip
 include snippets/gzip.conf;
 location / {
 try_files $uri $uri/ /index.php?$args;
 }
 location ~ .php$ {
 try_files $uri =404;
 include snippets/fastcgi-params.conf;
 fastcgi_pass unix:/run/php/php7.4-fpm.sock;
 #Skip cache based on rules in snippets/fastcgi-cache.conf.
 fastcgi_cache_bypass $skip_cache;
 fastcgi_no_cache $skip_cache;
 #Define memory zone for caching. Should match key_zone in fastcgi_cache_path above.
 fastcgi_cache kriyayoga;
 #Define caching time.
 fastcgi_cache_valid 60m;
 #increase timeouts
 fastcgi_read_timeout 6000;
 fastcgi_connect_timeout 6000;
 fastcgi_send_timeout 6000;
 proxy_read_timeout 6000;
 proxy_connect_timeout 6000;
 proxy_send_timeout 6000;
 send_timeout 6000;
 #these lines should be the ones to allow Cloudflare Flexible SSL 
 #to be used so the server does not need to decrypt SSL if you wish
 proxy_set_header X-Forwarded-Host $host;
 proxy_set_header X-Forwarded-Server $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto https;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-NginX-Proxy true;
 }
 #Protect WooCommerce upload folder from being accessed directly.
 #You may want to delete this config if you are using "Redirect Only" method for downloadable products.
 #Place this config towards the end of "server" block in NginX configuration.
 location ~* /wp-content/uploads/woocommerce_uploads/ {
   if ( $upstream_http_x_accel_redirect = "" ) {
     return 403;
     }
     internal;
 }
 }

Testez la nouvelle configuration:

nginx -t

Puis redémarrez NginX:

service nginx reload

Note: il est important de noter que je n’ai pas besoin de créer de certificat SSL puisque mes certificats sont wildcard par défaut. Si ce n’est pas le cas chez vous, pensez à en générer pour votre sous-domaine.

Lire la suite

Nettoyer un site WordPress infecté par un script shell photo 1

Nettoyer un site WordPress infecté par un script shell

Il n’est pas rare de voir des sites WordPress infectés par des scripts shell, qui peuvent exploiter certaines failles du core WordPress, de plugins ou de thèmes.

Ces attaques de WordPress sont courantes et concernent les sites qui n’ont pas été protégés par un antivirus ou un plugin de sécurité comme iThemes Security.

Il peut donc arriver que certains malwares infestent votre site WordPress, de manière automatisée si certaines composantes (core, plugins, themes) ne sont pas mis à jour régulièrement.

La technique détaillée ci-dessous vous permet d’identifier et de supprimer ces fichiers dans vos dossiers WordPress.

Important: avant de commencer, faites une sauvegarde du site: fichiers et base de données.

Étape 1 : suppression des fichiers potentiellement infectés

Sur l’installation en question, ces fichiers n’appartiennent pas à WordPress ou sont infectés. Nous les supprimons à vue:

rm 1index.php index.php db.php del.php wikindex.php

Nous supprimons également les répertoires wp-admin et wp-includes de WordPress car souvent des fichiers malfaisants sont copiés dedans:

rm wp-admin -rf
rm wp-includes -rf

Étape 2 : réinstallation de WordPress

On réinstalle WordPress:

wp core download --force --skip-content --locale=fr_FR --allow-root

Lire la suite

Jethro Tull - Aqualung photo

Local : importer une base de données depuis le shell

Local possède une version d’Adminer dans les options de chaque site qui est très utile puisqu’elle permet d’accéder rapidement à la base de données, ou d’importer une petite base de données.

Par contre, s’il s’agit d’importer une base qui fait plus de 80 Mo, mieux vaut se tourner vers un outil un peu plus robuste: le shell.

Accéder au shell depuis Local

Et cela tombe bien : Local possède son propre shell, accessible sur simple clic-droit sur le nom du site sur lequel vous souhaitez ouvrir une fenêtre de terminal:

local open site shell new 1280x787

Voici la marche à suivre : Démarrez votre site > sélectionnez le nom du site > clic-droit > Open Site Shell

Importer une base de données dans un site Local

Lorsque j’ai besoin de répliquer un site rapidement, je copie la base données dans le répertoire app du site Local en question.

Pour mon site de test (skyminds-2020 ), le chemin sur ma machine est /Users/matt/Local Sites/skyminds2020/app . C’est dans ce dossier que je place le fichier SQL à importer.

Ensuite, dans le shell Local, il suffit de faire un simple import SQL dans la base qui, par défaut, s’appelle local (et ce, pour tous vos sites Local, bien qu’elles soient toutes indépendantes).

L’utilisateur est root et le mot de passe root également, ce qui est plutôt pratique.

Le shell est par défaut sous app/public donc on remonte d’un cran dans l’arborescence pour pointer vers notre fichier (qui se trouve dans /app ).

Voilà ce que cela nous donne:

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

Résultat:

mysql: [Warning] Using a password on the command line interface can be insecure.
bash-3.2$

L’importation de la base de données SQL ne prend que quelques secondes, alors que cela se plante allégrement lorsque l’on utilise Adminer.

A utiliser sans modération, cela ne vaut vraiment pas le coup de s’embêter avec une interface graphique (ou à placer le fichier dans le répertoire d’adminer comme il l’indique sur la page d’importation).

WordPress: retirer l'option de supprimer les plugins dans l'interface d'administration photo

WordPress: retirer l’option de supprimer les extensions dans l’interface d’administration

C’est assez rare comme demande mais je me suis exécuté: comment faire pour retirer le lien qui permet de supprimer les plugins désactivés dans l’interface d’administration, même si l’on est administrateur ?

Et bien c’est assez simple, il suffit de filtrer le tableau des liens. Voici deux exemples simple pour mettre cela en place.

Retirer le lien de suppression pour toutes les extensions

Voici le code qui vous permet de retirer le lien “Supprimer” qui se trouve en dessous de chaque extension sur la page Extensions:

<?php
/*
Plugin Name: Disable Plugin Deletion
Plugin URI: https://www.skyminds.net/?p=32830
Description: Disable all plugins' deletion links on the plugins page.
Version: 1.0
Author: Matt Biscay
Author URI: https://mattbiscay.com
*/
add_filter( 'plugin_action_links', 'sky_disable_plugin_deletion', 10, 4 );
function sky_disable_plugin_deletion( $actions, $plugin_file, $plugin_data, $context ) {
  // Remove delete link for all installed plugins         
  unset( $actions['delete'] );     
  return $actions;
} 

Retirer le lien de suppression pour des extensions spécifiques

Voici le code qui vous permet de retirer le lien “Supprimer” qui se trouve en dessous des extensions dont vous spécifiez le chemin (dossier et nom du fichier de l’extension à charger) sur la page Extensions:

<?php
 /*
 Plugin Name: Disable Plugin Deletion
 Plugin URI: https://www.skyminds.net/?p=32830
 Description: Disable all plugins' deletion links on the plugins page.
 Version: 1.0
 Author: Matt Biscay
 Author URI: https://mattbiscay.com
 */
 add_filter( 'plugin_action_links', 'sky_disable_plugin_deletion_selected', 10, 4 );
 function sky_disable_plugin_deletion_selected( $actions, $plugin_file, $plugin_data, $context ) {
   // Remove delete link for specific plugins
   if ( array_key_exists( 'delete', $actions ) && in_array( $plugin_file,
   [
     'akismet/akismet.php',
     'redirection/redirection.php',
   ]
   ) ) {
     unset( $actions['delete'] );
   }
   return $actions;
 }

Dans ce dernier snippet, pensez à modifier le nom du répertoire et celui du plugin de manière à ce qu’ils coïncident avec les plugins qui ne doivent pas être supprimés.

A l’origine, c’était pour un de mes clients pour éviter que ses collaborateurs ne suppriment des plugins par inadvertance.

Je m’en sers également sous LocalWP pour éviter de supprimer un plugin en cours de développement – on ne sait jamais!