Logo Khaganat
Traductions de cette page?:

Cette page est noté comme étant en brouillon. Votre participation pour l'améliorer est requise !

Ceci est une ancienne révision du document !


Nginx

Installation

Pour Debian, installez les paquets de base :

sudo apt install nginx-full

Pour PHP :

sudo apt install php php-gd php-imagick php-curl php-intl php-fpm

Ces paquets installent les autres dépendances utiles.

Pour php, les modules complémentaires sont ceux qui nous sont utiles sur Khaganat, mais suivant les CMS ils peuvent être inutiles, ou avoir besoin d'être complétés.

Aperçu de Nginx

La configuration de Nginx et des sites se trouve dans /etc/nginx.

nginx
├── conf.d
├── custom
│   ├── acme_http-01.conf
│   ├── apache_compat.conf
│   ├── headers.conf
│   ├── headers_nocsp.conf
│   └── tls.conf
├── fastcgi.conf
├── fastcgi_params
├── koi-utf
├── koi-win
├── mime.types
├── modules-available
├── modules-enabled
│   ├── 50-mod-http-auth-pam.conf -> /usr/share/nginx/modules-available/mod-http-auth-pam.conf
│   ├── 50-mod-http-dav-ext.conf -> /usr/share/nginx/modules-available/mod-http-dav-ext.conf
│   ├── 50-mod-http-echo.conf -> /usr/share/nginx/modules-available/mod-http-echo.conf
│   ├── 50-mod-http-geoip.conf -> /usr/share/nginx/modules-available/mod-http-geoip.conf
│   ├── 50-mod-http-image-filter.conf -> /usr/share/nginx/modules-available/mod-http-image-filter.conf
│   ├── 50-mod-http-subs-filter.conf -> /usr/share/nginx/modules-available/mod-http-subs-filter.conf
│   ├── 50-mod-http-upstream-fair.conf -> /usr/share/nginx/modules-available/mod-http-upstream-fair.conf
│   ├── 50-mod-http-xslt-filter.conf -> /usr/share/nginx/modules-available/mod-http-xslt-filter.conf
│   ├── 50-mod-mail.conf -> /usr/share/nginx/modules-available/mod-mail.conf
│   └── 50-mod-stream.conf -> /usr/share/nginx/modules-available/mod-stream.conf
├── nginx.conf
├── proxy_params
├── scgi_params
├── sites-available
│   ├── default
│   └── test.conf
├── sites-enabled
│   └── test.conf -> ../sites-available/test.conf
├── snippets
│   ├── fastcgi-php.conf
│   └── snakeoil.conf
├── uwsgi_params
└── win-utf

Le fichier principal de configuration est nginx.conf, il fixe les paramètres globaux et il y a donc assez peu de raisons de le modifier. Tout comme pour Apache, le dossier sites-enabled contient les liens symboliques vers les fichiers de configuration des différents sites situés dans sites-available. Ces autres fichiers de configuration sont inclus depuis le fichier de configuration principal nginx.conf grâce à la directive include.

La spécificité de Khaganat est la création du dossier custom qui contient des fichiers de configuration destinés à être inclus au cas par cas dans la configuration de chaque site. Les fichiers de custom sont les suivants :

  • acme_http-01.conf : Configuration nécessaire pour la résolution du challenge HTTP-01 lors d'un renouvellement de certificat initié par ACMEd.
  • apache_compat.conf : Interdit l'accès aux fichiers dont le nom commence par .ht (notamment .htaccess et .htpasswd) afin de ne pas faire fuiter les éventuels résidus de fichiers de configuration spécifiques à Apache.
  • headers.conf : Ajoute tous les headers HTTP classiques dont un site a normalement besoin. :!: Attention, ceci inclut des CSP très sévères.
  • headers_nocsp.conf : Identique à headers.conf mais n'inclut aucune CSP afin de laisser la libre configuration de ces dernières.
  • tls.conf : Configuration TLS.

Ajouter un domaine ou sous-domaine

Créez un fichier de configuration pour votre nom de domaine dans /etc/nginx/sites-available/monsite.conf.

Un exemple de fichier est disponible dans /etc/nginx/sites-available/default. Copiez-le, adaptez-le, puis enregistrez-le avec un nom compréhensible.

Vous pouvez vérifier que vous n'avez pas fait d'erreur de syntaxe avec la commande suivante :

nginx -t

Ou vous pouvez voir la configuration lue par nginx (en plus de la tester) avec cette commande :

nginx -T | less

Activez ensuite le site en créant un lien symbolique dans /etc/nginx/sites-enabled/ :

cd /etc/nginx/sites-enabled/
sudo ln -s ../sites-available/monsite.conf

Puis dites à nginx de prendre en compte la nouvelle configuration en le redémarrant :

sudo service nginx restart

Rediriger les sous-domaines non existant vers une adresse précise

Créez un fichier de configuration redirigeant tout ce qui ne matche pas :

# En cas d'erreur de sous-domaine, renvoie sur example.org.
server {
    listen 10.0.0.10:80 default_server;
    listen 10.0.0.10:443 ssl default_server;
    # Toutes requêtes non définie par ailleurs
    server_name _;
    include snippets/snakeoil.conf;
        access_log off;
        error_log  off;
    return 301 https://example.org/404.html;
}

Le snippets snakeoil ici est pour le https, c'est un certificat autosigné, c'est mieux que “rien”, mais ça fera des erreurs dans les navigateurs des visiteuses.

SSL Passthrogh sur proxy Nginx

Cette partie est vraiment en brouillon mais si je ne note pas mes tests à mesure, je ne vais pas m'y retrouver. — zatalyz 2025/02/11 08:28

Un proxy est un outil qui peut faire beaucoup de choses, ou très peu. Dans notre cas, l'utilité principale est qu'en ayant une seule ipv4, on containerise les diverses applications histoire de limiter les dégâts si un des logiciels est troué. Donc tout arrive sur le serveur dédié, les flux sur les ports 80 et 443 sont redirigés vers le container du proxy, qui suivant les noms de domaine demandés renvoie vers un des containers ou un autre.

Il est assez simple de gérer les certificats ssl au niveau du proxy, mais cela a pour conséquence que le trafic entre le proxy et les containers passe “en clair”. Une attaque MITM à ce stade ne fais pas vraiment partie de notre modèle de menace, cependant certains CMS fonctionnent mal s'ils ne sont pas en https. Pour contourner ce problème, on peut donc dire au proxy de rediriger le flux mais sans s'occuper de ssl : il ne va rien déchiffrer et laisse ça au “backend”. Cela passe par l'usage de “stream” plutôt que de “http” au niveau de nginx.

Notre configuration des sites avec “stream” sera dans un dossier différent de “sites-avalaible/sites-enabled” : même logique mais avec “stream”.

sudo mkdir -p /etc/nginx/stream-enabled sudo mkdir -p /etc/nginx/stream-avalaible

Il faut aussi modifier le fichier “nginx.conf” afin que ce dossier soit lu et pris en compte en ajoutant la ligne suivante :

include /etc/nginx/stream-enabled/*.conf;

Exemple dans le fichier :

/etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
include /etc/nginx/stream-enabled/*.conf;
 
events {
        worker_connections 768;
        # multi_accept on;
}
 
http {
[...]

Il n'y a pas forcément besoin de faire un fichier de configuration par domaine, puisqu'on liste surtout “quel domaine redirige “où”. Par contre, on va avoir deux fichiers à faire, afin que les ports 80 et 443 du serveur puissent aussi servir des sites web en direct.

Pourquoi ? Parce que. On pourrait rediriger tout 443 vers le stream, ça marcherait, mais je fais mes tests avec des sites en prod à côté donc je vais éviter de tout casser. Par ailleurs, cette méthode va permettre d'avoir une page web sur le proxy pour les noms de domaine qui n'existent pas, et ça c'est assez classe.

Primo on fait un fichier dans la partie “site” pour renvoyer… vers un “stream”

/etc/nginx/sites-avalaible/tostream.conf
server {
    listen 80;
    # Liste de tous les domaines
    server_name domain1.org domain2.org;  
 
    # Rediriger toutes les requêtes HTTP vers HTTPS
    return 301 https://$host$request_uri;
}
 
# Configuration HTTPS pour tous les domaines
server {
    listen 443;
    server_name domain1.org domain2.org;  
 
    location / {
        # Configurer la connexion au backend via stream (port 1443)
        proxy_pass https://127.0.0.1:1443;  
        # Transmettre l'IP des visiteuses
        proxy_set_header X-Forwarded-For $proxy_protocol_addr;  
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

Et à présent le stream :

/etc/nginx/stream-avalaible/domaine.conf
stream {
    map $ssl_preread_server_name $backend {
    # Cette partie liste les domaines et "où" ça renvoie
        domain1.org 10.0.0.30:443;
        domain2.org 10.0.0.32:443;
    # Default est utile : si pas de domaines, ça renvoie là.
        default     10.0.0.30:443; 
    }
 
    server {
        listen 10.0.0.10:1443 proxy_protocol;
        proxy_pass $backend;
        ssl_preread on;
    }
}

On valide tout ça :

sudo ln -s /etc/nginx/sites-avalaible/tostream.conf /etc/nginx/sites-enabled/tostream.conf
sudo ln -s /etc/nginx/stream-avalaible/domaine.conf /etc/nginx/stream-enabled/domaine.conf
sudo nginx -t
sudo systemctl restart nginx

Cela demandera aussi ce genre de config côté apache/backend :

a2enmod remoteip

<VirtualHost *:443>
    RemoteIPProxyProtocol On
    RemoteIPHeader X-Forwarded-For
    RemoteIPInternalProxy 10.0.0.10

    # Autres directives...
</VirtualHost>

Exemple de configuration

Notre proxy

Exemple simple:

server {
    listen      ip.du.pro.xy:80;
    server_name exemple.khaganat.net;
 
    location / {
        proxy_pass http://IP.DE.LA.VMàjoindre;
        include /etc/nginx/proxy.conf;
    }
 
}

Création d'une conf commune :

nano /etc/nginx/proxy.conf
proxy_redirect          off;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size    50m;
client_body_buffer_size 512k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;

Exemple plus complet:

server {
    listen      192.168.20.10:80;
    server_name "exemple.khagouille.net";
 
    return      301 https://exemple.khaganat.net$request_uri;
}
 
server {
    listen      192.168.20.10:443 ssl http2;
    server_name "exemple.khaganat.net";
 
    ssl_certificate /etc/letsencrypt/live/exemple.khaganat.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exemple.khaganat.net/privkey.pem;
 
    location / {
        proxy_set_header    Host $host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;
        proxy_buffering     off;
        proxy_pass          http://IP.DE.LA.VMàjoindre/;
    }
}

D'autres exemples (ajouter des liens vers les autres tuto) :

Demander un certificat let'encrypt

Voir sur_nginx.

Sources et liens

En cas de besoin, la documentation d'nginx est très complète. La lecture des articles suivants est recommandée :

CC Attribution-Share Alike 4.0 International Driven by DokuWiki
fr/nginx.1739474941.txt.gz · Dernière modification : de zatalyz

Licences Mentions légales Accueil du site Contact Inclusion