Créer un serveur d'applications Web - 1ère partie

Comment exploiter des applications PHP et Node.js sur le même serveur ?

15 janvier 2017

Introduction

Nous entamons une série d'articles concernant la création et l'exploitation d'un serveur d'applications Web.

Les contraintes :

Les droits administrateurs sur le serveur sont nécessaires pour effectuer les différentes opérations.

Ce 1er article traitera uniquement de la configuration du reverse proxy et de la configuration du serveur pour des applications en Node.js et PHP.

Les logiciels serveur et applications Web

Le serveur Web utilise les logiciels Open Source ci-dessous :

Les applications Web sont :

L'outil d'analyse des statistiques Web est Piwik 3.

Configurer un reverse proxy

Utilité du reverse proxy

Configurer le serveur Web en reverse proxy permet de distribuer les requêtes HTTP aux différentes applications Web suivant l'URL de la requête.

Sans reverse proxy l'utilisateur devrait indiquer le port d'accès dans l'URL pour accéder à l'application correspondante.

Sans reverse proxy :

Avec reverse proxy :

Le fonctionnement est résumé par les schémas ci-dessous :

Reverse proxy schéma

Configurer Nginx en reverse proxy

Pour les applications Web exploitant les WebSockets, le serveur reverse proxy doit être configuré afin de laisser passer les entêtes Upgrade et Connection du protocole HTTP.

Dans notre cas, le fichier de configuration Nginx /etc/nginx/sites-available/projects créé contient :

map $http_upgrade $connection_upgrade {
    default upgrade;        # Si l'entête HTTP Upgrade contient une valeur, la valeur 'upgrade' est affectée à la variable $connection_upgrade
    '' close;               # Si l'entête HTTP Upgrade est vide, la valeur 'close' est affectée à la variable $connection_upgrade
}

# liste l'ensemble des applications Web utilisant leur propre port 
upstream websocket {
    server localhost:8010;  # l'application node.js Chat écoute sur le port 8010
    server localhost:8011;  # l'application node.js ToDo écoute sur le port 8011
}

#exemple avec l'application ToDo

location /todo/ { # Si l'URL commence par /todo/ , appliquer les règles ci-dessous
    rewrite /todo/(.*) /$1 break;                       # Transformer l'URL en éliminant /todo/, par exemple /todo/index.html devient /index.html  
    proxy_pass http://localhost:8011;                   # Translater les requêtes vers http://localhost:8011
    proxy_http_version 1.1;                             # Utiliser le protocole HTTP 1.1
    proxy_set_header Upgrade $http_upgrade;             # Affecter à l'entête HTTP Upgrade la valeur de la variable $http_upgrade
    proxy_set_header Connection $connection_upgrade;    # Affecter à l'entête HTTP Connection la valeur de la varialbe $connection_upgrade
}

Configurer l'application Web Node.js

Node.js est conçu pour directement inclure un serveur Web (Nginx ou Apache ne sont pas nécessaire pour faire fonctionner une application Web en Node.js).

Rendre exécutable

Ajouter l'entête ci-dessous au fichier principal app.js de l'application pour qu'il soit exécuter par Node.js :

#!/usr/bin/env node

Modifier les permissions d'accès à l'aide de chmod pour rendre app.js exécutable :

chmod +x app.js

Configurer en tant que daemon/service

Un daemon/service est une application qui s'exécute en arrière-plan.

Dans le cas de l'application ToDo, un fichier gltodo.service est créé dans le répertoire /etc/systemd/system et contient :

[Unit]
Description=GL-ToDo
After=network.target

[Service]
ExecStart=/home/projects/nodejs/GL-ToDo/app.js
Restart=always
User=projects
Group=projects
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/home/projects/nodejs/GL-ToDo

[Install]
WantedBy=multi-user.target

Un lien symbolique vers gltodo.service est créé dans le répertoire /etc/systemd/system/multi-user.target.wants pour que le daemon/service démarre automatiquement au boot du serveur :

root@scw:/etc/systemd/system/multi-user.target.wants# ln -s ../glchat.service .

Pour prendre en compte la nouvelle configuration :

systemctl daemon-reload

Pour démarrer le service :

systemctl start gltodo

Pour vérifier le bon fonctionnement du service :

service gltodo status

Pour consulter les logs de l'application en temps réel :

journalctl --follow -u gltodo

Configurer la connexion WebSockets côté client

Le framework Express.js utilisé dans nos applications intègre socket.io pour gérer les connexions WebSockets.

Dans le cas de notre application ToDo accessible depuis l'URL http://projects.glicer.com/todo/,
socket.io tente une connexion sur http://projects.glicer.com/socket.io au lieu de http://projects.glicer.com/todo/socket.io.

Pour y remédier les options de connexions du client sont modifiées :

var serverHost = window.location.protocol + "//" + window.location.host;
var socketOptions = {};
if (window.location.pathname !== "/") {
    socketOptions = { path: window.location.pathname + '/socket.io'};
}
var socket = io.connect(serverHost, socketOptions);

Configurer l'application Web PHP

FastCGI Process Manager

PHP est conçu pour fonctionner derrière un serveur Web comme Nginx ou Apache.

Le daemon/service conçu pour communiquer avec le serveur Web et exécuter les scripts PHP doit être installé :

apt-get install php7.0-fpm

Pour vérifier son bon fonctionnement :

service php7.0-fpm status

Cela affiche par exemple :

● php7.0-fpm.service - The PHP 7.0 FastCGI Process Manager
   Loaded: loaded (/lib/systemd/system/php7.0-fpm.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2016-11-29 16:35:35 UTC; 2 weeks 2 days ago
 Main PID: 3237 (php-fpm7.0)
   Status: "Processes active: 0, idle: 2, Requests: 4, slow: 0, Traffic: 0req/sec"
   CGroup: /system.slice/php7.0-fpm.service
           ├─3237 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)                      
           ├─3240 php-fpm: pool www                                                            
           └─3241 php-fpm: pool www                                                     

Configurer Nginx

Le fichier de configuration /etc/nginx/sites-available/projects est modifié :

location ~ \.php$ {                                                 # Si la requête URL demande un fichier avec l'extension .php, exécuter les règles ci-dessous
    include snippets/fastcgi-php.conf;                              # Inclure et appliquer les règles du fichier snippets/fastcgi-php.conf
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;                     # Transférer la requête au fichier réseau /run/php/php7.0-fpm.sock
    fastcgi_param  PHP_VALUE  "include_path=/home/projects/php";    # Créer et affecter la variable PHP_VALUE qui sera accessible par le script PHP
    fastcgi_param  CUSTOM  "custom";                                # Créer et affecter la variable CUSTOM qui sera accessible par le script PHP
}

La variable CUSTOM est accessible depuis les scripts PHP :

echo $_SERVER['CUSTOM'];

Prochain article

Le prochain article traitera de la création de la machine Docker correspondant à la configuration du serveur.