lindev.fr

Aller au contenu | Aller au menu | Aller à la recherche

mercredi, décembre 28 2016

HAProxy LetsEncrypt et Varnish en front .. rien que ça

L'objectif final

Avoir l'ensemble de ses sites accessibles en https, avec des certificats letsencrypt ( gratuits et surtout renouvelés automatiquement ) et un serveur de cache ( varnish ) pour augmenter la capacité de charge ( bref optimiser les perfs des sites ) pour enfin passer le relais au backend ( Apache, Nginx .. peu importe ).

network_diagram_user_haproxy_varnish_apache.png

le hic

Il y en a toujours un ... et pas des moindres cette fois, varnish ne gère pas l'https !

La solution - TLS Termination Proxy

L'utilisation d'un proxy ( HAProxy ) pour gérer les transactions Https, puis relayer en clair les requêtes vers varnish qui à son tour si nécessaire va relayer les requêtes au(x) serveur(s) ( Apache/Nginx/... )

Plusieurs avantages à cette solution ( Terminaison SSL ), soulager les serveurs finaux ( Apache/Nginx ... ) de la gestion du SSL et surtout pour nous admins, nous simplifier la tâche pour ce qui est de la gestion des certificats.

Dans ce billet

Dans ce billet, je ne vais parler que de HAProxy et letsencrypt pour commencer, varnish étant un assez gros morceau, il fera l'objet d'un second billet.

Mise en place de la situation

Vous pouvez utiliser un seul et même serveur pour héberger l'ensemble de ces services ... mais franchement ça ne devrait jamais être le cas ! Donc pour ce billet nous allons partir du principe que nous possédons 2 serveurs .

Le premier pour héberger HAProxy et Varnish ( 10.0.0.1 ) et le second pour héberger le serveur HTTP ( 10.0.0.2 )

Les deux serveurs sont sous Debian 8 (Jessie).

Serveur HAProxy

Commençons par Installer HAProxy ( plus quelque trucs utils dans ce "tuto" ) ... qui se fait simplement par

apt install haproxy bc vim 

Commençons par copier le fichier de configuration par defaut

cd /etc/haproxy/
cp haproxy.cfg haproxy.cfg.orig


Maintenant nous pouvons éditer le fichier /etc/haproxy/haproxy.cfg

vim /etc/haproxy/haproxy.cfg

Remplacer tout le contenu par :

global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin
        stats timeout 30s
        user haproxy
        group haproxy
        daemon

        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private

        # Default ciphers to use on SSL-enabled listening sockets.
        # For more information, see ciphers(1SSL). This list is from:
        #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
        ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
        ssl-default-bind-options no-sslv3

        maxconn 2048
        tune.ssl.default-dh-param 2048

defaults
        #log    global
        log     /dev/log local0
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http

        option forwardfor
        option http-server-close


#################################

frontend www-http
        bind *:80
        mode http

        #option httpclose
        option forwardfor
        option httplog
        option dontlognull

        reqadd X-Forwarded-Proto:\ http
        default_backend www-backend


frontend www-https
        bind *:443 ssl crt /etc/haproxy/certs/
        mode http
        reqadd X-Forwarded-Proto:\ https

        #option httpclose
        option forwardfor
        option httplog
        option dontlognull

        acl letsencrypt-acl path_beg /.well-known/acme-challenge/
        use_backend letsencrypt-backend if letsencrypt-acl

        default_backend www-backend


backend www-backend

        #option httpclose
        option forwardfor

        http-request set-header X-Forwarder-Port %[dst_port]
        redirect scheme https if !{ ssl_fc }
        server www-1 10.0.0.2:80 check

backend letsencrypt-backend
        server letsencrypt 127.0.0.1:54321


listen stats *:1936
        stats enable
        stats uri /
        stats hide-version
        stats auth username:password

Comme vous l'avez certainement remarqué, nous allons chercher les certificats dans le répertoire /etc/haproxy/certs/ qui n'éxiste pas encore.
Créons le

sudo mkdir /etc/haproxy/certs
sudo chmod -R go-rwx /etc/haproxy/certs

Voilà pour HAProxy, nous verrons ensuite dans l'interface de statistics si tout est ok .

Letsencrypt et certbot

Pour la génération des certificats, nous allons utiliser l'outil certbot .
Pour l'installer nous allons devoir activer ( si ce n'est déjà fait ) le dépôt BlackPorts de Debian

sudo echo 'deb http://ftp.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/blackports.list
apt update

On install certbot depuis ce dépôt

apt-get install certbot -t jessie-backports

Afin d'initialiser letsencrypt, nous allons le lancer une première fois

certbot certonly

Celà ne va pas aboutir, c'est normal, c'est juste pour qu'il crée les répertoires de base.

Celà ne vous a pas échappé, le port 80 est déjà utilisé par HAProxy, et ne peu donc être utilisé par Letsencrypt pour générer ou renouveler un certificat.
L'idée de couper HAProxy le temps de cette action est inconcevable, nous allons simplement utiliser un autre port. ( ici : 54321 )

Pour ne pas avoir à le spécifier à chaque commande, nous allons mettre en place un petit fichier de configuration pour définir quelques paramètres qui ne changent pas . ( ce qui va nous permettre de raccourcir nos lignes de commandes plus tard ).

sudo cd /etc/letsencrypt/ && vim cli.ini

Voici le contenu

# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Certbot with
# "--help" to learn more about the available options.

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
email = admin@your.net

# Uncomment to use a text interface instead of ncurses
text = True

standalone-supported-challenges = http-01

Afin de tester l'ensemble de notre configuration, nous allons générer notre premier certificat ( manuellement ) .
Imaginons que le domaine soit "lindev.fr" :

sudo certbot certonly --standalone --http-01-port 54321 -d lindev.fr -d www.lindev.fr
sudo cat /etc/letsencrypt/live/lindev.fr/fullchain.pem /etc/letsencrypt/live/lindev.fr/privkey.pem > /etc/haproxy/certs/lindev.fr.pem
sudo service haproxy restart

Bien entendu, il faut que le nom de domaine "lindev.fr" et "www.lindev.fr" pointent sur l'ip de mon serveur ( HAProxy ).

HAProxy est maintenant prêt . Je suppose que le backend ( Nginx ou Apache ) est déjà configuré avec un vhost écoutant sur le port 80 pour le domaine "lindev.fr et www.lindev.fr".

Et voilà le résultat. Capture_d_e_cran_2017-01-03_a__21.15.37.png

Renouvellement automatique

Nous allons maintenant faire en sorte que les certificats LetsEncrypt se régénèrent automatiquement avant expiration et ce tant qu'à faire sans intervention nécessaire d'une admin sys sur le serveur HAProxy.

Le script

Pour celà j'ai concocter un petit script batch générique qui fait très bien le travail.

sudo mkdir /root/scripts & cd /root/scripts
vim /root/scripts/renew_all.sh

Le voici

#!/bin/bash

#Configuration variables
certbot_bin="/usr/bin/certbot"
haproxy_pem_path="/etc/haproxy/certs"
http_01_port='54321'
exp_limit=30

#Then, create domain.pem containing fullchain et privkey for haproxy
for domainconf in $(ls /etc/letsencrypt/renewal/); do
        domain=${domainconf%.conf}

        cert_file="${haproxy_pem_path}/${domain}.pem"
        exp=$(date -d "`openssl x509 -in $cert_file -text -noout|grep "Not After"|cut -c 25-`" +%s)
        datenow=$(date -d "now" +%s)
        days_exp=$(echo \( $exp - $datenow \) / 86400 |bc)

        if [ "$days_exp" -gt "$exp_limit" ] ; then
                echo "[${domain}] : The certificate is up to date, no need for renewal ($days_exp days left)."
                #exit 0;
        else
                echo "The certificate for $domain is about to expire soon. Starting Let's Encrypt (HAProxy:$http_01_port) renewal script..."
                $certbot_bin certonly --standalone --renew-by-default --http-01-port $http_01_port -d ${domain} -d www.${domain}
                cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > ${haproxy_pem_path}/${domain}.pem
        fi
done

# At the end, reload haproxy
echo "$(date +%c) Reload haproxy"
/usr/sbin/service haproxy reload

Les deux seuls paramètres que vous pourriez vouloir changer sont :

  • http_01_port='54321'
  • exp_limit=30



A savoir, le port utiliser pour la génération des certificats, et la limite (en jours) à partir de laquelle vous souhaitez régénérer un certificat .

sudo chmod +x /root/scripts/renew_all.sh
sudo -s
crontab -e

On ajoute cette ligne dans la crontab ( afin de vérifier chaque jour les certificats à régénérer )

@daily /bin/bash /root/scripts/renew_all.sh 2>&1 | mail -s "[SSL Lindev] Vérification des certificats SSL HAProxy" admin@lindev.fr

Et voilà chaque jour, le script sera exécuté et vous recevrez un petit mail résumant le temps restant pour chaque certificat et potentiellement les logs de régénération s'il y en a eu.

Nouveau domaine à gérer

Imaginons que vous souhaitez gérer un autre nom de domaine, vous devrez la première fois créer le nouveau certificat.
Voici un petit script pour vous simplifier la vie.

sudo vim /root/script/new_cert.sh

le voici

#!/bin/bash

#Configuration variables
certbot_bin="/usr/bin/certbot"
haproxy_pem_path="/etc/haproxy/certs"
http_01_port='54321'
domain=$1

$certbot_bin certonly --standalone --renew-by-default --http-01-port $http_01_port -d ${domain} -d www.${domain}
cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > ${haproxy_pem_path}/${domain}.pem

# At the end, reload haproxy
echo "$(date +%c) Reload haproxy"
service haproxy restart

On le rend exécutable

sudo chmod +x /root/scripts/new_cert.sh

A partir de là pour générer un nouveau certificat (qui sera par la suite automatiquement renouvelé), il vous suffit (en root) d'executer ce script comme ceci

cd /root/scripts
./new_cert.sh mon_nouveau_domaine.com

Et voilà , le certificat sera généré, renouvelé automatiquement et pris en charge par HAProxy .

Conclusion

Nous avons mis en place notre front (HAProxy) qui se charge de la partie SSL puis redirige les flus vers un ou plusieurs backends .
L'avantage de cette configuration et la simplicité de gestion des certificats, même avec plusieurs backends physiquement différents ( load balancing, différents services etc ... ).

Prochaine étape intercaler entre HAProxy et le backend, un serveur de cache ( Varnish ) .

Dans un prochain billet... N'hésitez pas à commenter.

Ch.

dimanche, février 7 2016

Vagrant, environnement de développement unifié

Vagrant.png Je souhaite proposer aux différents développeurs d'un projet, un moyen simple d'avoir un environnement le plus proche possible du serveur de production, que ce soit au niveau de la distribution, mais également des versions des outils installés ( Php, Mysql MariaDb, MongoDb, python, uwsgi, etc ... ). Le but étant de mettre en place l'environnement en un minimum de temps possible, mais aussi de permettre aux développeurs de rester sur leur système d'exploitation préféré. (Linux Mac ou même Windows) pour développer.

Première approche

Peut être (certainement) dû à l'effet de mode, j'ai commencé mes tests avec Docker. Ce dernier permet ce genre de chose, mais je trouve la façon de faire un peu complexe ( Liaisons entre les conteneurs, maintenabilité de l’ensemble etc ) , juste pour avoir un environnement de dev ! Il est vrai que cette techno est vraiment intéressante, le partage de conteneurs avec les autres utilisateurs, le versionning grâce à l'union FS et tout ça sans exploser la conso d'espace disque.

Plus simple, vagrant

Puis un ami m'a parlé de Vagrant, une techno que je n'avais pas encore étudié plus que ça. Pour résumer, il n'y a rien de magique, c'est "juste" un écosystème de gestion de VMs , basé sur virtualbox, qui permet de créer/manager des VMs à partir de systèmes de bases disponibles sur le net ( catalogue Vagrant Boxes ) et surtout de provisionner ces VMs.

C'est là que ça devient intéressant, on a donc un système de gestion de VMs compatible Linux,Windows,Mac, permettant une gestion de VMs très efficace, start, stop, freeze, resume, reload etc ... mais surtout, vous permet de monter une VMs configurée selon vos souhaits et ce de plusieurs façons.

Testons avec un simple environnement LAMP

Je vais volontairement aller vite sur les options disponibles, la doc en ligne de Vagrant étant extrêmement clair, je ne vais pas la copier/coller ici

Commencez par installer Vagrant ( pas besoin d'explication pour cette étape triviale )

Système de base

Nous allons travailler sur une Debian Jessie . Commençons par créer un répertoire pour notre projet ( je le nomme lamp )

mkdir lamp && cd lamp
vagrant init debian/jessie64

Dans notre répertoire lamp, nous trouvons maintenant un fichier de configuration de notre environnement nommé Vagrantfile. Nous allons bientôt mettre les mains dedans .

Capture_d_e_cran_2016-02-13_a__14.53.05.png

Le téléchargement est terminé ? oui ? très bien lançons notre "machine" et allons faire un tour dedans .

Lancer la VM et tour du propriétaire

vagrant up

Une fois la machine lancée, prenons la main en ssh

vagrant ssh

Vous voilà connecté à notre machine. Le système est nu. Avez-vous remarqué au lancement de la vm, ces deux lignes :

==> default: Installing rsync to the VM...
==> default: Rsyncing folder: /Users/moi/lamp/ => /vagrant

Par défaut, vagrant synchronise le répertoire local ( dans notre cas /Users/moi/lamp/ ) avec le répertoire /vagrant présent à la racine du système de fichiers de la VM.
Nous pouvons bien entendu ajouter d'autres répertoires ( voir le fichier de configuration Vagrantfile ligne: config.vm.synced_folder "../data", "/vagrant_data" ).

Retournons sur notre machine hôte ( Cmd + D )

LAMP

Linux ( Ok ça c'est fait ), Apache ( à installer ), Mysql/MariaDB ( à installer ), Php ( à installer ).
Bon on sait ce qu'il nous reste à faire. Mettons les quelques lignes nécessaires à l'installation de ces derniers dans un script bash. Éditons donc dans le répertoire lamp, un fichier que nous nommerons bootstrap.sh

Voici le contenu:

#!/usr/bin/env bash

#Login par defaut : root et pwd : rootpass ( à modifier bien évidemment )
debconf-set-selections <<< 'mysql-server-5.5 mysql-server/root_password password rootpass'
debconf-set-selections <<< 'mysql-server-5.5 mysql-server/root_password_again password rootpass'

apt-get update
apt-get install -y apache2
apt-get install -y mysql-server
apt-get install -y php5 php5-mysql php-pear


if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

Éditons ensuite le fichier Vagrantfile, et en dessous de la ligne config.vm.box = "debian/jessie64" ajouter :

config.vm.provision :shell, path: "bootstrap.sh"

Ne reste plus qu'à provisionner la VM

vagrant reload --provision

Capture_d_e_cran_2016-02-13_a__14.55.18.png

Vous voilà avec un lamp de base, mais comment communiquer facilement avec ?

Le réseau

Il y a plusieurs solutions selon votre besoin.

  • Natter un port de votre machine hôte vers la VM
  • Créer un bridge avec une des vos interfaces pour que la VM soit présente comme n'importe quel autre poste sur votre réseau local
  • Créer un réseau privé permettant à la machine hôte d’accéder à la VM , tout en restant inaccessible depuis l'extérieur pour les autres postes ( solution retenu dans mon cas ).

Éditons le fichier de configuration pour activer ce mode. dé-commenter/compléter cette ligne :

config.vm.network "private_network", ip: "192.168.33.10"

Relançons notre vm

vagrant reload

Testons notre serveur Apache, ouvrez un navigateur, et entrez l'ip de votre vm : http://192.168.33.10

Et là ... vous avez un magnifique "404 not found" !!!.
Normal, le vhost par défaut d'apache cherche ses sources dans le répertoire /var/www/html . et si vous avez bien observé, dans le fichier bootstrap.sh, nous avons ces lignes :

if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

Qui a pour but de mettre le répertoire "vagrant" ( partagé entre l'hôte et la vm ) accessible ( via un lien symbolique ) vers /var/www . Il nous suffit donc de créer un répertoire nommé html dans notre répertoire de projet, lamp ( sur la machine hôte ).

Donc, sur notre machine hôte, dans notre répertoire lamp :

mkdir html && cd html
echo '<?php echo phpinfo();' > index.php

Relançons notre vm

vagrant reload

Maintenant allons rafraichir notre navigateur . Vous devriez avoir la belle page de phpinfo qui s'affiche . Capture_d_e_cran_2016-02-13_a__13.54.36.png

NFS

C'est magnifique, mais si vous ajoutez des fichiers depuis la machine hôte dans le répertoire html, ces derniers ne seront pas accessibles ( synchronisés ) sur la VM. Il faudra pour celà lancer la commande

vagrant rsync-auto

Pas très pratique. Je me suis donc tourné vers le protocole NFS qui est pris en charge en natif avec vagrant ( attention.. ne fonctionne pas avec Windows ).
Éditons notre fichier Vagrantfile et ajoutons ces quelques lignes avant de relancer notre vm

  config.vm.synced_folder ".", "/vagrant",
    :nfs => true

Relançons la VM

vagrant reload

Vagrant va vous demander le mot de passe sudo, afin de modifier pour le fichier /etc/exports.
Afin que le mot de passe ne soit pas demandé à chaque démarrage, vous pouvez soit:

  • Ajouter des règles dans le fichier de config sudo ou ...
  • Renseigner une bonne fois pour toute votre fichier exports et indiquer à vagrant qu'il n'a rien à faire . ( voir les options NFS ).

Conclusion

Voilà pour le premier tour d'horizon de Vagrant, nous avons dans nos main un système de gestion de VM bien ficelé, doté de nombreuses autres options, ( snapshots/restauration, share, ... ) je ne peux que vous conseiller d'aller faire un tour sur le site officiel pour découvrir les différentes options qui s'offrent à vous. Enfin, pour gérer vos environnements, je vous conseil de versionner votre projet ( dossier lamp dans notre exemple ) avec Git par exemple, car c'est grâce aux fichiers de ce répertoire que vous serez en mesure de remonter/partager une VM configurée à l'identique sans aucun effort et en un minimum de temps.

mardi, janvier 26 2016

Php7, installation/compilation ... et rollback

Les articles sur Php7 ne cessent de culpabiliser les développeurs sous php5.x .. , il est plus .. performant, rapide, des nouvelles fonctionnalités qui se rapprochent de python ( ok ... ça c'est un troll ), il est ... bref .. il faut le tester pour se faire une idée, et surtout vérifier si les projets tournent dessus dans devoir faire face à une horde de logs de type Notice , Deprecated, ou encore pire .. Fatal Error

On fait quoi

Vous avez de beaux projets qui tournent sous une version de Php stable 5.X et .. malgré l'adage .. on ne change pas quelque chose qui marche, vous trépigniez d'impatience de voir ce qu'ils donnent avec la dernière monture de la société Zend .

Ok .. mais sans tout casser s'il vous plait.

On va donc voir comment installer ( par compilation ) php7 afin de pouvoir l'utiliser (ou pas) projet par projet. Ou plutôt vhost par vhost .

Installer PHP7

J'ai pris comme base, un serveur tout neuf .. à poil .. Debian Jessie sur la plateforme Google.

Commençons par installer quelques paquets nécessaires pour le bon déroulement de cet article ( et de la compilation de php ).

sudo apt install vim bzip2 build-essential libxml2-dev libc-client-dev libbz2-dev libkrb5-dev libmcrypt-dev librecode-dev

Puis classiquement nous téléchargeons les sources de php

cd /usr/local/src
wget http://us2.php.net/distributions/php-7.0.2.tar.bz2
tar xjf php-7.0.2.tar.bz2
cd php-7.0.2

Nous allons créer un petit fichier de config pour notre version de php ( activer ou pas certains modules, définir l'emplacement de php... )

vim myConfig

Voici le contenu ( nous allons l'installer dans /usr/local/php7 )

#!/bin/sh

mkdir -p /usr/local/php7

export OPTIM=-02
./configure --prefix=/usr/local/php7 \
        --enable-fpm \
        --with-xsl \
        --with-gettext \
        --enable-mbstring \
        --enable-mbregex \
        --disable-debug \
        --enable-ftp \
        --with-mcrypt \
        --enable-zip \
        --enable-calendar \
        --enable-exif \
        --with-pdo-mysql \
        --with-gettext \
        --with-zlib \
        --with-bz2 \
        --enable-inline-optimization \
        --enable-pcntl \
        --enable-opcache \
        --with-mysqli \
        --with-zlib \
        --with-jpeg-dir \
        --with-gd \
        --with-freetype-dir=DIR \
        --with-imap-ssl \
        --with-imap \
        --with-curl \
        --enable-bcmath \
        --with-kerberos \
        --enable-sysvsem \
        --enable-sysvshm \
        --enable-sockets \
        --enable-gd-native-ttf \
        --with-openssl \

Rendons ce script exécutable et ... c'est parti

chmod +x myConfig
./myConfig

Si tout ce passe bien, nous pouvons lancer les deux dernières commandes pour installer php7

make -j `cat /proc/cpuinfo | grep processor | wc -l` 
sudo make install

Configuration

Et bien oui .. vous ne passez pas par les paquets de la distrib .. vous avez donc un poil plus de boulot . Commençons par récupérer le configuration par défaut ( vous 'adapterez au besoin plus tard, ce point sort du cadre de cet article )

cd /usr/local/php7/etc/
cp php-fpm.conf.default php-fpm.conf

Malgré tout, vérifiez bien à dé-commenter la ligne suivante ( vous verrez plus tard pourquoi )

pid = run/php7-fpm.pid
Pools

Enfin il nous faut également créer le pool par défaut de php-fpm

cd php-fpm.d
cp www.conf.default www.conf

Idem il nous faut dé-commencter/éditer/modifier deux trois lignes ( vous pouvez reprendre les valeurs ci-dessous, si vous avez une installation de base . Notamment pour l'utilisateur utilisé pour interpréter vos scripts php )

user = www-data
group = www-data
listen = /var/run/php7-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
php.ini

Aller .. encore un fichier de config à gérer.
On va prendre la version "prod" disponible dans les sources que nous avons téléchargées .

cp /usr/local/src/php-7.0.2/php.ini-production /usr/local/php7/lib/php.ini

Ajoutons le module opcache dans la foulé

vim /usr/local/lib/php.ini

Ajouter en fin de fichier

zend_extension=opcache.so

Ready ! ? ... non pas encore

Lancer php-fpm au démarrage

Commençons par créer notre fichier d'init ( modèle dispo dans les sources également. Je précise ce point car certains articles semblent sortir ces scripts de leur chapeau, sans explication ! )
Les modèles se trouvent dans : /usr/local/src/php-7.0.2/sapi/fpm

vim /etc/init.d/php7-fpm

Le contenu :

#! /bin/sh
### BEGIN INIT INFO
# Provides:          php7-fpm
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts php7-fpm
# Description:       starts the PHP FastCGI Process Manager daemon
### END INIT INFO
php_fpm_BIN=/usr/local/php7/sbin/php-fpm
php_fpm_CONF=/usr/local/php7/etc/php-fpm.conf
php_fpm_PID=/usr/local/php7/var/run/php7-fpm.pid
php_opts="--fpm-config $php_fpm_CONF"
wait_for_pid () {
        try=0
        while test $try -lt 35 ; do
                case "$1" in
                        'created')
                        if [ -f "$2" ] ; then
                                try=''
                                break
                        fi
                        ;;
                        'removed')
                        if [ ! -f "$2" ] ; then
                                try=''
                                break
                        fi
                        ;;
                esac
                echo -n .
                try=`expr $try + 1`
                sleep 1
        done
}
case "$1" in
        start)
                echo -n "Starting php-fpm "
                $php_fpm_BIN $php_opts
                if [ "$?" != 0 ] ; then
                        echo " failed"
                        exit 1
                fi
                wait_for_pid created $php_fpm_PID
                if [ -n "$try" ] ; then
                        echo " failed"
                        exit 1
                else
                        echo " done"
                fi
        ;;
        stop)
                echo -n "Gracefully shutting down php-fpm "
                if [ ! -r $php_fpm_PID ] ; then
                        echo "warning, no pid file found - php-fpm is not running ?"
                        exit 1
                fi
                kill -QUIT `cat $php_fpm_PID`
                wait_for_pid removed $php_fpm_PID
                if [ -n "$try" ] ; then
                        echo " failed. Use force-exit"
                        exit 1
                else
                        echo " done"
                       echo " done"
                fi
        ;;
        force-quit)
                echo -n "Terminating php-fpm "
                if [ ! -r $php_fpm_PID ] ; then
                        echo "warning, no pid file found - php-fpm is not running ?"
                        exit 1
                fi
                kill -TERM `cat $php_fpm_PID`
                wait_for_pid removed $php_fpm_PID
                if [ -n "$try" ] ; then
                        echo " failed"
                        exit 1
                else
                        echo " done"
                fi
        ;;
        restart)
                $0 stop
                $0 start
        ;;
        reload)
                echo -n "Reload service php-fpm "
                if [ ! -r $php_fpm_PID ] ; then
                        echo "warning, no pid file found - php-fpm is not running ?"
                        exit 1
                fi
                kill -USR2 `cat $php_fpm_PID`
                echo " done"
        ;;
        *)
                echo "Usage: $0 {start|stop|force-quit|restart|reload}"
                exit 1
        ;;
esac

On le rend exécutable et crée les liens de démarrage

sudo chmod 755 /etc/init.d/php7-fpm
insserv php7-fpm

Puis on crée le fichier pour initd

vim /lib/systemd/system/php7-fpm.service

Voici le contenu

[Unit]
Description=The PHP 7 FastCGI Process Manager
After=network.target

[Service]
Type=simple
PIDFile=/usr/local/php7/var/run/php7-fpm.pid
ExecStart=/usr/local/php7/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php7/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

On active le service

systemctl enable php7-fpm.service
systemctl daemon-reload
systemctl enable php7-fpm

On lance ENFIN php7-fpm

service php7-fpm start

Petit check

ps -xa | grep php-fpm

qui doit donner un truc du genre:

  861 ?        Ss     0:00 php-fpm: master process (/usr/local/php5/etc/php-fpm.conf)                
  862 ?        S      0:00 php-fpm: pool www                                                         
  863 ?        S      0:00 php-fpm: pool www

Et voilà, vous avez la toute dernière monture de php disponible .
Ok mais ... comment l'utiliser dans le vhost.

Nginx

Installons rapidement Nginx

sudo apt-get install nginx

éditons le vhost par défaut pour prendre en compte notre installation de php

vim /etc/nginx/sites-enabled/default

Et on dé-commente pour avoir ceci

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        #
        #       # With php5-cgi alone:
        #       fastcgi_pass 127.0.0.1:9000;
        #       # With php5-fpm:
                fastcgi_pass unix:/var/run/php7-fpm.sock;
        }

On demande à Nginx de passer les requêtes pointant les fichiers php au socket : /var/run/php7-fpm.sock

Test

Un rapide script de test ...LE phpinfo() :)

vim /var/www/html/test.php

Puis on colle le code suivant

<?php

echo phpinfo();

Rendez-vous sur l'url de votre serveur http://x.x.x.x/test.php

Et là ... victoire ..

Capture_d_e_cran_2016-01-26_a__22.00.30.png

Conclusion

Vous avez compris comment ajouter une version de php à votre serveur ( en plus de la version des dépôts ). Vous pouvez comme celà installer n'importe quelle version de php et utiliser l'une ou l'autre au besoin, en spécifiant le bon socket dans votre vhost .

N'hésitez pas à laisser un commentaire si vous avez des questions .

Bonne nuit.

jeudi, octobre 1 2015

EC2, ajouter un compte utilisateur avec certificat .pem

A la création d'une instance EC2, vous avez un compte par défaut ( ec2-user ou admin selon la distrib ) .
Ce compte vous permet d’accéder et d'administrer votre instance via une connexion SSH , avec une authentification par certificat ( que vous avez préalablement téléchargé à la création de l'instance ).

On va voir ici comment ajouter un compte utilisateur avec un nouveau certificat pour qu'il puisse également se connecter sur cette instance EC2.

Première étape le certificat

Nous allons commencer par créer ce nouveau certificat via l'interface d'amazon ( la clef privée )

Clef privée ( .pem )

C'est très simple, suivez le guide...

Dirigez-vous vers le service EC2 Capture_d_e_cran_2015-10-01_a__09.22.02.png

Gestion des clef Capture_d_e_cran_2015-10-01_a__09.22.13.png

Créer un clef Capture_d_e_cran_2015-10-01_a__09.22.23.png

Vous devrez alors télécharger cette nouvelle clef ( ici elle s'appelle lindev.pem )

Clef public

Coté serveur, nous allons devoir spécifier la clef publique liée à cette clef privée pour le nouvel utilisateur.
Commençons donc par récupérer cette clef publique.

Changez les droits du certificat
chmod 400 lindev.pem
Générer les clef publique à partir de la clef privée
ssh-keygen -y

Cette commande va vous demander le chemin vers la clef privée. Suite à quoi il va vous sortir la clef public .
Par exemple :

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCISBb/pQYoSz1tm2mWrBBK8Yfs+8z2rdcbYhCIgz7oLE2YNrT/cs8D9WXduTezS1p/SjdfA4zhXSJNBvjNP0A0M2s1Mj3E+edpENhsYrLBxDc1F60CQ4be0hLICX2e2mDzPYi7sLgAzAdVI67Eo2Zmj/0QYwckS4JgFl7JXedV8Fz4D2gm8xjByxbtlsPhG84Y9wq7GGmtHuaHzi+H+RVS1hlDZIH8QKwX9U5eWJY3BaQjXpwnorNvn2OrlO9wmTE+22A7F0vF8zsRia+t5TwqPaVYmfX7DN5zqBMcd8tQC1LdYS0b+h6+fLAkUdaqQ0kXGm1FCxYH00hTYNS+JV/V

Gardez cette clef nous allons en avoir besoin bientôt coté serveur.

Coté serveur

Nous sommes maintenant sur notre instance EC2 avec l'utilisateur par defaut, nous allons donc créer notre second utilisateur et lui transmettre notre clef publique.

Création de l'utilisateur

root@ip-172-41-26-237:/home/admin# adduser lindev
Adding user `lindev' ...
Adding new group `lindev' (1001) ...
Adding new user `lindev' (1001) with group `lindev' ...
Creating home directory `/home/lindev' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for lindev
Enter the new value, or press ENTER for the default
	Full Name []: Lindev
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] Y

Voilà mon utilisateur créé, ne nous reste plus qu'à lui créer sa configuration ssh

ssh

Création du répertoire contenant la configuration ssh de l'utilisateur

sudo -s
su - lindev
mkdir /home/lindev/.ssh
chmod 700 /home/lindev/.ssh

Création du fichier contenant les clefs publiques

touch /home/lindev/.ssh/authorized_keys
chmod 600 /home/lindev/.ssh/authorized_keys

Editer le fichier authorized_keys et y coller votre clef public .

vim /home/lindev/.ssh/authorized_keys

je colle donc :

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCISBb/pQYoSz1tm2mWrBBK8Yfs+8z2rdcbYhCIgz7oLE2YNrT/cs8D9WXduTezS1p/SjdfA4zhXSJNBvjNP0A0M2s1Mj3E+edpENhsYrLBxDc1F60CQ4be0hLICX2e2mDzPYi7sLgAzAdVI67Eo2Zmj/0QYwckS4JgFl7JXedV8Fz4D2gm8xjByxbtlsPhG84Y9wq7GGmtHuaHzi+H+RVS1hlDZIH8QKwX9U5eWJY3BaQjXpwnorNvn2OrlO9wmTE+22A7F0vF8zsRia+t5TwqPaVYmfX7DN5zqBMcd8tQC1LdYS0b+h6+fLAkUdaqQ0kXGm1FCxYH00hTYNS+JV/V

On enregistre et on quitte.

Tests

Il ne vous reste plus qu'à tester a connexion avec votre nouvel utilisateur .

ssh -i "lindev.pem" lindev@52.29.115.207

Normalement vous devriez être connecté sans avoir à rentrer le moindre mot de passe, en utilisant le certificat Amazon.

mardi, juillet 14 2015

Monter un Bucket S3 sur un serveur Débian

S3, espace de stockage illimité chez Amazon avec des tarifs défiant toute concurrence. Qui en plus de son prix, offre des options plus qu’intéressantes...

  • chiffrement des données
  • versioning automatique
  • rotation ou mise en glacier des vielles versions ..


Etc ...
Je ne vais pas détailler ces options dans ce billet, mais juste expliquer comment monter un Bucket S3 ( répertoire S3 ) sur une machine / serveur linux afin d'y accéder comme un simple montage réseau . Nous verrons également comment le monter automatiquement via une simple ligne dans le fstab.

Prérequis

Nous allons utiliser fuse pour monter ce bucket, et l'authentification peut être chiffrée selon vos options, nous allons installer tout ce qu'il nous faut...

sudo apt-get install build-essential git libfuse-dev libcurl4-openssl-dev libxml2-dev mime-support automake libtool fuse-utils pkg-config libssl-dev

S3fs-fuse

Maintenant, S3 + fuse n'étant pas un "système de fichiers" conventionnel, nous allons utiliser l'outil s3fs-fuse disponible sur un dépôt Gît

cd /usr/local/src/
git clone https://github.com/s3fs-fuse/s3fs-fuse
cd s3fs-fuse/
./autogen.sh
./configure --prefix=/usr --with-openssl 
make
sudo make install

Authentification S3

Sauf si votre serveur se trouve sur la plateforme Amazon et que vous lui avez donné des droits spécifiques (S3) à sa création, il vous faudra obligatoirement préciser le couple "Access Key / Secret Key" récupéré sur la plateforme Amazon.
Personnellement, je donne à mes utilisateurs un minimum de droits. Dans mon exemple donc, mon utilisateur fictif "John Doe" aura uniquement accès à son bucket, qui sera appelé "jdbucket".
Nous allons donc éditer le fichier qui va lister les authentifications passwd-s3fs.

sudo vim /etc/passwd-s3fs

Le contenu devra respecter la forme suivante bucketName:accessKeyId:secretAccessKey :

jdbucket:AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Nous allons maintenant retirer un maximum de droits au fichier passwd-s3fs

sudo chmod 600 /etc/passwd-s3fs

Montage

Ne nous reste plus qu'à monter notre bucket jdbucket . Disons sur le répertoire /var/mntJdBucket

Commençons par créer le répertoire de montage.

sudo mkdir /var/mntJdBucket; sudo chmod 777 /var/mntJdBucket

Testons le montage avant de la mettre dans le fstab

/usr/bin/s3fs jdbucket /var/mntJdBucket -ouse_cache=/tmp,passwd_file=/etc/passwd-s3fs

Note: Spécifier le fichier de mot de passe S3 n'est pas obligatoire.
Si tout va bien .. vous voilà connecté à votre S3 !
Ne vous faite pas berner par le débit ( important ), ici le débit apparent sera celui de votre disque dur, car l'option use_cache=/tmp utilise un répertoire local comme cache entre votre système et le S3.

Fstab

Ne nous reste plus qu'à configurer notre montage dans le fstab, afin que le montage se fasse à chaque démarrage.

sudo vim /etc/fstab


Voici la ligne qu'il faut ajouter

#Fuse
s3fs#jdbucket	/var/mntJdBucket	fuse	rw,_netdev,use_cache=/tmp,allow_other,passwd_file=/etc/passwd-s3fs	0	0

Au niveau des options, du classique, droits en lecture et écriture pour les utilisateurs, attente de la connexion réseau pour tenter de monter le bucket, configuration du répertoire de cache et du fichier de mot de passe ( toujours facultatif )

Conclusion

Nous avons maintenant fait le tour du montage S3 sur une machine debian, rien de bien méchant. Cependant, suite à mes tests, je conseille d'utiliser les commandes s3cmd pour envoyer de gros fichiers ( plusieurs Gb ) celle-ci étant plus adaptée.

N'hésitez pas si vous avez des questions.

Ch.

- page 1 de 10