Bonne nouvelle, une nouvelle version stable de Debian vient de sortir, à savoir la version 9 nommé "stretch".
Ce qui vous laisse donc environ 1 an avant que la précédente version Jessie maintenant passée en old-stable ne soit plus maintenue.
stretch qui correspond comme d'habitude au nom d'un personnage de l'animation Toy Story.
Si vous utilisez le dépôt "stable" dans votre sources.list, le prochain upgrade sera plus important que d'habitude.
Pensez à parcourir la note de publication pour debian 9 avant d’entamer le dist-upgrade sur vos serveurs .
19 juin 2017
Debian 9 Stretch vient de sortir
Par Christophe de saint leger le lundi, juin 19 2017, 15:08 - Serveur
07 juin 2017
Environnement de développement complet avec Docker
Par Christophe de saint leger le mercredi, juin 7 2017, 18:00 - Serveur
Qu'allons nous voir
Nous allons voir comment mettre sur pied avec Docker un environnement de développement Web complet ( LAMP ) en quelques minutes ( si l'on compte uniquement le temps de déploiement, et non la lecture de ce post. ).
Mais surtout , rendre cet environnement facilement configurable pour qu'il réponde à vos attentes.
Au programme, nous aurons donc 3 conteneurs
- Apache 2.4.25, avec prise en charge des "virtualhosts"
- Php 5.6 Fpm, avec les principaux modules mysqli, pdo, gd, xdebug, redis, opcache, json, mcrypt ...
- Mysql 5.6.36
Petit plus, nous aurons à disposition, un fichier de configuration permettant l'utilisation de la fonction mail() de php.
Pour lancer facilement ces conteneurs Docker, nous utiliseront l'outil docker-compose, qui permet en un seul fichier de déclarer notre environnements et bien plus encore.
Pour les plus pressés : Si vous ne souhaitez pas créer les répertoires et fichiers de conf à la main en suivant tout le billet, vous pouvez directement cloner le projet puis lancer ( Après avoir installé Docker sur votre machine évidemment ). Rendez-vous tout en bas de cette page, dans la section Go go go.
Installation de Docker et docker-compose
Franchement, il n'y a rien de compliqué, je ne vais pas détailler spécialement la méthode , juste vous donner les liens pour les différents systèmes.
Après, il suffit de suivre.
Docker CE
Docker-Compose
Bonne nouvelle pour les utilisateurs de Mac & Windows, l'outil est automatiquement installé avec Docker.
Pour les utilisateurs Linux, je conseille la commande pip
sudo pip install docker-compose
Le projet LAMP
Parfait, nous avons tout les outils nécessaires pour atteindre notre objectif.
Commençons par créer un répertoire qui contiendra l’ensemble des fichiers de configuration et le code source de nos futurs projets Web .
mkdir -p dockerlamp/www dockerlamp/docker/apache/vhosts dockerlamp/docker/mysql dockerlamp/docker/php
Voici en résumé ce que ça donne :
dockerlamp ├── docker │ ├── apache │ │ └── vhosts │ ├── mysql │ ├── php └── www
Nous aurons donc les fichiers de configuration dans le répertoire docker/ et le code source sera dans le répertoire www/
docker-compose.yml
Je vais pas tourner autour du pot, je vais tout de suite vous donner le contenu complet du fichier docker-compose.yml, nous verrons ensuite les différents points à compléter.
Créez donc le fichier docker-compose.yml à la racine du répertoire dockerlamp/
# Adopt version 2 syntax: # https://docs.docker.com/compose/compose-file/#/versioning version: '2' volumes: database_data2: driver: local services: ########################### # Setup the Apache container ########################### httpd: container_name: dockerapache_httpd_1 restart: always image: httpd:2.4.25 ports: - 80:80 volumes: - ./docker/apache/httpd.conf:/usr/local/apache2/conf/httpd.conf - ./docker/apache/vhosts/:/usr/local/apache2/conf/vhosts volumes_from: - php ########################### # Setup the PHP container ########################### php: container_name: dockerapache_php_1 restart: always build: ./docker/php/ expose: - 9000 volumes: - ./www/:/usr/local/apache2/htdocs - ./docker/php/ssmtp.conf:/etc/ssmtp/ssmtp.conf:ro - ./docker/php/php-mail.conf:/usr/local/etc/php/conf.d/mail.ini:ro ########################### # Setup the Database (MySQL) container ########################### mysql: container_name: dockerapache_mysql_1 restart: always image: mysql:5.6.36 expose: - 3306 volumes: - database_data2:/var/lib/mysql - ./docker/mysql/conf-mysql.cnf:/etc/mysql/mysql.conf.d/conf-mysql.cnf:ro environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: project MYSQL_USER: project MYSQL_PASSWORD: project
Configuration Apache
Afin de configurer finement le service Apache, nous allons récupérer le fichier httpd.conf et le déposer dans le répertoire dockerlamp/docker/apache/
Voici le lien de téléchargement httpd.conf
La seule modification faite à ce fichier ( comparé à la version d'origine ) est la prise en charge des virtualhosts.
Nous allons par conséquent également récupérer le virtualhost par défaut et le placer dans le répertoire dockerlamp/docker/apache/vhosts/
Voici le lien de téléchargement 000-default.conf
Pour les curieux, si vous éditez le fichier 000-default.conf, vous verrez que l'on utilise le module proxy d'apache pour gérer les sources php . Nous passons ces sources au service nommé "php" sur le port 9000.
Nous en avons terminé avec le service apache . Passons au service php.
Configuration php-fpm
Contrairement au service apache, le conteneur php-fpm doit être modifié, pour ne serait-ce qu'installer les extensions.
Nous allons donc créer un fichier Dockerfile, qui contiendra toutes les instructions pour finaliser notre container .
La bonne pratique
J'aurais pu simplement créer une image du container sur dockerHub et la mettre à disposition, mais pour partager une image modifiée, la bonne pratique consiste à utiliser comme base l'image officielle ( php ), puis d'ajouter explicitement les changements à apporter dans un DockerFile.
Ce qui vous permet d'être certain que l'image finale n'est pas corrompue.
Dockerfile
créez le fichier Dockerfile dans le répertoire dockerlamp/docker/php/, comme précisé dans docker-compose.yml.
FROM php:5.6-fpm # install the PHP extensions we need RUN set -ex; \ \ apt-get update; \ apt-get install -y \ libjpeg-dev \ libpng12-dev \ libmcrypt-dev \ ssmtp \ ; \ rm -rf /var/lib/apt/lists/*; \ \ docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ docker-php-ext-install gd mysqli opcache pdo_mysql json mcrypt; \ pecl install -o -f xdebug redis \ && rm -rf /tmp/pear \ && echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini \ && echo "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so" > /usr/local/etc/php/conf.d/xdebug.ini; # TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php RUN { \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.interned_strings_buffer=8'; \ echo 'opcache.max_accelerated_files=4000'; \ echo 'opcache.revalidate_freq=2'; \ echo 'opcache.fast_shutdown=1'; \ echo 'opcache.enable_cli=1'; \ } > /usr/local/etc/php/conf.d/opcache-recommended.ini RUN { \ echo '[xdebug]'; \ echo 'xdebug.default_enable = 0'; \ } >> /usr/local/etc/php/conf.d/xdebug.ini RUN { \ echo 'error_reporting = E_ALL'; \ echo 'log_errors = On'; \ echo 'display_errors = Off'; \ } > /usr/local/etc/php/php.ini CMD ["php-fpm"] EXPOSE 9000
php7-fpm : Si vous préférez une autre version de php, il vous suffit de la changer sur la première ligne ( ex : FROM php:7.1.5-fpm ).
Toutes les versions sont listées ici.
fonction mail()
Puisque nous utilisons le service php à l'intérieur d'un container, seul ce service est disponible ( bien qu'il soit possible de lancer plusieurs services dans un même conteneur, cette méthode n'est pas conseillée ), le service sendmail n'est pas disponible.
Pour palier à ce problème, nous allons utiliser ssmtp. Cet utilitaire ne fait que rediriger les mails vers un serveur SMTP externe.
Pour le configurer ( l'activer au sein de php et définir quel serveur SMTP utiliser ), nous allons ajouter deux fichiers dans le répertoire dockerlamp/docker/php/
- php-mail.conf
- ssmtp.conf
php-mail.conf
Ce fichier de configuration ( chargé comme un php.ini supplémentaire ) ne fait que surcharger le chemin de l’exécutable sendmail afin d'utiliser ssmtp.
[mail function] sendmail_path = "/usr/sbin/ssmtp -t"
ssmtp.conf
Ce fichier vous permet de définir quel serveur SMTP utiliser pour envoyer vos mails.
Par exemple, pour utiliser un compte Gmail:
mailhub=smtp.gmail.com:587 [email protected] AuthPass=mypassword FromLineOverride=YES hostname=dockerdev.foo.net UseSTARTTLS=YES
Seules les 3 premières lignes sont à adapter selon votre cas.
Nous en avons terminé avec la configuration de php-fpm. Passons à Mysql
Configuration Mysql
C'est presque le service le plus simple... dans le fichier docker-compose, nous avons défini des variables d'environnements, qui spécifient le mot de passe du compte root, une base de données à créer avec un utilisateur associé (login et mot de passe) .
Par la suite, si vous devez ajouter une nouvelle base de données, deux possibilités .
- Ajouter les informations dans le fichier docker-compose, et relancer le conteneur
- Se connecter en root sur le service mysql et créer manuellement la base de données et son utilisateur .
Nous allons créer le fichier conf-mysql.cnf, dans le répertoire dockerlamp/docker/mysql/ ce fichier est automatiquement monté dans le conteneur Mysql à son démarrage et permet donc de modifier simplement la configuration de mysql .
Par exemple, si l'on souhaite modifier la variable sql_mode
[mysqld] sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
Note : Vous pouvez laisser ce fichier vide si vous n'en avez pas l'utilité pour le moment. Mais il doit être présent dans le répertoire mysql !
Notre environnement LAMP est maintenant prêt !
Lancer l'environnement LAMP
Puisque nous avons configuré notre environnement via un fichier docker-compose.yml, nous allons évidemment utiliser la commande docker-compose pour le lancer.
Placez-vous à la racine du projet dockerlamp/
docker-compose up -d
Cette commande va construire les volumes, les interfaces réseaux, télécharger les images nécessaires, construire les conteneurs si besoin ( via le Dockerfile ) et enfin ... les exécuter en tache de fond . Oui oui .. tout ça en une seule commande .. le pied!
Le test
Nous allons tester notre stack, apache et php.
Créez deux fichiers dans le répertoire www/
- info.php
- index.html
info.php
<?php echo phpinfo();
index.html
<h1>Hello World</h1>
Enfin ouvrez un navigateur et entrez ces URLs :
Vous devriez normalement voir un magnifique Hello World, et la page d'infos de php !
Un vrai projet
Je ne vais pas vous laisser avec un simple phpinfo() et un Hello World !!
Nous allons aller au bout des choses, en installant par exemple un petit Drupal.
L'objectif est d'installer Drupal et qu'il soit accessible ( sur votre machine ) depuis l'url http://drupal.local/
Le Vhost
Afin de pouvoir utiliser un nom de domaine locale, ( drupal.local ), il faut auparavant renseigner le fichier hosts, pour le déclarer .
Linux et Mac
sudo sh -c "echo '127.0.0.1 drupal.local' >> /etc/hosts"
Windows
Pour Windows vous devez ouvrir le fichier c:\Windows\System32\Drivers\etc\hosts en administrateur avec NotePad et y ajouter la ligne :
127.0.0.1 drupal.local
Maintenant, nous allons créer notre vhost afin qu'Apache sache quoi faire lorsqu'il reçoit les requêtes avec le nom de domaine drupal.local.
Editer le fichier dockerlamp/docker/apache/vhosts/drupal.conf
<VirtualHost *:80> ServerAdmin [email protected] ServerName drupal.local <Directory /> AllowOverride All Require all granted </Directory> DocumentRoot "/usr/local/apache2/htdocs/drupal" <Directory "/usr/local/apache2/htdocs/drupal"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> <FilesMatch \.php$> # 2.4.10+ can proxy to unix socket # SetHandler "proxy:unix:/var/run/php5-fpm.sock|fcgi://localhost/" # Else we can just use a tcp socket: SetHandler "proxy:fcgi://php:9000" </FilesMatch> </VirtualHost>
On a donc déclaré le nom de domaine à Apache, en lui spécifiant de pointer sur le répertoire drupal/
Les sources
Puisque nous avons demandé à Apache de pointer sur le répertoire drupal/, nous allons télécharger les sources de Drupal dans ce répertoire qui lui-même se trouve dans le répertoire dockerlamp/www/
cd www wget https://ftp.drupal.org/files/projects/https://ftp.drupal.org/files/projects/drupal-8.3.2.tar.gz tar xzf drupal-8.3.2.tar.gz mv drupal-8.3.2 drupal mkdir -p drupal/sites/default/files/translations && chmod -R 777 sites/default/files/translations chmod -R 777 drupal/sites/default/files touch drupal/sites/default/settings.php && chmod 777 drupal/sites/default/settings.php
Enfin, pour que le conteneur Apache prenne en considération notre nouveau vhost, nous allons redémarrer notre stack
docker-compose restart
L'installation
Pour l'installation, il suffit de pointer sur notre nom de domaine local et suivre les instructions
http://drupal.local/
Arrivé à l'installation de la base de données, remplissez le formulaire comme ceci ( Base de données déclarée dans le fichier docker-compose.yml ),
- Nom de la base de données : project
- Utilisateur : project
- Mot de passe : project
- Et dans options avancés > Hôte : mysql
Après cette étape, Drupal s'installe tranquillement sur votre environnement
Remplissez les formulaires durant l'installation, vous devriez rapidement arriver sur la page d'accueil de votre Drupal fraîchement installé .
Conclusion
Vous avez à disposition un environnement de développement complet comme démontré avec Drupal.
Pour chaque projet vous devez donc
- Créer un domaine local dans votre fichier hosts
- Créer la configuration du virtualHost pour apache
- Récupérer les sources et les placer dans le répertoire www/
- Relancer la stack LAMP via docker-compose
Voici quelques outils / lignes de commandes pour vous aider à travailler, "debugger".
Vous trouverez ces petits scripts dans le répertoire tools/ du dépôt dockerlamp.
Ces scripts ne représentent qu'une base pour vous aider à travailler, je vous laisse maintenant parcourir la documentation de Docker pour comprendre les différentes commandes / configurations utilisées dans ce billet.
N’hésitez pas à poser des questions si besoin.
Créer un dump d'une base de données
dump_sql.sh
docker exec dockerapache_mysql_1 /usr/bin/mysqldump --databases -uroot -psecret $DATABASE > $DATABASE.sql
Restaurer/Importer une base de donnée depuis un dump sql
restore_sql.sh
cat $DUMP | docker exec -i dockerapache_mysql_1 /usr/bin/mysql -uroot -psecret
Afficher les logs Apache en temps réel ( Pour débugger )
logs.sh
docker logs --tail 100 -f dockerapache_httpd_1
Afficher les ressources utilisées par les conteneurs sur votre machine
stats.sh
docker stats --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"
Go go go
On clone l'environnement
git clone https://[email protected]/cdesaintleger/dockerlamp.git && cd dockerlamp
On Configure le smtp
cp docker/php/ssmtp.conf.dist docker/php/ssmtp.conf && vim docker/php/ssmtp.conf
On lance la stack
docker-compose up -d
01 mar. 2017
Cloud Amazon, ne pas mettre tous ses oeufs dans le même panier
Par Christophe de saint leger le mercredi, mars 1 2017, 21:28 - Autre
L'article
Voici la source : cio.com
Pour résumer, cet article fait le constat qu'une panne chez Amazon a des conséquences énormes .
Principalement dû au fait que ce seul et même fournisseur de services offre tellement de produits qu'il n'est pas nécessaire d'aller voir ailleurs pour monter un SI complexe .
Amazon devient tellement présent que cette panne a impacté 20% de l'internet ! 20% !
Il est vrai qu'Amazon offre des services de très haute qualité, le problème n'est pas là, mais plutôt du constat qu'il devient l'hébergeur majoritaire des services en ligne.
Internet qui a pour force d'être multi-prestataires devient de fait affaibli par un marché qui se déséquilibre ..
Une panne et hop 20% du net tombe avec lui .
Comment en est-on arrivé là ?
Pourquoi la concurrence à ce niveau n'est elle pas plus au rendez-vous ?
Problème marketing ?
Trop grosse différence de coût ?
Ce rouleau compresseur va t'il tout écraser sur son passage comme pour la vente en ligne ?
Un constat qui devient inquiétant . (selon moi) Ch.
28 déc. 2016
HAProxy LetsEncrypt et Varnish en front .. rien que ça
Par Christophe de saint leger le mercredi, décembre 28 2016, 20:13 - Serveur
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 ).
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 = [email protected] # 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.
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" [email protected]
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.
07 fév. 2016
Vagrant, environnement de développement unifié
Par Christophe de saint leger le dimanche, février 7 2016, 14:23 - Serveur
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 .
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
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 .
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.
26 janv. 2016
Php7, installation/compilation ... et rollback
Par Christophe de saint leger le mardi, janvier 26 2016, 16:01 - Serveur
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 ..
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.
23 janv. 2016
Python pip et son cache local
Par Christophe de saint leger le samedi, janvier 23 2016, 13:25 - Python
Afin d'éviter de re-télécharger les paquets pour chaque projet nous allons voir ce petit truc extra simple qui est d'activer le cache local de pip.
Le principe est simple, la première fois que vous installez un paquet, ce dernier est téléchargé, puis mis en cache.
La seconde fois ( s'il s’agit de la même version ), pip va simplement l'installer depuis le cache.
Ok, ça ne va pas vous changer la vie, mais moi je trouve ça sympa à utiliser, surtout lorsque vous devez installer des gros paquets avec une connexion d’hôtel faiblarde, ça peut vous faire gagner de précieuses minutes .
Configuration de PIP
Commençons par éditer le fichier de configuration de pip
vim ~/.pip/pip.conf
Ajouter dans la section "global":
[global] download-cache=/usr/local/pip/cache
enfin on donne les droits d'écriture
mkdir -p /usr/local/pip/cache chmod -R 755 /usr/local/pip/cache
Deuxième méthode un peu plus courte
Simplement ajouter dans votre fichier de profil : ~/.bash_profile
export PIP_DOWNLOAD_CACHE=$HOME/.pip_download_cache
Voilà pour ce micro billet.
Bon weekend .
06 déc. 2015
Réference commande dans prestashop [1.6.x]
Par Christophe de saint leger le dimanche, décembre 6 2015, 14:26 - Prestashop
Prestashop et ses bizarreries
Je travaille quotidiennement sur Prestashop, car à mon grand regret, il n’existe pas aujourd'hui, beaucoup d'alternatives qui proposent un produit :
- libre
- fonctionnel et évolutif
- supporté par une communauté active
- avec une documentation complète ( pour l'utilisateur et le développeur )
- développé en python sous Django par exemple .... humm ce dernier point sent le troll
Bref dans ma grande frustration personnel, je dois tout de même admettre que Pretashop offre une solution complète performante et fonctionnelle pour l'utilisateur final, mais dés qu'il s'agit de mettre les mains dans le code, la documentation et plus que maigre !! Et il faut investiguer, poser des questions qui bien souvent dés que ces dernières sont un peu techniques, restent sans réponse sur le forum officiel !!
Nous ( développeurs ) sommes doc seuls devant le code et devons faire preuve de patience pour apprivoiser le code sans documentation approfondie. Ce manque d'information est selon moi voulu pour pousser le système économique qui tourne autour de Prestashop ( modules payants pour ajouter des fonctionnalités qui parfois devraient être disponibles par défaut dans la solution ).
D'autant que certains choix fait par Prestashop semblent parfois peu efficaces, voir illogiques.
Prenons le cas de la référence commande, qui est sous la forme d'une chaine de caractères aléatoire et unique .
Pour une boutique qui n'a que quelques commandes / jour cela ne pose aucun problème (quoique), mais pour un flux plus important, cette référence qui sera utilisée par vous et vos clients n'est absolument pas pratique.
Prenons un exemple. Si je vous donne la référence : QRFRUMBMF vous êtes bien avancé, ce n'est pas mnémotechnique et ne vous apprend rien sur la commande.
Alors que ( par exemple ) une référence comme : 20151206-225 qui est la concaténation de :
- 2015 : L'année de la commande
- 12 : le mois de la commande
- 06 : le jour de la commande
- 225 : id unique de la commande
Aurait était un choix beaucoup plus pertinent pour tout le monde ( client et marchand ).
Posez la questions sur le forum et vous aurez avec un peu de chance, une âme charitable qui va vous guider pour effectuer ce changement. Dans le cas contraire, votre demande tombera dans les abîmes avec les autres messages du genre restés sans réponse .
Aller au boulot, voyons comment faire ce changement dans le code.
La surcharge
Je ne vais pas détailler comment surcharger les différents éléments de Prestashop mais utiliser cette technique pour deux fichiers.
Comme expliqué pus haut, prestashop est bien fini et permet de tout "surcharger" pour vous permettre de modeler/modifier les fonctionnalités de base de l'outil à volonté.
Nous allons donc surcharger dans un premier temps les fichiers suivants :
- classes/order/OrderHistory.php
- classes/PaymentModule.php
OrderHistory.php
Cette classe gère l'historique des commandes et de ce fait, gère également l’expédition des emails liés à ces états. Mails dans lesquels est rappelé la référence de la commande.
Nous allons donc créer le fichier de surcharge override/classes/order/OrderHistory.php , copier la méthode d'origine addWithemail et enfin le modeler à notre sauce.
ce qui donne :
<?php class OrderHistory extends OrderHistoryCore{ /** * @param bool $autodate Optional * @param array $template_vars Optional * @param Context $context Optional * @return bool */ public function addWithemail($autodate = true, $template_vars = false, Context $context = null){ if (!$context) $context = Context::getContext(); $order = new Order( (int)$this->id_order ); $date = new DateTime($order->date_add); $data = array( '{id_order}' => $date->format('Ymd').'-'.$this->id_order ); if ($template_vars){ $data = array_merge($data, $template_vars); } return parent::addWithemail($autodate, $data, $context); } }
Ne vous reste plus qu'à remplacer dans vos mails la balise {order_name} par {id_order}
PaymentModule.php
Cette classe est utilisée à la confirmation de commande et s'occupe également de l'expédition du mail de confirmation de commande ( pourquoi avoir séparé ce mails des autres ? ). Bref, nous allons donc également surcharger cette classe et plus précisément la méthode validateOrder.
Nous allons donc créer le fichier de surcharge override/classes/PaymentModule.php , copier la méthode d'origine validateOrder() et enfin le modeler à notre sauce.
class PaymentModule extends PaymentModuleCore{ /** * Validate an order in database * Function called from a payment module * * @param int $id_cart * @param int $id_order_state * @param float $amount_paid Amount really paid by customer (in the default currency) * @param string $payment_method Payment method (eg. 'Credit card') * @param null $message Message to attach to order * @param array $extra_vars * @param null $currency_special * @param bool $dont_touch_amount * @param bool $secure_key * @param Shop $shop * * @return bool * @throws PrestaShopException */ public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null) { ... ... ... //contenu de la méthode d'origine ( copier - coller de la methode validateOrder dans le fichier classes/PaymentModule.php ) ... ... ... // Avant la liste des paramétres, o va formater la date de la commande $dateOrder = new DateTime($order->date_add); .... //Vers la ligne 622 dans la liste des paramètres balancés au template du mail, ajouter la ligne ... '{id_order}' => $dateOrder->format('Ymd').'-'.$order->id ... ... ... } }
Voilà , ne vous reste plus qu'à mettre à jour le mail orderConf pour remplacer {order_name} par {idorder}
vider le cache
Afin que les surcharges soient bien prises en compte, vous devez supprimer le fichier de cache suivant :
cache/class_index.php
Conclusion
Voilà comment changer une partie de prestashop sans toucher au code d'origine.
Si ce que vous avez fait ne fonctionne pas ou casse quelque chose, il vous suffit alors de supprimer ces fichiers ( dans le répertoire Override ) et remettre les balises dans les mails.
Pas d'inquiétude donc lancez-vous.
01 oct. 2015
EC2, ajouter un compte utilisateur avec certificat .pem
Par Christophe de saint leger le jeudi, octobre 1 2015, 10:01 - Serveur
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
Gestion des clef
Créer un clef
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
[email protected]:/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" [email protected]
Normalement vous devriez être connecté sans avoir à rentrer le moindre mot de passe, en utilisant le certificat Amazon.
14 juil. 2015
Monter un Bucket S3 sur un serveur Débian
Par Christophe de saint leger le mardi, juillet 14 2015, 15:10 - Serveur
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.
27 juin 2015
Prestashop - Surcharger le code d'un module
Par Christophe de saint leger le samedi, juin 27 2015, 11:04 - Prestashop
Prestashop permet dans sa version actuelle (1.6) de surcharger à peu prés .. tout !
Ce qui est vraiment pratique pour modeler votre site e-commerce comme vous l'entendez sans toucher au cœur du code. Ce qui vous permettra ( dans une certaine mesure ) de pouvoir mettre à jour prestashop sans devoir réécrire vos fonctionnalités spécifiques ou votre thème.
Mais il y a les modules
Une autre des force de cet outil e-commerce, ce son ses modules, très nombreux qui permettent d'ajouter des fonctionnalités de façon .. "plug and play", activer désactiver etc .. super !!
Seulement dans la documentation, impossible de trouver le moyen de surcharger un module existant.( je parle de la surcharge de la fonctionnalité apportée par ce module, les templates associés sont surchargeable de façon classique )
jusqu'à maintenant, si vous souhaitiez changer le fonctionnement d'un module, vous aviez le choix entre :
- Toucher directement au code du module ( prochaine mise à jour .. et hop ... vous devez recommencer )
- Copier le module pour le dupliquer à votre sauce ( Assez lourd )
La signature à utiliser
Et bien figurez vous que c'est possible .. si si ..
Note : uniquement à partir de la v1.6.0.11 ( merci à ChDUP pour cette précision )
Pour surcharger une classe, vous utilisez l'écriture suivante :
class [className sans Core] extends [className]Core
dans le répertoire override/ ou modules/monModule/override/
Et bien pour surcharger le code d'un module, il vous faut utiliser l'écriture suivante
class [classNameModule]Override extends ClassNameModule
Il suffit donc d'utiliser la chaine "Override" dans le nom de votre classe qui va surcharger le module souhaité .
Par contre, il faut placer votre code dans le répertoire
override/modules/moduleName/
L'exemple qui va bien
Prenons le cas du module BlockPaymentLogo disponible par défaut, qui permet d'afficher les logis de paiement sur une colonne de votre home.
Moi je souhaite les afficher .. dans le pied de page "Footer", ce module n'a pas prévu ce cas, est n'est donc pas enregistré au bon Hook ( displayFooter ) . Bref impossible de le faire en natif .
Surchargeons
Nous allons commencer par créer le répertoire du même nom que celui d'origine
override/modules/blockpaymentlogo/
Puis créer le code de surcharge que voici.
if (!defined('_PS_VERSION_')) exit; class BlockPaymentLogoOverride extends BlockPaymentLogo { public function install(){ if( parent::install() ){ return $this->registerHook('displayFooter'); }else{ return false; } } public function hookDisplayFooter($params) { return $this->hookLeftColumn($params); } }
Petites explications,
- on commence par déclarer notre classe comme il se doit ( en ajoutant Override, et en héritant de la classe du module d'origine )
- Puis j'ajoute dans le constructeur l'association du module dans le hook displayFooter
- Et enfin, je définis le code spécifique à ce hook ( ici le code sera le même que sur le hook leftcolumn, donc je ne réécris pas le code j'appelle celui du hook leftcolumn )
Ne reste plus qu'à réinitialiser le module .. et voilà les logos qui apparaissent dans mon footer .
Restez informé
inscrivez vous à la newsletter pour recevoir les nouveaux billets par mail. ( formulaire en haut à droite )
25 mai 2015
Gérer les Bounces avec Amazon
Par Christophe de saint leger le lundi, mai 25 2015, 09:17 - Serveur
Ce billet va présenter deux outils Amazon autour d'un exemple concret, la gestion des Bounces en utilisant Amazon en relais pour vos mails.
Bounces
Lorsque vous envoyez une "newsletter" à de nombreuses adresses mails, il y a ce que l'on appel les "BOUNCES" , qui traduit donne "rebonds". Il s'agit en fait du retour des mails qui partent vers une adresse qui ne fonctionne pas. Il y a plusieurs raisons qui peuvent engendrer un tel rebond, certaines raisons sont temporaires, d'autres définitives. Par exemple :
- Le destinataire n’existe pas ( définitif )
- Boite pleine ( temporaire )
- Erreur Serveur ( temporaire )
- Plainte ( définitif )
- Pas de réponse ( temporaire )
- Pas de résolution DNS ( définitif )
Pourquoi traiter ces rebonds ?
Tout est une histoire de réputation, en effet ne pas traiter ces rebonds et les laisser s'augmenter à chaque newsletter, peut tout doucement vous faire passer pour un "spammeur", d'autant que nous utilisons le relais mails Amazon ( service SES ) qui va réduire votre capacité à envoyer des mails si le nombre de bounces augmente sans action de votre part.
Deuxième raison, financière, pourquoi continuer à envoyer et payer des mails à des adresses qui n’existent pas ! ( ok le cout du mail est ridicule avec Amazon, mais c'est une question de principe )
Comment les gérer ?
Souvent, vous définissez une adresse de retour via ue entête spécifique, dédiée au retour "système" ( Entête : return-path ), ainsi les bounces atterrissement dans cette boite mail dédiée et c'est à vous de les traiter. ( les outils des mailing intègrent souvent une fonction de récupération des bounces par une lecture de boite mail en pop ).
Cependant, Amazon permet d'aller un peu plus loin grâce à son service de notification SNS.
Le principe est simple, lorsque Amazon reçoit un "Bounce" il va transmettre un message de notification dans le topic associé . A ce "topic" nous allons lui associer une "inscription" ( qui est en fait une action à lancer lorsque qu'un "message" arrive sur ce topic ).
Dans notre cas, ce sera une simple requête HTTP avec dans son corps les informations du Bounce en format JSON.
Création du Topic
Depuis l'interface Amazon SNS, vous créez un nouveau "topic"
On va le nommer Bounces
Puis nous allons créer une "subscription"
On va donc choisir le protocole HTTP et dans le champ "endpoint", nous mettons l'url qui pointe sur notre script décrit plus bas ( exemple : http://lindev.fr/sns.php )
Pour le moment, voici notre script sns.php :
<?php ob_start(); var_dump( $_POST ); $content = ob_get_clean(); $fp = fopen('sns_validation.txt', a+); fwrite($fp,$content); fclose($fp);
Le but étant d'enregistrer dans un fichier texte, ce que nous envoi Amazon . NÉCESSAIRE AU DÉBUT POUR LA VALIDATION DE LE SOUSCRIPTION
Vous pouvez maintenant valider votre formulaire d'ajout de "subscription", vous allez alors voir apparaitre dans le fichier sns_validation.txt une url pour valider définitivement l'enregistrement.
Il vous suffit alors d'ouvrir cette url pour terminer l'enregistrement.
SES et SNS, le lien
Maintenant nous allons faire en sorte que tout les bounces liés à un domaine géré par le service SES d'amazon, utilisent le système de notification SNS et surtout le "topic" fraichement créé.
Pour cela, nous allons dans la section SES d'amazon, ( le domaine doit auparavant être validé pour pouvoir relayer des mails, pour cela il suffit d'ajouter des champs TXT dans la zone DNS. La documentation d'amazon est très bien faite à ce sujet ).
Nous allons donc dans la section Notifications, et l'on édite la configuration
Et là nous allons choisir les options adéquats
On sélectionne donc notre souscription dans les menus "Bounces" et "Complaints" uniquement, car ce sont ces deux cas que nous souhaitons traiter automatiquement.
Et voilà, après validation, dés qu'un "bounce" montre le bout de son nez, un message est transmit au service SNS et une requête HTTP avec toutes les informations nécessaires dans un format JSON est lancée en POST.
Tests
Pour tester le service, Amazon nous met à disposition des adresses spécifiques, qui simulent chaque cas.
Ne vous reste donc plus qu'à envoyer un mail à ces deux adresses, et regarder le contenu des données POST qui vont s'ajouter dans votre fichier sns_validation.txt
Cas simple
Imaginons, que nous souhaitons, simplement lister les mails des Bounces et Complaints dans un fichier TXT avec trois champs
- Date de réception du Bounce
- Adresse mail
- Type de Bounce ( temporaire ou définitif ou complaint ).
Nous allons donc extraire ces données du JSON, notre script sns.php devient :
<?php // Fetch the raw POST body containing the message $postBody = file_get_contents('php://input'); // JSON decode the body to an array of message data $msg = json_decode($postBody, true); if ($msg) { //Ouverture du fichier de log $fp = fopen('sns_bounces.txt', 'a+'); $data = json_decode($msg['Message'],true); $typeMsg = $data['notificationType'];//A utiliser pour séparer plaintes et Bounces switch( $typeMsg ){ case 'Bounce': $bounceType = $data['bounce']['bounceType']; foreach( $data['mail']['destination'] AS &$mail ){ //Ecriture dans la liste txt fwrite($fp, date('Y-m-d H:i:s').";".$mail.";". $bounceType . "\n"); } break; case 'Complaint': foreach( $data['mail']['destination'] AS &$mail ){ //Ecriture dans la liste txt fwrite($fp, date('Y-m-d H:i:s').";".$mail.";complaint" . "\n"); } break; } fclose($fp); }
Vous allez alors vous retrouver avec une liste exploitable comme un CSV .
L'idée, c'est d'améliorer ce script de démo pour une désinscription automatique dans votre outil de mailing ( très simple avec phplist )
Restez informé
inscrivez vous à la newsletter pour recevoir les nouveaux billets par mail. ( formulaire en haut à droite )
18 mai 2015
Amazon Ec2 IO et Raid
Par Christophe de saint leger le lundi, mai 18 2015, 14:00 - Serveur
J'ai eu quelques soucis récemment avec une instance Amazon qui héberge une base de données Mysql très sollicitée par période.
En effet les données de la base étaient sur la même partition que le système ( déjà c'est mauvais ), celle-ci étant fortement sollicitée en IO, la charge système se met à grimper, les temps d'attente d’accès au disque étant de plus en plus grand, jusqu'au crash complet .
La solution simple et rapide est de déplacer les données vers une partition dédiée, avec des performances en IO plus importantes (tant qu'à faire). C'est dans ce contexte que je vais présenter, dans ce billet, la mise en place d'une partition en Raid0 pour augmenter significativement les IO/s et surtout éviter de surcharger le système.
Ce que l'on va voir
- Création de système de fichiers XFS
- Création d'un Raid logiciel
- Monitoring avec atop
- Ajout d'un disque au Raid
- Extension d'une partition XFS
Etat des lieux
Je vais utiliser une instance micro ( gratuite ) sous Debian Jessie en HVM ( virtualisation totale ). je vais y attacher 4 disques.
- /dev/xvda pour le système
- /dev/sdb pour tester les perfs. sur un seul disque
- /dev/sdc premier disque du Raid
- /dev/sdb deuxième disque du Raid
Installation des outils
Le système étant vierge nous allons installer les paquets nécessaires pour les manipulations ci-dessous.
sudo apt-get install xfsprogs atop mdadm
Premier test : Disque seul
Pour pouvoir comparer, nous allons commencer avec un test sur un disque "seul" possédant une partition XFS
Voici comment sont perçus les disques à ce moment
Commençons par créer la partition :
sudo cfdisk /dev/xvdb
Une fois la partition créée, voici comment sont perçus les disques
Nous allons maintenant créer le système de fichiers sur cette nouvelle partition
mkfs.xfs /dev/xvdb1
Enfin il ne nous reste plus qu'à monter cette partition sur un répertoire que nous allons également créer maintenant
mkdir /home/admin/diskLocal mount -t xfs /dev/xvdb1 /home/admin/diskLocal/
Dirigeons nous dans ce répertoire et effectuons le premier test basique, grâce à l'outil dd
cd /home/admin/diskLocal dd if=/dev/zero of=bench.dat bs=1M count=1024 oflag=direct
Pendant le test on voit bien grâce à la commande atop, l'utilisation du disque qui est à son maximum
Et voici le résultat
Deuxième test : 2 Disques en Raid0
Commençons par construire notre raid0 "software" ( via la commande mdadm )
mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=2 /dev/xvdc /dev/xvdd
Ce qui nous donne :
Un petit check :
mdadm -D /dev/md0
Maintenant, créons notre système de fichiers sur md0
mkfs.xfs /dev/md0
Enfin il ne nous reste plus qu'à monter cette partition sur un répertoire que nous allons créer: diskRaid
mkdir /home/admin/diskRaid mount -t xfs /dev/md0 /home/admin/diskRaid/
Dirigeons nous dans ce répertoire et effectuons le second test sur ce disque Raid0
cd /home/admin/diskRaid dd if=/dev/zero of=bench.dat bs=1M count=1024 oflag=direct
Regardons ce qui se passe pendant le test
Les deux disques sont en pleine charge, et quelques secondes plus tard ...
On passe donc de 30 secondes à 18 sec. pour effectuer ce test et un débit d’écriture de 35.5MB/s à 51MB/s
Conclusion
Il est plus intéressant de mettre en place 2 disques en Raid0 qu'avoir un gros disque pour améliorer les IO/s.
Ajoutons un disque au Raid0
Si nous ajoutons un disque à notre Raid0, nous passerons ainsi à 3 disques
Voici le disque à ajouter
- /dev/xvde
Ajoutons le à notre raid md0
sudo mdadm --grow /dev/md0 --raid-devices=3 --level=0 --add /dev/xvde sudo xfs_growfs /dev/md0
Regardons si tout est ok
lsblk
Vérifions que la partition fasse bien 15G
df -h
Bien ça me semble parfait, lançons le troisième test
cd /home/admin/diskRaid dd if=/dev/zero of=bench.dat bs=1M count=1024 oflag=direct
Résultat :
Les performances restent les mêmes, certainement limitées par la virtualisation ou simplement physiquement, cependant la charge étant répartie sur 4 disques, l'occupation ne dépasse pas les 65%, ce qui permet d'avoir d'autres processus en parallèles.
L'ajout de disques reste donc très intéressante pour pouvoir encaisser une forte charge d'IO/s .
Bon tests ,
Ch.
Restez informé
inscrivez vous à la newsletter pour recevoir les nouveaux billets par mail. ( formulaire en haut à droite )
16 mai 2015
Envoi de mail à la création de compte via le backend de prestashop
Par Christophe de saint leger le samedi, mai 16 2015, 14:33 - Prestashop
Un petit truc tout bête bien pratique, à tel point que je ne comprends pas pourquoi ce n'est pas en place dans les fonctionnalités de base de prestashop.
Le besoin
Prestashop 1.6
Lorsqu'un employé crée un compte utilisateur depuis le backoffice de prestashop, aucun mail n'est envoyé au client final ( le mail de bienvenue contenant ses identifiants pour se connecter ), de plus l'employé doit entrer lui-même un mot de passe, ce qui n'est pas des plus pratique, surtout lorsque l'employé est en manque d'imagination, on peut se retrouver alors dans une problématique de sécurité non négligeable.
La solution
Nous allons simplement permettre à l'employé de laisser le champs "passwd" vide, il sera alors automatiquement généré de façon aléatoire.
Enfin, nous allons ajouter un bouton "On/Off" dans le formulaire de création de compte qui va permettre à l'employé de décider si oui ou non les identifiants seront envoyés au client.
Le code
Bien commençons par créer la classe de surcharge
override/controllers/admin/AdminCustomersController.php
Nous allons donc surcharger les méthodes suivantes :
- processAdd()
- renderForm()
Et créer une fonction
- sendConfirmationMail()
Voici donc le code complet de notre fichier AdminCustomersController.php
<?php /* * 05-2015 * * @author Christophe De Saint Leger * @Description Surcharge Formulaire création compte depuis le BackEnd */ class AdminCustomersController extends AdminCustomersControllerCore { public function processAdd() { if (Tools::getValue('submitFormAjax')) $this->redirect_after = false; // Check that the new email is not already in use $customer_email = strval(Tools::getValue('email')); $customer = new Customer(); if (Validate::isEmail($customer_email)) $customer->getByEmail($customer_email); if ($customer->id) { $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$customer_email; $this->display = 'edit'; return $customer; } elseif (trim(Tools::getValue('passwd')) == '') { $_POST['passwd'] = Tools::passwdGen(); } if ($customer = parent::processAdd()) { $this->context->smarty->assign('new_customer', $customer); if( Tools::getValue('sendWelcomeEmail') ){ $this->sendConfirmationMail($customer); } return $customer; } return false; } public function renderForm() { if (!($obj = $this->loadObject(true))) return; $genders = Gender::getGenders(); $list_genders = array(); foreach ($genders as $key => $gender) { $list_genders[$key]['id'] = 'gender_'.$gender->id; $list_genders[$key]['value'] = $gender->id; $list_genders[$key]['label'] = $gender->name; } $years = Tools::dateYears(); $months = Tools::dateMonths(); $days = Tools::dateDays(); $groups = Group::getGroups($this->default_form_language, true); $this->fields_form = array( 'legend' => array( 'title' => $this->l('Customer'), 'icon' => 'icon-user' ), 'input' => array( array( 'type' => 'radio', 'label' => $this->l('Social title'), 'name' => 'id_gender', 'required' => false, 'class' => 't', 'values' => $list_genders ), array( 'type' => 'text', 'label' => $this->l('First name'), 'name' => 'firstname', 'required' => true, 'col' => '4', 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"°{}_$%:' ), array( 'type' => 'text', 'label' => $this->l('Last name'), 'name' => 'lastname', 'required' => true, 'col' => '4', 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"°{}_$%:' ), array( 'type' => 'text', 'prefix' => '<i class="icon-envelope-o"></i>', 'label' => $this->l('Email address'), 'name' => 'email', 'col' => '4', 'required' => true, 'autocomplete' => false ), array( 'type' => 'password', 'label' => $this->l('Password'), 'name' => 'passwd', 'required' => ($obj->id ? false : true), 'col' => '4', 'hint' => ($obj->id ? $this->l('Leave this field blank if there\'s no change.') : sprintf($this->l('Password should be at least %s characters long. or void for automatic generation'), Validate::PASSWORD_LENGTH)) ), array( 'type' => 'switch', 'label' => $this->l('Send Welcome Email'), 'name' => 'sendWelcomeEmail', 'required' => false, 'class' => 't', 'is_bool' => true, 'values' => array( array( 'id' => 'sendWelcomeEmail_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'sendWelcomeEmail_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), 'hint' => $this->l('Send the credentials to the client') ), array( 'type' => 'birthday', 'label' => $this->l('Birthday'), 'name' => 'birthday', 'options' => array( 'days' => $days, 'months' => $months, 'years' => $years ) ), array( 'type' => 'switch', 'label' => $this->l('Enabled'), 'name' => 'active', 'required' => false, 'class' => 't', 'is_bool' => true, 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), 'hint' => $this->l('Enable or disable customer login.') ), array( 'type' => 'switch', 'label' => $this->l('Newsletter'), 'name' => 'newsletter', 'required' => false, 'class' => 't', 'is_bool' => true, 'values' => array( array( 'id' => 'newsletter_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'newsletter_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_NWSL'), 'hint' => $this->l('This customer will receive your newsletter via email.') ), array( 'type' => 'switch', 'label' => $this->l('Opt-in'), 'name' => 'optin', 'required' => false, 'class' => 't', 'is_bool' => true, 'values' => array( array( 'id' => 'optin_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'optin_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_OPTIN'), 'hint' => $this->l('This customer will receive your ads via email.') ), ) ); // if we add a customer via fancybox (ajax), it's a customer and he doesn't need to be added to the visitor and guest groups if (Tools::isSubmit('addcustomer') && Tools::isSubmit('submitFormAjax')) { $visitor_group = Configuration::get('PS_UNIDENTIFIED_GROUP'); $guest_group = Configuration::get('PS_GUEST_GROUP'); foreach ($groups as $key => $g) if (in_array($g['id_group'], array($visitor_group, $guest_group))) unset($groups[$key]); } $this->fields_form['input'] = array_merge( $this->fields_form['input'], array( array( 'type' => 'group', 'label' => $this->l('Group access'), 'name' => 'groupBox', 'values' => $groups, 'required' => true, 'col' => '6', 'hint' => $this->l('Select all the groups that you would like to apply to this customer.') ), array( 'type' => 'select', 'label' => $this->l('Default customer group'), 'name' => 'id_default_group', 'options' => array( 'query' => $groups, 'id' => 'id_group', 'name' => 'name' ), 'col' => '4', 'hint' => array( $this->l('This group will be the user\'s default group.'), $this->l('Only the discount for the selected group will be applied to this customer.') ) ) ) ); // if customer is a guest customer, password hasn't to be there if ($obj->id && ($obj->is_guest && $obj->id_default_group == Configuration::get('PS_GUEST_GROUP'))) { foreach ($this->fields_form['input'] as $k => $field) if ($field['type'] == 'password') array_splice($this->fields_form['input'], $k, 1); } if (Configuration::get('PS_B2B_ENABLE')) { $risks = Risk::getRisks(); $list_risks = array(); foreach ($risks as $key => $risk) { $list_risks[$key]['id_risk'] = (int)$risk->id; $list_risks[$key]['name'] = $risk->name; } $this->fields_form['input'][] = array( 'type' => 'text', 'label' => $this->l('Company'), 'name' => 'company' ); $this->fields_form['input'][] = array( 'type' => 'text', 'label' => $this->l('SIRET'), 'name' => 'siret' ); $this->fields_form['input'][] = array( 'type' => 'text', 'label' => $this->l('APE'), 'name' => 'ape' ); $this->fields_form['input'][] = array( 'type' => 'text', 'label' => $this->l('Website'), 'name' => 'website' ); $this->fields_form['input'][] = array( 'type' => 'text', 'label' => $this->l('Allowed outstanding amount'), 'name' => 'outstanding_allow_amount', 'hint' => $this->l('Valid characters:').' 0-9', 'suffix' => $this->context->currency->sign ); $this->fields_form['input'][] = array( 'type' => 'text', 'label' => $this->l('Maximum number of payment days'), 'name' => 'max_payment_days', 'hint' => $this->l('Valid characters:').' 0-9' ); $this->fields_form['input'][] = array( 'type' => 'select', 'label' => $this->l('Risk rating'), 'name' => 'id_risk', 'required' => false, 'class' => 't', 'options' => array( 'query' => $list_risks, 'id' => 'id_risk', 'name' => 'name' ), ); } $this->fields_form['submit'] = array( 'title' => $this->l('Save'), ); $birthday = explode('-', $this->getFieldValue($obj, 'birthday')); $this->fields_value = array( 'years' => $this->getFieldValue($obj, 'birthday') ? $birthday[0] : 0, 'months' => $this->getFieldValue($obj, 'birthday') ? $birthday[1] : 0, 'days' => $this->getFieldValue($obj, 'birthday') ? $birthday[2] : 0, ); // Added values of object Group if (!Validate::isUnsignedId($obj->id)) $customer_groups = array(); else $customer_groups = $obj->getGroups(); $customer_groups_ids = array(); if (is_array($customer_groups)) foreach ($customer_groups as $customer_group) $customer_groups_ids[] = $customer_group; // if empty $carrier_groups_ids : object creation : we set the default groups if (empty($customer_groups_ids)) { $preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); $customer_groups_ids = array_merge($customer_groups_ids, $preselected); } foreach ($groups as $group) $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], in_array($group['id_group'], $customer_groups_ids)); return AdminController::renderForm(); } /** * sendConfirmationMail * @param Customer $customer * @return bool */ protected function sendConfirmationMail(Customer $customer) { if (!Configuration::get('PS_CUSTOMER_CREATION_EMAIL')) return true; return Mail::Send( $this->context->language->id, 'account', Mail::l('Welcome!'), array( '{firstname}' => $customer->firstname, '{lastname}' => $customer->lastname, '{email}' => $customer->email, '{passwd}' => Tools::getValue('passwd')), $customer->email, $customer->firstname.' '.$customer->lastname ); } }
Attention à ne pas oublier
Pour toute nouvelle surcharge, il vous faut supprimer le fichier de cache suivant
cache/class_index.php
Résultat
Et voilà le résultat au niveau du formulaire
Bonne journée,
Ch.
Restez informé
inscrivez vous à la newsletter pour recevoir les nouveaux billets par mail. ( formulaire en haut à droite )
13 mai 2015
Time zones nommées mysql
Par Christophe de saint leger le mercredi, mai 13 2015, 14:44
Un nouveau billet pense bête ...
A l'installation de Mysql selon la version ou la façon de l'installer, les Time Zone nommées ne sont pas toujours ajoutées dans la base de données mysql. Voilà la petite ligne de commande à exécuter (sous linux) pour y remédier ( les ajouter )
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u <utilisateur admin> mysql
Et voilà .. vous pouvez utiliser les requête
SET time_zone = timezonename;
Restez informé
inscrivez vous à la newsletter pour recevoir les nouveaux billets par mail. ( formulaire en haut à droite )
26 avr. 2015
Jessie, la bonne nouvelle du jour
Par Christophe de saint leger le dimanche, avril 26 2015, 10:11
Ça y est, après de longs mois de développement des équipes Debian, voilà la nouvelle monture disponible "Debian Jessie".
Merci aux développeurs pour ce travail formidable .
22 fév. 2015
Apache2 php5-fpm VirtualHost
Par Christophe de saint leger le dimanche, février 22 2015, 15:24 - Serveur
Cela fait maintenant quelques mois que je n'ai pas édité de nouveau billet sur ce site, je vais donc couper cette période creuse en vous proposant un petit tutoriel sur la mise en place de php5-fpm avec apache2 et tout ça configurable au besoin dans des virtualhost .
Nous avons déjà vu comment faire avec Nginx ( qui est franchement plus clair qu'apache ) mais parfois on a pas le choix du serveur web sur lequel on travail .. alors voyons comment faire ça proprement avec apache2.
Etat des lieux
Le tutoriel se base sur la version stable de Débian du moment, Debian 7 "Wheezy" .
Nous allons également activer les dépôts contrib et non-free pour installer ce qui va suivre .
Pour cela commencez par éditer le fichier /etc/apt/sources.list
sudo vim /etc/apt/sources.list
Et ajoutez à la fin de chaque ligne contrib non-free
Ce qui donne quelque chose comme çà
deb http://cloudfront.debian.net/debian wheezy main contrib non-free deb-src http://cloudfront.debian.net/debian wheezy main contrib non-free deb http://security.debian.org/ wheezy/updates main contrib non-free deb-src http://security.debian.org/ wheezy/updates main contrib non-free deb http://cloudfront.debian.net/debian wheezy-updates main contrib non-free deb-src http://cloudfront.debian.net/debian wheezy-updates main contrib non-free
PS: ne faite pas attention à l'url de mes dépôts ci-dessus "cloudfront.debian.net" , j'utilise une instance (VM) Amazon pour réaliser mes tests .
Installation des paquets nécessaires
Nous allons installer les paquets suivants :
sudo apt-get install php5-fpm libapache2-mod-fastcgi php5-cgi
Puis il nous faut activer le module fastcgi et actions via la commande a2enmod
sudo a2enmod actions fastcgi
Configuration du module fastcgi
Il nous faut lier le module fastcgi aux processus php5-fpm, pour celà nous allons éditer le fichier de configuration du module fastcgi
vim /etc/apache2/mods-available/fastcgi.conf
Pour arriver à ce résultat
<IfModule mod_fastcgi.c> AddType application/x-httpd-fastphp5 .php Action application/x-httpd-fastphp5 /php5-fcgi Alias /php5-fcgi /usr/bin/php5-fcgi FastCgiExternalServer /usr/bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization </IfModule>
NB : il vous faut vérifier le chemin du socket php5-fpm dans votre cas, normalement, /var/run/php5-fpm.sock et la valeur par défaut pour l’environnement Débian 7, pour vérifier exécuter cette commande
cat /etc/php5/fpm/pool.d/www.conf | grep "listen = "
Le test
Il ne vous reste plus qu'à tester cette nouvelle configuration, commençons par tester l'ensemble des paramètres d'apache via la commande très pratique
sudo apache2ctl configtest
Puis il ne reste plus qu'à relancer Apache si tout est ok
sudo service apache2 restart
Enfin, nous allons mettre un simple fichier php dans le DocumentRoot par défaut d'apache2
sudo echo "<?php echo phpinfo();" > /var/www/lindev.php && chown www-data:www-data /var/www/lindev.php
Il ne vous reste plus qu'à entrer l'url http://localhost/lindev.php pour voir le résultat .
Conf spécifique par virtualhost
Jusque là, les scripts php sont exécutés par l'utilisateur système www-data dans la plupart des cas, cela va être adéquat, mais si pour une raison quelconque vous devez utiliser un autre utilisateur pour exécuter un script/site en particulier, dans le virtualhost correspondant, il vous faudra surcharger la configuration du module fastcgi, ce qui donnera par exemple
<VirtualHost *:80> ServerAdmin [email protected] ServerName lindev.fr ServerAlias www.lindev.fr DocumentRoot /var/www/lindev/ ErrorLog /var/www/lindev/error.log CustomLog /var/www/lindev/access.log combined <IfModule mod_fastcgi.c> AddType application/x-httpd-fastphp5 .php Action application/x-httpd-fastphp5 /php5-fcgi Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi_lindev FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi_lindev -socket /var/run/php5-fpm_lindev.sock -pass-header Authorization </IfModule> </VirtualHost>
Ici , j'ai donc donné un autre socket à utiliser, que j'ai nommé php5-fpm_lindev.sock. Ce socket devra bien évidement être configuré coté php-fpm, en créant un nouveau pool ( dans un prochain article certainement ), en attendant, pour tester copiez juste la conf du pool par défaut, et changer le paramètre listen pour spécifier le socket à créer pour ce pool.
C'est également dans ce fichier de pool que vous pourrez spécifier l'utilisateur système à utiliser pour interpréter les fichiers php.
cp /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/lindev.conf
Changer les paramètres listen, user et group , puis relancer php-fpm
sudo service php5-fpm reload
L'article touche maintenant à sa fin, vous savez maintenant installer apache, php5-fpm et configurer un pool spécifique de php pour un virtualhost.
Ch.
15 sept. 2014
Réparer son virtualenv aprés un update Systéme/Libs
Par Christophe de saint leger le lundi, septembre 15 2014, 11:25 - Python
Après une belle maj de votre système, vous avez, au moment de vous remettre au travail, un sympathique message du genre
ImportError: No module named datetime
detatime !! Cette lib fait pourtant partie du standard de python ! Le fait est que lorsque l'on met à jour python, les liens utilisés à la création du venv sont hs !
Ici c'est la lib datetime qui a été remonté, mais ça peu être n'importe laquelle ..
Solution
Il ne m'a pas fallu longtemps pour résoudre ce problème tout bête, ( beaucoup de cas similaires sur le net ).
Réinitialiser le virtualenv
Par exemple avec mon venv nommé foo
virtualenv /home/cdsl/.virtualenvs/foo New python executable in /home/foo/.virtualenvs/creasoft3/bin/python Installing setuptools............done. Installing pip...............done.
Et voilà ..
27 août 2014
Django déploiement avec Nginx Gunicorn et Supervisord
Par Christophe de saint leger le mercredi, août 27 2014, 12:13
Je vois souvent passer des questions sur le forums ou autres fils de discussion concernant la mise en production d'un projet Django.
Ici je vais présenter une façon de faire, utilisant Nginx Gunicorn et Supervisord .
Prérequis
Sur une Débian toute fraiche,
Nginx
sudo apt-get install nginx
Virtualenv
Car nous travaillons toujours avec un environnement virtuel, dans lequel nous allons y installer les dépendances de notre projet.
Ce qui permet de ne pas avoir de conflit de version avec d'autres éventuels projets déjà en prod.
pip install virtualenv virtualenvwrapper
Note : Si vous n'avez pas l'outil pip de disponible, installez-le comme ceci
sudo apt-get install python-setuptools sudo easy_install pip
Puis dans votre fichier ~/.bashrc , ajoutez les lignes suivantes, pour l'autocompletion
export VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--no-site-package' export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh
Gunicorn
Pourquoi pas utiliser uWSGI ? humm ... car je préfère Gunicorn qui me donne toute satisfaction sur mes projets en prod. donc ... pourquoi pas !
sudo apt-get install libevent-dev pip install gunicorn
Supervisor
Installation simple :
sudo pip install supervisor
Récupération du fichier de conf par défaut
echo_supervisord_conf > /etc/supervisord.conf
Dans le fichier de conf, afin de pouvoir manager votre projet via l'interface web, il faut dé-commenter et paramétrer les lignes suivantes
[inet_http_server] ; inet (TCP) server disabled by default port=*:9001 ; (ip_address:port specifier, *:port for all iface) username=user ; (default is no username (open server)) password=123 ; (default is no password (open server))
Note: Changer le username et password évidemment
L'interface web sera disponible à l'adresse : http://ipduserveur:9001
Pour le lancement automatique au démarrage du système, vous pouvez utiliser ces scripts d'init:
Installer votre projet
Notre environnement est prêt, nous allons commencer par installer le projet Django dans l’environnement virtuel.
Création du virtualenv
mkvirtualenv monprojet
Si vous utilisez git, cloner votre projet, sinon, copier le à l'endroit que vous souhaitez, ( pour l'exemple ce sera /var/www/monprojet )
Installation des dépendances du projet
si vous utilisez également les environnements virtuels pour développer ( ce que je conseille ) vous pouvez alors enregistrer la liste des libs python installées dans cette environnement, afin de pouvoir également les installer ( avec la même version ) sur un autre serveur.
Pour avoir la liste des libs :
pip freeze > requirements.txt
puis sur votre serveur, pour installer les libs depuis un export freeze :
pip install -r requirements.txt
Configuration de Django
Il vous faudra peut-être toucher un peu à votre fichier settings.py pour le passer du mode debug au mode production.
Personnellement j'utilise une autre subtilité qui me permet de ne pas avoir à toucher au fichier settings.py ( j'expliquerai celà dans un autre billet ) .
N'oubliez pas de vérifier le paramètre STATIC_ROOT
STATIC_ROOT = '/var/www/static_monprojet/'
C'est le répertoire ou seront copiés les fichiers statiques du projet, pour ensuite être servis par Nginx
Ce répertoire DOIT EXISTER
Une fois le répertoire créé, nous allons y "placer/lier" les fichiers statiques du projet
python manage.py collectstatic --link
Perso je préfère y mettre des liens symboliques .. ( les gouts et les couleurs ... )
Liaison du projet avec Gunicorn
Nous allons créer un fichier dans notre projet qui sera utilisé pour le lancement du/des process Gunicorn ( vous devrez adapter les valeurs dans ce script )
vim /var/www/monprojet/monprojet/gunicorn.sh
Et voici le contenu
#!/bin/bash set -e NUM_WORKERS=2 USER=www-data GROUP=www-data ADDRESS=127.0.0.1:5002 cd /var/www/monprojet source /home/monuser/.virtualenvs/monprojet/bin/activate exec gunicorn monprojet.wsgi:application -w $NUM_WORKERS --bind=$ADDRESS \ --user=$USER --group=$GROUP --log-level=debug
Puis on le rend exécutable
chmod 777 /var/www/monprojet/monprojet/gunicorn.sh
Configuration Supervisord
Notre projet est prêt, afin de lancer Gunicorn automatiquement, nous allons utiliser supervisord, qui en plus de s'occuper de démarrer le projet automatiquement au démarrage du système, va aussi le relancer en cas de crash, gérer les logs et vous donner la main pour arrêter ré-demarrer les process, via l'interface web ou en mode console.
Ajoutez à la fin du fichier de configuration /etc/supervisord.conf les lignes suivantes ( paramètres à adapter selon votre cas )
[program:guni_monprojet] directory=/var/www/monprojet/monprojet user = www-data autostart=true autorestart=true stdout_logfile=/var/log/monprojet.log redirect_stderr=true stopsignal=QUIT command = /var/www/monprojet/monprojet/monprojet.sh
Ne reste plus qu'à redémarrer supervisor pour prendre en compte la nouvelle config.
Pour le lancer manuellement
sudo supervisord -c /etc/supervisord.conf
Vhost Nginx
Dernier point, la création du vhost de Nginx, pour diriger les requêtes vers Gunicorn qui écoute sur le port 5002 ( il est aussi possible d'utiliser un fichier socket à la place )
vim /etc/nginx/sites-enabled/monprojet
Et voilà le contenu ( fonctionnel, mais vous pouvez l'adapter )
upstream us_monprojet { server 127.0.0.1:5002; } server { listen 80; root /var/www/monprojet; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain application/xml text/css text/javascript application/x-javascript application/x-shockwave-flash video/x-flv; gzip_disable "MSIE [1-6]\."; server_name monprojet.com; charset utf-8; client_max_body_size 75M; location ~ /\.ht { deny all; } location /favicon.ico { alias /var/www/monprojet/monprojet/static/favicon.ico; if (-f $request_filename) { access_log off; expires max; } } location /media { alias /var/www/monprojet/monprojet/media; if (-f $request_filename) { access_log off; expires max; } } location /static { alias /var/www/static_monprojet/; if (-f $request_filename) { access_log off; expires max; } } location / { if (-f $request_filename) { access_log off; expires max; } #gunicornParams if (!-f $request_filename) { proxy_pass http://us_monprojet; break; } proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
Ne reste plus qu'à activer le vhost, et relancer nginx
ln -s /etc/nginx/sites-available/monprojet /etc/nginx/sites-enabled/ service nginx reload
01 août 2014
Proxy Socks sous android NON Rooté
Par Christophe de saint leger le vendredi, août 1 2014, 12:36 - Autre
En cette période de vacances, nous sommes nombreux à nous connecter depuis nos terminaux ( smartphone, tablette .. ) pour surfer, parfois travailler , dépanner .
Il est vrai que ces appareils sont formidables sur ce point ( le coté nomade ). Mais le revers de la médaille, c'est la sécurité !
Lorsque vous vous connectez à une borne wifi ( gratuite ou non ), qui vous assure que votre navigation n'est pas épiée ?
Voilà pour le coté sécurité, mais il peut être aussi utile de se connecter à son réseau local depuis l'extérieur.
Nous allons pour cela nous connecter via un serveur proxy de type socks.
Maintenant peu importe ce qui motive l'utilisation d'une telle connexion, voyons comment faire pour nous y connecter depuis un client Android non chrooté
Les apps à installer
JuiceSSH est un client SSH qui fonctionne vraiment bien, gratuit pour les fonctionnalités de base, mais payant pour faire une redirection de port. Vous allez donc devoir l'acheter, mais l'investissement en vaut la peine.
D'autres ont utilisé ConnectBOT qui lui est à 100% gratuit, mais de mon coté il plantait régulièrement je n'ai donc pas insisté.
Configuration de juiceSSH
Nous allons commencer par créer une connexion SSH de base, le tout en image :
- Nickname : nom de la connexion
- Type : SSH
- Adresse : Adresse du serveur SSH
- Identity : Login pour se connecter au serveur SSH
- Port : port à utiliser pour se connecter au serveur SSH
Configuration de la redirection de port
Allez dans l'onglet PORT FORWARD, et nous allons utiliser la connexion SSH précédemment crée, comme ceci.
Il est ensuite possible de mettre une icône sur votre page principale, pour se connecter plus rapidement au serveur proxy SOCKS
Configuration de Firefox
Pour utiliser le serveur proxy ( après s'y être connecté ), dans firefox, ouvrez un nouvel onglet et entrez dans la barre d'adresse :
Voici les 5 paramètres à configurer comme ceci
Tests
Voilà maintenant vous pouvez tester le bon fonctionnement en entrant l'url suivante : http://www.whatismyip.com/, qui devrait vous afficher l'ip du serveur SSH à partir duquel vos requêtes sont envoyés .
Bonnes vacances .
« billets précédents - page 1 de 28
Derniers commentaires