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