Jenkins : installation sur Centos, Debian ou Ubuntu

jenkins install

Jenkins est un outil open source d’intégration continue. C’est sans doute le plus connu de sa catégorie. Il est écrit en JAVA et embarque son propre serveur web. L’intégration continue apporte de nombreux avantages comme l’automatisation de taches ou encore la possibilité de délivrer une version fonctionnelle de votre application régulièrement.

Jenkins (anciennement appelé Hudson), dont la réputation n’est plus à faire, s’est formé tout un éco-système et dispose à ce jour plus de 1000 Plugins. Nous allons voir comment l’installer sur les distributions linux les plus standard avec Nginx en reverse proxy.

Centos / RedHat

1. Mise en place du repository

wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key

2. Installation

yum install jenkins

3. Activation du service

Pour s’assurer que le service soit démarrer au lancement du serveur :

systemctl enable jenkins

On démarre le service :

systemctl start jenkins

Debian / Ubuntu

1. Mise en place du repository

wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'

2. Installation

sudo apt-get update
sudo apt-get install jenkins

3. Activation du service

Pour s’assurer que le service soit démarrer au lancement du serveur :

systemctl enable jenkins

On démarre le service :

systemctl start jenkins

Mise en place du reverse proxy avec Nginx

Nous allons créer un nouveau virtual host pour notre Jenkins.

 vi /etc/nginx/conf.d/jenkins.conf

et y mettre ceci :

upstream app_server {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {
    listen 80;
    server_name jenkins.cloud-devops.fr;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        proxy_pass http://app_server;
        }
}

On relance le service nginx :

systemctl restart nginx

et on peut accéder à Jenkins via l’url http://jenkins.cloud-devops.fr/

Notre Jenkins est maintenant installé. Nous verrons par la suite comment le paramétrer pour

WordPress : Restreindre l’accès de l’admin par ip

restreindre admin wordpress

Si vous avez une adresse IP statique, chez vous ou au bureau, ou peut-être votre propre VPN, vous avez la chance de pouvoir augmenter votre sécurité. La technique consiste à restreindre les accès à l’admin de wordpress par une ou plusieurs ip.

Nous allons voir comment le mettre en place sur Nginx.

1. Création d’un bloc map

Nous allons créer un bloc map pour y inclure la liste des adresses ip autorisées.

map $remote_addr $allowed_ip {

1.2.3.4 1;
1:: 1;
5.6.7.8 1;

default 0;
}

On assigne la valeur 1 aux adresses ip que l’on veut autoriser et 0 pour le reste.

2. Modification du bloc server

Nous allons modifier notre « bloc server » pour y inclure nos conditions. Nginx ne supporte pas les opérateurs logiques dans les bloc if , nous allons donc devoir contourner le problème en mettant plusieurs if.

server {
... 
set $check ''; #initialisation de la variable  

if ( $allowed_ip = 0 ) {
  set $check "A";
}

if ( $request_uri ~ ^/wp-(login\.php|admin/) )  {
  set $check "${check}B";
}

if ( $check = "AB" ) {
return 403;
}
...
}

Donc si l’adresse n’est pas dans la liste du bloc map « check = A » et si l’uri correspond à /wp-login.php ou wp-admin/ « check = AB ». Si nous avons $check = AB nous retournons une 403 ( forbidden ).

Nginx : Installer la dernière version / mainline

Nginx

Chaque nouvelle version de Nginx apporte son lot de nouveauté. Par exemple la version 1.9.7 apporte le support du protocole http2. Vous pouvez trouver les différents changements ainsi que les corrections de bug sur le changelog.

J’avais l’habitude d’utiliser la version « stable » de Nginx sur mes serveurs, mais je voulais vraiment offrir le support de http2. J’ai donc décidé de mettre à jour ma version pour passer sur la version « mainline« . Attention si vous utilisez des modules dit de « third-party » ils peuvent devenir incompatible ou apporter des nouveaux bugs.

Nous allons voir une méthode pour passer sur cette version tout en conservant le gestionnaire de paquets de ma distribution linux (apt, yum).

1. Installation de la version mainline sur Centos/Redhat

Nous allons créer le fichier /etc/yum.repos.d/nginx.repo avec ce contenu :

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/OS/OSRELEASE/$basearch/
gpgcheck=0
enabled=1

Il faut modifier OS par rhel ou centos suivant votre distribution et OSRELEASE par 5,6 ou 7 suivant votre version.
Ensuite il faut mettre à jour le paquet Nginx :

 yum update

2. Installation de la version mainline sur Debian/Ubuntu

Pour Debian/Ubuntu nous devons identifier le repository à l’aide d’une clé. Cela va aussi permettre d’eliminer tous les messages d’alertes.

curl http://nginx.org/keys/nginx_signing.key | apt-key add -

On ajoute ensuite le repository. Il faut ajouter ces lignes à la fin du fichier /etc/apt/sources.list.

Pour Debian :

deb http://nginx.org/packages/mainline/debian/ codename nginx
deb-src http://nginx.org/packages/mainline/debian/ codename nginx

Il faut remplacer « codename » par wheezy pour la version 7.x ou jessie pour la version 8.x.

Pour Ubuntu :

deb http://nginx.org/packages/mainline/ubuntu/ codename nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ codename nginx

On remplace « codename » par precise pour la version 12.04, trusty pour la version 14.04, vivid pour la version 15.04 et wily pour la version 15.10

Il ne reste plus qu’à mettre à jour :

apt-get update
apt-get install nginx

3. Test de la version

nginx -v
nginx version: nginx/1.9.10

On peut bien sur, garder ce numéro de version pour nous et ne pas l’afficher dans nos headers http.

Nginx: cacher la version dans les headers http

nginx-logo

Par défaut, Nginx affiche sa version dans les headers http. On peut pour des raisons de veilles versions ou de vulnérabilités vouloir cacher cette version.

Par défaut nous avons ceci :

$ curl -I https://www.cloud-devops.fr/
HTTP/1.1 200 OK
Server: nginx/1.9.10
Date: Fri, 05 Feb 2016 20:57:50 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding

Si l’on veut ne plus afficher la version 1.9.10, il faut ajouter dans le bloc « http » l’option :

server_tokens off;

Après un restart de Nginx, nous obtenons ceci :

$ curl -I https://www.cloud-devops.fr/
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 05 Feb 2016 21:04:09 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding

Voilà ça fonctionne ! Notre version de Nginx est maintenant masquée aux utlisateurs.

Nginx : Activer la compression GZIP

gzip_compress

C’est toujours dans une approche d’optimization de notre serveur ainsi que de l’expérience utilisateur que nous allons aborder la mise en place de la compression Gzip des requêtes http sur Nginx. Nous avons déjà vu comment mettre en cache nos fichiers statiques pour rendre notre site plus rapide.  Ici nous allons voir comment compresser nos requêtes.

Vous devez avoir le module ngx_http_gzip_module de compiler sur votre nginx. C’est généralement le cas par défaut.

Les paramètres gzip sont à mettre dans le bloc « http » généralement ce bloc se trouve dans le fichier nginx.conf.

On y ajoute les paramètres suivants :

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 4 32k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/x-font-ttf application/javascript font/eot font/opentype image/svg+xml image/x-icon text/plain;

Et l’on redémarre nginx.
Les lignes les plus importantes sont gzip on; et gzip_types.

Quelques explications :

  • gzip on : active la compression
  • gzip_types : permet de spécifier quel type de fichiers doit être compressé.
  • gzip_vary : permet d’ajouter dans le header « Vary: Accept-Encoding” ce qui permet au proxy de stocker une version compressée et non compressée du fichier.
  • gzip_proxied : permet de compresser les requêtes venant de proxies.
  • gzip_comp_level : determine le niveau de compression. Plus la compression sera élevée plus la requête sera petite mais le client perdra un peu plus de temps à la décompresser.
  • gzip_buffers 4 32k : le premier chiffre (4) correspond au nombre et le deuxième à la taille du buffer utilisés pour compresser la requête.
  • gzip_http_version : permet de spécifier la version http qui doit être compressée.

On peut surcharger nos paramètres en le mettant dans le bloc « server ».
Par exemple si l’on met gzip off dans un bloc « server » cela désactivera la compression gzip sur notre domaine.

Test

Nous allons tester à l’aide de curl si nos paramètres sont bien pris en compte.

$ curl -I --header "Accept-Encoding: gzip" https://www.cloud-devops.fr/
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 05 Feb 2016 14:32:20 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Content-Encoding: gzip

Si vous voyez « Vary: Accept-Encoding » et « Content-Encoding: gzip » c’est que votre serveur est bien paramétré.

Pour plus d’infos sur le module gzip voici le documentation nginx officiel gzip 

Nginx: mise en cache des fichiers statiques

nginx

Il est très important de bien configurer votre serveur nginx pour servir correctement les fichiers statiques (images, javascript, css, texte …).
Cela vous permet d’économiser la bande passante de votre serveur et également d’améliorer l’expérience utilisateur. L’utilisateur aura l’impression que votre site se charge plus vite.
L’utilisateur n’aura pas besoin de télécharger de nouveau ce fichier js ou l’image car son navigateur l’aura déjà dans son propre cache.

La mise en cache des fichiers statiques, coté du navigateur, se fait à l’aide des headers renvoyés par le serveur.
Il faut être sur d’avoir le module ngx_http_headers_module compilé avec nginx. C’est le cas par défaut.
Il y a plusieurs paramètres à mettre en place pour configurer correctement nos headers.

Prenons l’exemple suivant :

location ~* \.(png|jpg|jpeg|gif|ico|woff|otf|ttf)$ {
  root /var/www/static/;
  access_log off;
  log_not_found off;
}

1. expires

Ce paramètre permet de contrôler la durée de mise en cache. Il est par défaut à off. La directive expires permet d’agir sur les headers http Expires et Cache-Control
Ce paramètre peut prendre différents paramètres epoch,max,une durée, off ou une heure.

  • off: désactive les headers http Expires et Cache-Control
  • epoch: met le header Expires à la date du 1 January, 1970 00:00:01 GMT.
  • max: met le header Expires à la date du Thu, 31 Dec 2037 23:55:55 GMT et le Cache-Control au maximum c’est à dire à 10ans
  • une durée: met le cache à une durée relatif par rapport à l’accès au fichier. Par exemple expires 10d; signifie que votre navigateur conservera cette version de fichier pendant 10 jours.
  • une heure: met une heure à partir de laquelle de fichier expire dans la journée. Il doit être préfixé par un @. Par exemple expires @12:10; signifie que votre fichier va expiré à 12h10

Dans la plupart des cas un expires max; ou expires 1y; sera bien efficace. Dans notre exemple cela donne :

location ~* \.(png|jpg|jpeg|gif|ico|woff|otf|ttf)$ {
  root /var/www/static/;
  access_log off;
  log_not_found off;
  expires 1y;
}

2. add_header

Cette directive prend des options libres c’est à nous de renseigner ce que l’on veut. Nos paramètres doivent correspondre aux standard du protocol http pour être interprété par l’ensemble des navigateurs et proxies.

Nous allons intervenir sur le header Cache-Control. Avec le paramètre expires nous sommes déjà intervenu sur le cache-control pour mettre max-age=31536000. Il faut maintenant décrire la façon dont cela doit être conserver. Plusieurs options sont à notre disposition :

  • no-cache : cela indique que la prochaine requête sur la même url devra être validé par le serveur pour confirmer qu’elle n’a pas changé.
  • no-store : interdit de stocker la réponse. On ne l’utilise pas pour les fichiers statiques mais généralement sur des urls qui contiennent des données confidentielles (mon compte par exemple).
  • private: ne sera mis en cache que par les navigateurs et jamais par les serveurs proxies.
  • public: peut être stocké par n’importe qui. Ce paramètre est implicite si le paramètre max-age est déjà en place.

Nous allons donc de notre coté mettre le paramètre add_header Cache-Control « public »; qui va permettre de mettre nos fichiers en cache pour tout le monde et de les stocker. Dans notre exemple cela donne :

location ~* \.(png|jpg|jpeg|gif|ico|woff|otf|ttf)$ {
  root /var/www/static/;
  access_log off;
  log_not_found off;
  expires 1y;
  add_header Cache-Control "public"; 
}

3. Test

A l’aide d’un curl nous allons tester que cela fonctionne.

$ curl -I https://www.cloud-devops.fr/wp-content/uploads/2016/02/log_nginx.jpg
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 05 Feb 2016 12:07:27 GMT
Content-Type: image/jpeg
Content-Length: 181406
Last-Modified: Thu, 04 Feb 2016 21:31:59 GMT
Connection: keep-alive
ETag: "56b3c34f-2c49e"
Expires: Sat, 04 Feb 2017 12:07:27 GMT
Cache-Control: max-age=31536000
Pragma: public
Cache-Control: public
Vary: Accept-Encoding
Accept-Ranges: bytes

Nous avons le header Cache-Control à public, le Cache-control max-age à 365 jours et un Expires à la date du Sat, 04 Feb 2017 12:07:27 GMT. Tout fonctionne parfaitement !

Nginx: exclure un user agent de nos logs

log nginx

Nous avons vu précédemment que nous pouvions exclure des logs nginx une url spécifique et même une adresse ip.

Nous allons voir ici, comment exclure de nos logs un user agent spécifique. Par exemple nous ne voulons pas avoir dans nos logs le user agent de notre monitoring « mymonitoringBot » ou encore celui de « Googlebot ».

Nous allons créer un bloc « map » pour y mettre nos règles :

map $http_user_agent $log_useragent {
  ~Googlebot 0;
  ~mymonitoringBot 0;
  default 1;
}

On assigne la valeur 0 aux user agent Googlebot et mymonitoringBot. Toutes les autres user agent auront la valeur 1.
Il suffit ensuite de mettre cette condition dans notre bloc « server« .

server {
   ...
access_log /var/log/nginx/access.log main if=$log_ua;

}

N’entrerons dans les logs que la valeur 1 qui correspond à la valeur par défaut. Notre fichier access.log ne contiendra pas les user agent Googlebot et mymonitoringBot.

Nginx : exclure une ip des logs

log nginx

Pour des raisons pratiques, on peut vouloir exclure de nos logs nginx une ou plusieurs adresses ip.

Nginx déconseille d’utiliser le « if » dans la configuration de nginx et le considère comme le mal !

1. Nise en place d’un bloc map

Nous allons créer un bloc « map » pour y mettre la liste des adresses ips.  Ce bloc « map »  doit être créer en dehors du bloc « server« .

Vous pouvez avoir envie d’exclure le localhost ou encore l’ip de votre monitoring.

map $remote_addr $log_ip {
     "127.0.0.1" 0;
     "1.2.3.4" 0;
    default 1;
}

On assigne la valeur 0 aux adresses ip 127.0.0.1 et 1.2.3.4. Toutes les autres adresses ip auront la valeur 1.

2. Mise en place du filtre

Il suffit ensuite de mettre dans le bloc « server » notre condition sur nos logs.

server {
     ...

     access_log /var/log/nginx/access.log main if=$log_ip;
}

Les adresses ip 127.0.0.1 et 1.2.3.4 n’apparaitront plus dans le log access.log.

Nginx: exclure une url des logs

nginx exclure url

On peut vouloir exclure des urls spécifiques dans nos logs. Cela facilitera les futurs recherches par exemple.

Dans la config de nginx, on utilise très souvent le bloc « location »  pour définir les paramètres d’un type d’url, par exemple pour servir les fichiers statiques.

Vous avez sans doute ce type de configuration :

location ~* \.(png|jpg|jpeg|gif|ico|js|css)$ {
   root /var/www/static/;
   expires max; 
}

Pour que les urls de nos images, js ou css n’apparaissent pas dans nos logs, il suffit d’ajouter l’option « access_log off; »
Comme ceci :

location ~* \.(png|jpg|jpeg|gif|ico|js|css)$ {
   root /var/www/static/;
   expires max; 
   access_log off;
   log_not_found off;
}

Vous pouvez noter que j’ai également ajouter l’option « log_not_found off; » qui permet de ne pas écrire dans le fichier « error_log » les fichiers manquants.

Configurer http2 sur nginx

nginx http2

Depuis sa version 1.9.5, nginx apporte le support du protocole http version 2. Si vous utilisiez déjà le module SPDY, il est remplacé par le module HTTP/2.

Pour savoir si vous supportez ce protocole :

# nginx -V

Vous devez avoir une version supérieur à 1.9.5 et avoir dans les options de compilations –with-http_v2_module. Si vous n’avez pas cette option, il faudra mettre à jour votre version de nginx.

Il faut savoir que l’implémentation de HTTP/2 requière du HTTPS.

1. Configuration :

Pour ajouter la prise en charge de HTTP/2 dans la configuration de nginx, il suffit de remplacer dans le bloc server { }

listen 443 ssl;

par :

listen 443 ssl http2;

On recharge ensuite la config :

# service nginx restart

2. Test :

Pour vérifier que cela fonctionne correctement je vous invite à faire le test sur :

https://tools.keycdn.com/http2-test