Faire son CDN perso avec nginx
Dans ce billet je vais expliquer comment j'ai mis en place un petit CDN (Content Delivery Network) pour servir du contenu statique (images/css/javascript).
Le problème :
- Avec une connexion 800kbs envoyer des images ça peut prendre du temps.
- Sur les sites dynamiques, l'application web envoie souvent des cookies valides pour le domaine en question. Du coup le client envoie son cookie quand il demande le contenu statique du site dynamique, c'est une perte de temps.
La solution :
- Mettre le contenu statique sur un domaine propre.
- Plusieurs serveurs peuvent servir ce contenu statique, ainsi le client peut faire des requêtes sur plusieurs serveurs à la fois.
Les moyens que j'ai :
- Un serveur à Toulouse qui contient les applications dynamiques et le contenu statique (la source), servi par de multiples jails FreeBSD avec un nginx en reverse proxy. aldo.philpep.org
- Un serveur chez lost-oasis à Marseille, qui fait uniquement du MX et DNS secondaire. d.philpep.org
L'idée
L'idée est dont de servir le contenu statique des sites suivant par mes deux serveurs, sur un domaine sans cookie :
- blog.philpep.org : c'est ici, un blog en python.
- wmfs.info et projects.philpep.org : redmine en ruby.
- l'oujevipo : un joomla en php.
- cerf de grésigne : un dotclear en php.
- Le reste n'a pas besoin d'utiliser le cdn (petit sites internes ou sans visiteurs)
Step one: static.philpep.org
J'ai configuré le domaine avec nginx, pour qu'il serve le contenu statique sur static.philpep.org/$host/$uri
Par exemple http://static.philpep.org/blog.philpep.org/static/ouverta/style.css doit servir http://blog.philpep.org/static/ouverta/style.css.
Pour ça je me suis pas cassé la tête, dans /usr/local/data j'ai des liens symboliques vers le virtual root de chaque virtual host (les dossier étant des points de montage pour les jails FreeBSD qui servent le contenu dynamique)
(phil@aldo.philpep.org ~) % ls -l /usr/local/data/ total 26 drwxr-xr-x 3 root wheel 212 Oct 14 16:40 awstats drwxr-xr-x 5 root wheel 5 Sep 12 02:33 banach lrwxr-xr-x 1 root wheel 23 Oct 14 16:41 blog.philpep.org -> cantor/blog.philpep.org drwxr-xr-x 7 root wheel 8 Sep 28 15:00 bolzano drwxr-xr-x 5 root wheel 5 Oct 14 16:36 cantor lrwxr-xr-x 1 root wheel 25 Oct 14 16:40 cerf-gresigne.org -> bolzano/cerf-gresigne.org lrwxr-xr-x 1 root wheel 21 Oct 14 16:40 dl.philpep.org -> banach/dl.philpep.org lrwxr-xr-x 1 root wheel 19 Oct 14 16:40 dl.wmfs.info -> banach/dl.wmfs.info drwxr-xr-x 3 root wheel 4 Oct 14 16:36 fourier lrwxr-xr-x 1 root wheel 19 Oct 14 16:41 oujevipo.fr -> bolzano/oujevipo.fr lrwxr-xr-x 1 root wheel 18 Oct 14 16:40 philpep.org -> banach/philpep.org lrwxr-xr-x 1 root wheel 22 Oct 14 17:09 projects.philpep.org -> fourier/redmine/public lrwxr-xr-x 1 root wheel 21 Oct 14 16:41 sica.vaour.net -> cantor/sica.vaour.net lrwxr-xr-x 1 root wheel 7 Oct 14 16:40 stats.philpep.org -> awstats lrwxr-xr-x 1 root wheel 27 Oct 14 16:41 webmail.philpep.org -> bolzano/webmail.philpep.org lrwxr-xr-x 1 root wheel 22 Oct 14 17:09 wmfs.info -> fourier/redmine/public
Et la conf nginx qui va avec :
server {
listen 80;
server_name static.philpep.org;
location ~* \.(ico|png|jpg|jpeg|gif|css|js)$ {
root /usr/local/data/;
expires 10y; # 10 ans
add_header Cache-Control public;
}
}
Un petit coup de bind pour créer static.philpep.org et ça marche.
Step two: configurer les applications
C'est la partie la plus difficile. Suivant comment est codée l'application ça peut être très long à faire.
- Pour le blog c'est fait maison et j'avais prévu le coup.
- Pour redmine facile aussi grâce à au framework rails : il faut mettre
ActionController::Base.asset_host = "static.philpep.org/projects.philpep.org"dansconfig/environments/production.rb - Pour dotclear il y a des options dans
about:config, le problème c'est les plugins qui ne l'utilisent pas. - Pour joomla c'est l'horreur ! J'ai du mettre un preg_replace avec une regexp horrible pour faire du remplacement sur toute la chaine retournée par php.
Step three: nginx cache sur d.philpep.org
Il faut configurer nginx pour faire du proxy cache de static.philpep.org, en gros si le contenu demandé n'est pas dans le cache nginx demande au serveur source aldo.philpep.org, il met en cache et le renvoie au client.
http {
proxy_cache_path "/usr/local/www/cache/static" levels=1:1:2 keys_zone=STATIC:1000m inactive=1y max_size=1g;
# Cache pendant 1 an, avec une taille inférieure à 1G.
upstream aldo {
server 82.229.137.130:80;
}
server {
listen 80;
server_name static.philpep.org;
location ~* \.(ico|png|jpg|jpeg|gif|css|js)$ {
proxy_pass http://aldo;
proxy_set_header Host $host;
proxy_cache_key "$request_uri";
proxy_cache STATIC;
}
}
}
Step four : DNS
static IN A 82.229.137.130 ; aldo.philpep.org static IN A 212.85.155.53 ; d.philpep.org
Et après ?
- Regardez votre cache se remplir, et les sites qui sont plus rapides à charger.
- Configurez nginx pour qu'il fasse de la compression gzip sur le css et le javascript.
- Regardez comme la configuration du cache est simple, on peut facilement rajouter un noeud dans le cdn.


0