Guide pour la création de site Web

Ce guide à plusieurs objectifs :

  • Simplifier le déploiement depuis le serveur de test vers le serveur de production
  • Une meilleure intégration du site dans l'OS (respectant la FHS)
  • Simplifier la sauvegarde des données
  • Diminuer les risques de sécurités
  • Améliorer l'extensibilité
  • Permettre de facilement améliorer les performances

Introduction

Généralement lors de la création d'un site Web, tous les fichiers se retrouve à la racine du serveur web (DocumentRoot). Que ce soit les fichiers générés par des scripts pour un court instant, des fichiers tampons, des fichiers chargés par les utilisateurs du site ou encore des fichier HTML statique.

Cela peut poser des problèmes, comme un fichier charger par les utilisateurs passant au travers d'un interpréteur (PHP, par exemple), les sauvegardes copiant maladroitement les fichiers tampons, … C'est donc le but de ce guide : comment garder une séparation des données en diminuant les contraintes de celle-ci.

Identifications des problèmes

Différents problèmes peuvent être listés :

  • Les fichiers chargés lors de l'utilisation doivent être stockés au-dehors de la racine du serveur Web et distribué soit par l'application, soit par un autre serveur (plus léger) ayant des droits en lecture et sans interpréteur.
  • Les fichiers tampons ou les fichiers de “spool” doivent être stockés sur un espace du système de fichier prévu à cet effet.
  • Les bibliothèques de fonctions doivent être stockées au-dehors de la racine du serveur Web.
  • Les fichiers de configurations doivent être stockés au-dehors de la racine du serveur Web.
  • Les modèles de fichiers doivent être stockés au-dehors de la racine du serveur Web.
  • Excepté les fichiers tampons, de “spool” et chargés, le processus serveur doit avoir un accès en lecture seule uniquement.
  • Le processus serveur doit avoir un accès en exécution uniquement sur les scripts, les “cgi” et les binaires.

Communiquer avec le serveur

Le premier problème pour le développeur est de savoir où l'administrateur système a prévu de l'espace pour tous ces fichiers.

Une des solutions serait qu'ils se décident sur un lieu pour chaque type de fichier ”[…] tu mets tes fichiers tampons dans /var/cache/ton_projet […]”, mais si l'administrateur système désire changer la structure il ne pourra pas trop déplacer ces fichiers (le développeur ayant pris soin de bien codé en dur les chemins à travers tout le code).

Une solution plus élégante est de passer par les variables d'environnement. Elles sont facilement configurables pour chaque site Web, elles sont facilement accessible par le développeur et toujours disponible. Le développeur et l'administrateur système ont juste besoin de s'entendre sur le nom de ces variables :

  • WEB_APP_CONFIG_DIR : chemin vers le répertoire des fichiers de configuration [RO].
  • WEB_APP_TEMPLATE_DIR : chemin vers le répertoire des modèles de fichier [RO].
  • WEB_APP_CACHE_DIR : chemin vers le répertoire des fichiers tampons [RW].
  • WEB_APP_SPOOL_DIR : chemin vers le répertoire des fichiers de “spool” [RW].
  • WEB_APP_DATA_DIR : chemin vers le répertoire des données chargées par les utilisateurs [RW].

C'est un bon début, mais l'administrateur système devra définir cinq variables pour chaque site Web, ce qui va lui prendre du temps et augmente le risque d'erreurs (au bout de la deuxième il est déjà très fatigué).

Il suffit de laisser l'administrateur système donner un nom de code au site Web :

  • WEB_APP_CODENAME : nom de code donné par l'administrateur (seulement utiliser cette variable, ne jamais afficher à l'écran, il est des choses qu'il ne vaut mieux pas savoir)

Ce nom de code va définir le sous-répertoire que le développeur pourra utiliser (exemple, $WEB_APP_CACHE_DIR/$WEB_APP_CODENAME)

Tenter de créer le sous-répertoire

L'administrateur système est un type sympathique, mais il n'aura certainement pas créer le sous-répertoire. Pour les répertoires en lecture-seule, le développeur ne peut pas le créer, mais pour les fichiers en lecture-écriture, l'application doit tenter des le créer s'il n'existe pas.

Le code

On a parlé des données, mais pas encore du code.

Le code va être déposer naturellement à la racine du serveur Web. C'est l'administrateur système qui va s'occuper du déploiement, mais c'est au développeur de gérer la séparation entre le code dynamique, le code statique (HTML) et les cgi-bin.

Pour rester simple, le répertoire racine contient le contenu dynamique. Les fichiers statiques et les cgi-bin sont des sous-répertoires (afin de présenter des URL absolue comme /static/css/design ou /cgi-bin/query.cgi).

L'administrateur système sait qu'il peut déplacer ces deux répertoires du moment qu'il conserve les URL identiques. Il sait aussi que le fichier d'index est dans le contenu dynamique.

Dans le cas où le fichier d'index est un fichier statique (index.html), c'est le seul fichier pouvant outrepasser la séparation des données et donc être dans le contenu dynamique.

Les outils

Si des outils sont nécessaire, pour du nettoyage avant la mise en production, un répertoire tools devrait être créer. Un README et/ou INSTALL devrait aussi être présent.

Exemple

projet-RELEASE1
 |
 +- content  # Contenu dynamique
 |   |
 |   +- cgi-bin
 |   +- static
 |   +- .htaccess
 |   +- index.php
 |
 +- tools
 |   |
 |   +- clean.sh
 |   +- Makefile
 |
 +- ro
 |   |
 |   +- config
 |   +- lib
 |   +- templates
 |
 +- rw
 |   |
 |   +- cache
 |   +- data
 |   +- spool
 |
 +- .htaccess
 +- README
 +- INSTALL

Quand l'administrateur obtient le projet, il sait :

  • Qu'il doit lire le README.
  • content est le répertoire racine.
  • tools contient des scripts pour la mise en production, décrit dans le README. Un Makefile est une excellente option, l'administrateur a peut-être déjà un pour ce projet et a juste besoin d'inclure un appel vers celui-ci.
  • ro contient les données devant être copiées à la mise en production.
  • rw ne contient rien (ou des données entrées par erreur dans le gestionnaire de version) et sera supprimé.

À propos des bibliothèques

Les bibliothèques sont prévues pour être utilisées par plusieurs applications et donc devrait être un projet séparé. Si les bibliothèques fournies ne sont justes que des “fonctions pour l'application”, elles doivent être mise dans un sous-répertoire du contenu. Logiquement lib devrait être vide et le fichier README devrait contenir la liste des autres projets devant être obtenus et déposé dans l'espace des bibliothèques du serveur.

Si votre projet va être distribué à des personnes sans compétence technique spécifique, les bonnes bibliothèques devrait être incluses lors de la génération de l'archive pour la distribution.

.htaccess

Deux fichiers .htaccess sont visibles.

Le premier est à la racine du projet (et non du serveur) pour permettre aux utilisateurs sans compétence technique spécifique de dé-archiver le projet directement dans le répertoire racine du serveur et avoir un système fonctionnel. Le contenu de ce fichier ressemblerait à ça :

<Files README>
Deny from all
<Files>
<Files INSTALL>
Deny from all
<Files>

RewriteRule ^/(.*) /content/$1 [L]

Le second contient tous ce que désire le développeur. C'est à l'administrateur système de savoir s'il veut activer le gestion du .htaccess sur le serveur Web ou s'il veut inclure ce fichier directement dans la configuration du serveur.

... dans tools

Sans surprise, tools doit contenir ce fichier .htaccess :

Deny from all

Exemple (code)

Un exemple de comment cette structure pourrait être gérée. L'exemple utilise le moteur de modèle smarty :

/* index.php */
 
if(($codename=getenv('WEB_APP_CODENAME'))!==false) {
   if(!empty($codename)) {
      define('WEB_APP_CODENAME', $codename);
   }
}
if(!defined('WEB_APP_CODENAME')) {
   define('WEB_APP_CODENAME', 'project');
}
 
$S = new Smarty();
 
$S->compile_dir = dirname(__FILE__) . '/../rw/cache/compile';
$S->cache_dir = dirname(__FILE__) . '/../rw/cache/cache';
$S->config_dir = dirname(__FILE__) . '/../ro/config';
$S->template_dir = dirname(__FILE__) . '/../ro/template/';
 
$S->plugins_dir[] = dirname(__FILE__) . 'smarty/plugins';
 
if(($cache_dir=getenv('WEB_APP_CACHE_DIR'))!==false) {
   if(file_exists($cache_dir) && 
         is_dir($cache_dir) && 
         is_writable($cache_dir)) {
      $cache_dir .= '/' . WEB_APP_CODENAME;
      if(!file_exists($cache_dir)) {
         mkdir($cache_dir);
      }
      if(file_exists($cache_dir) && 
            is_dir($cache_dir) && 
            is_writable($cache_dir)) {
         mkdir($cache_dir . '/cache');
         mkdir($cache_dir . '/compile');
         if(file_exists($cache_dir . '/cache') &&
               is_dir($cache_dir . '/cache') &&
               is_writable($cache_dir . '/cache')) {
           $S->cache_dir = $cache_dir . '/cache';
         }
         if(file_exists($cache_dir . '/compile') &&
               is_dir($cache_dir . '/compile') &&
               is_writable($cache_dir . '/compile')) {
            $S->compile_dir = $cache_dir . '/compile';
         }
      }
   }
}
 
if(($config_dir=getenv('WEB_APP_CONFIG_DIR'))!==false) {
   if(file_exists($config_dir) &&
         is_dir($config_dir) &&
         is_readable($config_dir) &&
         !is_writable($config_dir)) {
      $config_dir .= '/' . WEB_APP_CODENAME;
      if(file_exists($config_dir) &&
            is_dir($config_dir) &&
            is_readable($config_dir) &&
            !is_writable($config_dir)) {
         $S->config_dir($config_dir);
      }
   }
}
 
if(($template_dir=getenv('WEB_APP_TEMPLATE_DIR'))!==false) {
   if(file_exists($template_dir) &&
         is_dir($template_dir) &&
         is_readable($template_dir) &&
         !is_writable($template_dir)) {
      $template_dir .= '/' . WEB_APP_CODENAME;
      if(file_exists($template_dir) &&
            is_dir($template_dir) &&
            is_readable($template_dir) &&
            !is_writable($template_dir)) {
         $S->template_dir = $template_dir;
      }
   }
}

Comme le serveur de test n'a pas forcément la même structure, il faut pouvoir utiliser les répertoires internes et cela permet aux personnes sans compétence technique spécifique de mettre en service à l'aide d'un ou deux droits.

Inclure des bibliothèques

Les bibliothèques devraient être accessible grâce au chemin d'inclusion automatique, mais pas forcément. Une solution pourrait être :

/* index.php */
 
@include('myLib/myLib.php');
if(!function_exists('my_lib_function')) {
   require(dirname(__FILE__) . '/../ro/lib/myLib/myLib.php');
}

Structure sur le serveur de production

Les données servies par le serveur web devraient être localisées dans /srv. Comme c'est du web, elles devraient être dans /srv/www ou /srv/web. Une structure simple pourrait être :

/srv/web
  |
  +- projects
  |   |
  |   +- httpd-includes
  |   |   |
  |   |   +- project1.conf -> /srv/web/projects/project1/httpd-project1.conf
  |   |   +- project2.conf -> /srv/web/projects/project2/httpd-project2.conf
  |   |
  |   +- project1
  |   |   |
  |   |   +- tools # Outils de l'administrateur
  |   |   +- RELEASE1 # Projet respectant la structure définie
  |   |   +- httpd-project1.conf
  |   |
  |   +- project2
  |       |
  |       +- tools
  |       +- RELEASE1
  |       +- RELEASE2
  |       +- RELEASE3
  |       +- httpd-project2.conf
  |
  +- webroot # juste root ressemble trop à /root
      |
      +- project1 -> /srv/web/projects/project1/RELEASE1/content/
      +- project2 -> /srv/web/projects/project2/RELEASE3/content/

Avec la simple modification d'un lien symbolique (ou physique), tout le site passe en production et il est toujours possible de faire des testes de pré-production.

Spool, cache, ...

Spool

Le répertoire pour les fichiers de “spool” devrait être dans /var/local/spool :

/var/local/spool/
  |
  +- webapps
      |
      +- project1
      +- project2

Cache

Les fichiers tampons dans /var/local/cache

/var/local/cache/
  |
  +- webapps
      |
      +- project1
      +- project2

Configurations

Les fichiers de configuration dans /usr/local/etc

/usr/local/etc
  |
  +- webapps
      |
      +- project1
      +- project2

Templates

Les modèles de fichier dans /usr/local/share/misc

/usr/local/share/misc
  |
  +- webapps
      |
      +- project1
      +- project2

Data

Les données chargées dans /srv/web

/srv/web/data
  |
  +- project1
  +- project2

Bibliothèques

Les langage de développement devrait déjà avoir un répertoire prévu à cet effet, la même hiérarchie est reproduite dans /usr/local

Conclusion

Cette structure veut simplifier le travail, si ce n'est pas le cas ne l'utilisez pas.

Si vous avez uniquement des données statiques, la même structure peut être conservée, il y aura juste moins de répertoire à entrer en action.

 
website/guideline/fr.txt · Last modified: 2010/08/05 11:03 by tchetch
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Debian Driven by DokuWiki