false

⏳  Temps de lecture :  ~4 min.
✍🏻  Édité le :  mardi 13 octobre 2020
Niveau : 🧩 🧩 🧩 🧩 🧩

Bien qu'il soit beaucoup plus aisé de mettre en route un site pré-compilé en production qu'un site dynamique, il y a tout de même une série de réglages à effectuer sur le serveur HTTP de mon choix, Nginx.

Cette compilation de directives glanées à droite à gauche peut s'appliquer sur d'autres rendus de sites HTML que Gatsby, à l'instar d'Eleventy ou autre. Vous constaterez que ce sont des principes généraux, pour la plupart.

Notez qu'elle évoluera car la partie sécurité concerne surtout les vieux navigateurs, le Content Security Policy (ou CSP) étant amené à supplanter ou compléter la plupart des anciennes directives.

Configuration de départ

On commence par une configuration nginx standard d'un dossier contenant les fichiers statiques générés par Gatsby. Le tout chiffré et servi via HTTP/2.

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  
  server_name juliancataldo.com www.juliancataldo.com;
  
  location / {
    root /srv/repos/juliancataldo.com/production;
  }
}
📋  copier

Notez que ma configuration SSL (utilisant des clefs Let's encrypt) est gérée séparemment, dans un snippet global pour mes différents sites.

Router la page 404 de Gatsby

Par défault, nginx ne résoudra pas le chemin des pages introuvables généré par Gatsby.
Pour remédiez à cela, ajoutez cette directive au bloc server :

# Indique l'emplacement pour les pages introuvables.
error_page 404 /404.html;
📋  copier

Économiser de la bande-passante grace à gzip

Les ressources textuelles (html, css, svg, json..) profitent particulièrement de la compression gzip à la volée supportée par nginx. Veillez à bien spécifier les types MIME concernés.
Attention, les images (jpeg, png…) ou les polices de caractères (woff), déjà compressées ne profitent pas de cette optimisation, c'est même l'inverse.

gzip on;
# Une valeur élevée sollicite plus fortement le processeur.
gzip_comp_level 5;
gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/rss+xml text/javascript image/x-icon image/bmp image/svg+xml application/json;
📋  copier

Il n'est pas rare d'observer des gains de 50% à 75% du poids initial.

GZIP is working

Définir l'encodage du texte dans les entêtes HTTP

Bien que l'encodage UTF-8 puisse être spécifié dans la balise racine d'un document html en modifiant le template de base de Gatsby, /src/html.js de cette façon :

{/* ./src/html.js */}<html lang="fr" charSet="utf-8">
📋  copier

Il est toutefois préconisé de le faire aussi en amont, au sein même des entêtes HTTP.
Pour cela, ajouter ces directives dans le bloc server :

# Définit l'encodage en amont du chargement du document.
charset utf-8;
charset_types text/html text/plain application/json;
📋  copier

Désormais, le navigateur sait interpréter le jeu de caractères avant même de recevoir le moindre octet du document HTML demandé. En revanche je ne saurais vous dire si les gains sont mesurables…

Établir une politique de mise en cache basique

Facteur considéré comme « vital » par les métriques de Google, la mise en cache des fichiers statiques évite à vos visiteurs de les re-télecharger à chaque visite.
Par défaut, les navigateurs ne conservent ces fichiers que durant la session de navigation.

À noter : Il faut définir le même chemin racine que dans le bloc location /.

Ajouter le bloc suivant dans le bloc parent, server :

location ~* \.(js|json|css|png|jpg|jpeg|gif|ico|woff2)$ {
  # En jours.
  expires 365d;
  
  # Autoriser la mise en cache aux intermédiaires (proxys, navigateur…),
  # interdire son altération.
  add_header Cache-Control "public, no-transform";
  
  # Reprendre la racine dans le bloc 'location' principal.
  root /srv/repos/juliancataldo.com/production;
}
📋  copier

Sécuriser les requêtes HTTP, les rudiments

1. Chiffrement

Tout d'abord, pour se prémunir de certaines attaques de l'« homme au milieu » 🦹‍♂️ (ou man-in-the-middle), forçons l'utilisation du SSL par les clients.

# Forcer le HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
📋  copier

2. Iframes

Ensuite on décide de n'accepter les urls dans les iframes que si elles proviennent de la même origine que votre site (donc pas de problème pour un chargement d'un vidéo YouTube par ex.), ceci afin d'éviter le détournement de clicks (click-jacking).

# Bloquer les urls dans les iframes qui n'ont pas la même
# origine que la page. Prévient le détournement de clicks.
add_header X-Frame-Options SAMEORIGIN always;
📋  copier

3. Scripts

Bloquer le chargement de la page si une attaque de script croisés (cross-site-scripting) est detectée.

# Bloque le chargement en cas de détection d'attaque XSS.
add_header X-XSS-Protection "1; mode=block";
📋  copier

4. Types MIME

Forcer une définition stricte des types MIME pour éviter le reniflage (sniffing).

# Empêcher le reniflage des types MIME.
add_header X-Content-Type-Options nosniff;
📋  copier

L'ensemble de ces 4 directives est à ajouter au bloc parent, server.

Utiliser les politiques de sécurité du contenu (à venir)

Comme dit au début de l'article, une mise-à-jour sera apportée pour parler des entêtes plus modernes, les Content Security Policy (ou CSP).

Configuration finale

Voici le fichier de configuration nginx final reprenant toutes les directives pré-citées :

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  
  server_name juliancataldo.com www.juliancataldo.com;
  
  gzip on;
  # Une valeur élevée sollicite plus fortement le processeur.
  gzip_comp_level 5;
  gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/rss+xml text/javascript image/x-icon image/bmp image/svg+xml application/json;
  
  # Définit l'encodage en amont du chargement du document.
  charset utf-8;
  charset_types text/html text/plain application/json;
  
  # Forcer le HTTPS
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  
  # Bloquer les urls dans les iframes qui n'ont pas la même
  # origine que la page. Prévient le détournement de clicks.
  add_header X-Frame-Options SAMEORIGIN always;
  
  # Bloque le chargement en cas de détection d'attaque XSS.
  add_header X-XSS-Protection "1; mode=block";
  
  # Empêcher le reniflage des types MIME.
  add_header X-Content-Type-Options nosniff;
  
  location / {
    root /srv/repos/juliancataldo.com/production;
  }
  
  location ~* \.(js|json|css|png|jpg|jpeg|gif|ico|woff2)$ {
    # En jours.
    expires 365d;
  
    # Autoriser la mise en cache aux intermédiaires,
    # interdire son altération.
    add_header Cache-Control "public, no-transform";
  
    # Reprendre la racine dans le bloc 'location' principal.
    root /srv/repos/juliancataldo.com/production;
  }
  
  # Indique l'emplacement pour les pages introuvables.
  error_page 404 /404.html;
}
📋  copier

Vous pouvez maintenant profiter sur votre site des gains de performances et de sécurité qu'apportent ces quelques optimisations pour Nginx 😄.

Résultats GTMetrix
👈  INDEX