23/04/2014

GCU-Squad! >> Graphite clusters

Par : pinpin
Tags:
Irc
clustering
graphite

Une bonne intro / explication des différents modes de fonctionnement de graphite en cluster.

http://bitprophet.org/blog/2013/03/07/graphite/ proposé par twisla sur #GCU@freenode


22/04/2014

GCU-Squad! >> It’s never too late to adopt emacs

Par : pinpin
Tags:
Irc
emacs

Mais comme la bête peut être un tantinet délicate à amadouer les premiers temps, on appréciera à sa juste valeur cette collection de liens pour aider les débutants.

http://sachachua.com/blog/2014/04/emacs-beginner-resources/ proposé par Seb sur #GCU@freenode


16/04/2014

GCU-Squad! >> UNIX; do you teach it, motherfucker ?

Par : pinpin
Tags:
Irc
Unix
course
teaching

Une introduction plaisante aux principes de base d’UNIX, avec des exemples et tout, pour amener plus de gens du côté clair de la force.

http://www.ee.surrey.ac.uk/Teaching/Unix/ proposé par Seb sur #GCU@freenode


16/04/2014

GCU-Squad! >> UNIX; do you script it, motherfucker ?

Par : pinpin
Tags:
Irc
Unix
shell
tutorial

Et pour poursuivre, les bases de la programmation en shell. Mais si vous préférez appeler ça du scripting, vous pouvez aussi.

http://www.dreamsyssoft.com/unix-shell-scripting/ proposé par Seb sur #GCU@freenode


11/04/2014

Le Projet NetBSD, en Français >> Is your heart bleeding ?

Par : GuiGui2
Tags:
Code
NetBSD
Securité
current

Bon! Hier a été publié la 4ème alerte de sécu de l’année affectant notre système préféré, et pas des moindres. Une erreur de programmation dans OpenSSL, composant central s’il en est, peut être exploitée pour exposer des données stockées en mémoire. Parmi les données exposées, on peut retrouver des mots de passe, mais surtout la clé privée utilisée par le programme vulnérable pour établir la connection sécurisée – ce qui rend d’un coup la connexion beaucoup moins sécurisée…. Le bug est présent dans openssl 1.0.1 jusqu’à la version 1.0.1f. La version 1.0.1g est la version mise à jour contenant le fix.

Alors, cette fois-ci plus que les autres, il est impératif de mettre vos systèmes à jour. NetBSD-6.0, NetBSD-6.1, NetBSD-6 et NetBSD-current sont vulnérables, L’advisory comporte tous les détails requis pour effectuer la mise à jour dans les meilleurs délais.


07/04/2014

GCU-Squad! >> A/B testing, 100% Apache-based

Par : pinpin
Tags:
Apache
Irc
a/b
httpd
testing

Où comment le réaliser uniquement avec Apache, sans aucun PHP ou autre horreur… mod_rewrite FTW.

http://julien.danjou.info/blog/2014/a-b-testing-with-apache proposé par Seb sur #GCU@freenode


06/04/2014

Philpep's blog >> Intégration continue avec Jenkins et Docker

Par : Philippe Pepiot
Tags:
docker
jenkins

Tout bon développeur se doit connaitre le très bon mix github et travis-ci. Je ne saurais que trop vous conseiller d'utiliser ces outils mais il y a toutefois différentes raisons qui pourraient vous pousser à ne pas vouloir utiliser ces services:

Voilà donc une infrastructure que j'ai mise en place avec jenkins un très bon outil d'intégration continue (malgré le fait qu'il soit codé en java) et docker qui est un système de container linux ultra léger basé sur les cgroups, lxc et aufs

L'idée est la suivante pour un build:

De cette manière le build est toujours lancé dans un environnement sain et contrôlé, vous n'avez pas besoin de maintenir des slaves jenkins et ça scale particulièrement bien puisque vous pouvez rajouter des serveurs docker capables de lancer pleins de containers.

Voilà la manip sur Debian wheezy pour faire des containers Debian wheezy.

Installation de docker

root@ci:~# wget https://get.docker.io/builds/Linux/x86_64/docker-latest -O /usr/bin/docker
root@ci:~# curl -o /etc/init.d/docker https://raw.githubusercontent.com/dotcloud/docker/master/contrib/init/sysvinit-debian/docker
root@ci:~# chmod +x /usr/bin/docker /etc/init.d/docker
root@ci:~# addgroup docker
root@ci:~# update-rc.d -f docker defaults
root@ci:~# cat << EOF > /etc/default/docker
DOCKER_OPTS="-H 127.0.0.1:4243 -H unix:///var/run/docker.sock"
EOF
root@ci:~# service docker restart
root@ci:~# docker info
Containers: 0
Images: 0
Storage Driver: aufs
    Root Dir: /var/lib/docker/aufs
    Dirs: 0
Execution Driver: native-0.1
Kernel Version: 3.2.0-4-amd64
WARNING: No memory limit support
WARNING: No swap limit support

Installation de Jenkins

root@ci:~# echo "deb http://pkg.jenkins-ci.org/debian binary/" > /etc/apt/sources.list.d/jenkins.list
root@ci:~# wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
root@ci:~# apt-get update
root@ci:~# apt-get install jenkins
root@ci:~# service jenkins start
root@ci:~# if curl http://localhost:8080 2>/dev/null | grep -iq jenkins; then echo "OK"; else echo "FAIL"; fi
OK

Création du container

Il faut maintenant créer une image qui servira de base pour notre container. On part d'un debootstrap et on installe ce qu'il faut pour lancer le slave jenkins.

root@ci:~# apt-get install debootstrap
root@ci:~# curl -o mkimage-debootstrap.sh https://raw.githubusercontent.com/dotcloud/docker/master/contrib/mkimage-debootstrap.sh
root@ci:~# chmod +x mkimage-debootstrap.sh
root@ci:~# ./mkimage-debootstrap -s wheezy64 wheezy http://ftp.fr.debian.org/debian/
root@ci:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
wheezy64            wheezy              7867d3b51969        About a minute ago   116.7 MB

root@ci:~# cat << EOF > Dockerfile
FROM wheezy64:wheezy

RUN apt-get install -y openssh-server openjdk-7-jre-headless
RUN useradd -m -s /bin/bash jenkins
RUN echo jenkins:jenkins | chpasswd
RUN mkdir -p /var/run/sshd
EXPOSE 22
CMD /usr/sbin/sshd -D
EOF
root@ci:~# docker build -t wheezy64:jenkins .
root@ci:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
wheezy64            jenkins             77f27af6a9d5        4 minutes ago       333.4 MB
wheezy64            wheezy              7867d3b51969        27 minutes ago      116.7 MB

On teste le container en le lançant et en essayant de se connecter avec l'user jenkins.

root@ci:~# jenkins=$(docker run -d -p 0.0.0.0:2222:22 -t -i wheezy64:jenkins)
root@ci:~# ssh jenkins@localhost -p 2222
jenkins@localhost's password: 
Linux ci 3.2.0-4-amd64 #1 SMP Debian 3.2.54-2 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

jenkins@2eb438b131f4:~$ exit
logout
Connection to localhost closed.

root@ci:~# docker kill $jenkins && docker rm $jenkins

Jenkins et docker

C'est maintenant que la magie s'opère, on va installer le plugin docker sur jenkins via l'interface web et dans la configuration générale, paramètres "cloud", on déclare notre image docker. On rajoute au passage un credential "Username with password" pour qu'il puisse se connecter en ssh sur le container (username: jenkins, password: jenkins) et on met un label "wheezy64" pour ces containers.

jenkins docker

Ensuite on configure un job qui va se lancer sur un container jenkins avec le système de labels.

jenkins job

On lance le job et voilà:

Started by user anonymous
Building remotely on 8c736a572ff6 (wheezy64) in workspace /home/jenkins/workspace/test
Finished: SUCCESS

Et maintenant ?

Vous pouvez adapter l'image docker pour y installer l'environnement de build dont vous avez besoin (base de données, compilateurs, interpréteurs python, ruby etc). Pour plus de flexibilité vous pouvez aussi installer sudo et donner tous les droits sans mot de passe à l'utilisateur jenkins, ainsi le script de build peut installer des packages et modifier la configuration de l'image.


31/03/2014

Weblog de Natacha >> Dissonances cognitives

Par : Natacha Kerensikova
Tags:
Tarée

Récemment, pendant un entretien téléphonique de recrutement à une prestation, le client potentiel m'a posé une question classique : « [professionnellement] qu'est-ce que vous aimez faire ? »

J'aime faire du code robuste, fiable. Pendant très longtemps je n'ai développé que des outils pour moi, pour les utiliser. Je veux pouvoir compter sur mes outils, ne pas passer mon temps à les déboguer.

J'ai lu à plusieurs endroits que lorsqu'on fait un reproche aux autres (ou à un conjoint/compagnon suivant les sources), c'est en fait à soi-même qu'on le fait, et c'est dans cette direction qu'il faut travailler sur soi. Je n'ai jamais réussi à le vérifier.

Par contre, c'est bien le cas pour mon code. Cette fiabilité que j'attends de mon code, c'est une des caractéristiques fortes de ce moi idéal vers lequel je cherche à tendre.

Alors évidemment, ça n'empêche pas que j'attends une grande fiabilité de mon code et des outils logiciels que j'utilise. D'ailleurs parmi le peu de choses qui arrivent qui arrivent à m'énerver, il y a lorsqu'un outil ou une partie de mon infrastructure me lâche et que je n'arrive pas à le réparer ou la remettre en place.

Exactement une autre de ces choses qui me met hors de moi : lorsqu'une partie de mon corps « bug », par exemple lorsqu'une impulsion inopinée contracte une de mes cuisses lorsque j'essaye de m'endormir, contraction qui me tire immédiatement de mon début de sommeil (c'est d'ailleurs grâce à la combinaison de cet énervement et de l'irritabilité de manque de sommeil que j'ai découvert que la douleur empêche des impulsions, du moins tant qu'elle dure).

Parce que finalement, même si je ne suis pas une geekette, je considère mes outils comme des extensions de moi-même.

Peu de temps après cette réponse, une sonnerie retentit. Je me précipite pour refuser l'appel sur mon téléphone mobile, en remarquant au passage qu'il vient de mon compagnon, censé être sur la route.

Une heure plus tard, après l'entretien, j'écoute son message, où il me demande de le rappeler dès que possible. Je le rappelle, je tombe sur la messagerie sans sonnerie. Je commence à m'inquiéter, mais je rationalise. Une demi-heure plus tard, pareil. Je m'inquiète. Encore une demi-heure plus tard, pareil. J'angoisse sérieusement.

Quelqu'un de fiable, sur qui on peut compter, tu parles.

Alors que ma vie amoureuse est largement au dessus de ma vie professionnelle dans mon échelle de valeurs.

Comme ce lundi soir où il m'avait proposé une sortie où je n'ai pu que bêtement répondre « Ben c'est lundi, j'ai arène [à World of Warcraft] »

Quelqu'un sur qui on peut compter pour un évènement en groupe, où chacun est indispensable, ou un évènement improvisé amoureux ? Sachant que de mon échelle de valeurs, ma vie amoureuse est largement au dessus des jeux vidéos.

J'ai pourtant une échelle de valeurs pourtant simple… Comment on fait pour gérer des cas comme ça sans se bouffer par l'intérieur ?


29/03/2014

Philpep's blog >> État de l'art du packaging python

Par : Philippe Pepiot
Tags:
python

La distribution des programmes python a toujours été décrit comme étant la bête noire des développeurs python. Les choses ont changés en 2013 mais il reste beaucoup de documentation obsolète sur internet et la confusion règne encore.

Qu'est ce qu'un package ?

Un package, ou dans la terminologie python une distribution c'est:

Pour créer un package on crée un fichier setup.py qui va avoir pour fonction:

Il y a deux sortes de distributions:

Le format egg est à python ce qu'est le .jar à Java, du moins dans l'idée. Le problème c'est que ce format n'est pas standard, l'outil pip ne sait pas les installer et les eggs ne tiennent pas compte des différents interpréteurs python (CPython, pypi, jython etc).

Petit historique

Tout les développeurs python on déjà entendu des noms comme distutils, setuptools, distribute et distutils2. Voilà un petit historique:

Pour résumer, il faut maintenant utiliser setuptools.

pip et pypi.python.org

pip est un gestionnaire de package pour python. Il va télécharger les distributions dans l'index pypi et les installer en tenant compte des dépendances. Certains packages sont référencés sur l'index sans pour autant que les distributions ne soient disponibles sur pypi, du coup pip avant la version 1.5 allait chercher par défaut des distributions dans les urls définies par le développeur dans le fichier setup.py et l'installation des packages pouvait prendre des plombes et parfois ne pas aboutir suivant la disponibilités des différents sites. Une campagne d'information a été faite auprès des développeurs enregistrés sur pypi pour les inciter à uploader les distributions directement sur l'index et dans la version 1.5 de pip les liens externes ne sont plus utilisés par défaut.

Une bonne façon de faire c'est de mettre à jours pip avec pip:

pip install -U pip

Le format wheel

Installer des distributions sources c'est bien, mais ça peut prendre du temps et ça nécessite pour certains packages d'avoir accès à un compilateur et a des librairies de développement, choses qu'on ne trouve pas toujours sur un environnement de production. Pour répondre à ce besoin le format compilé wheel a été crée. Les wheels tiennent compte de l'interpréteur et de l'architecture. Et la bonne nouvelle c'est que pip et setuptools prennent en charge les fichiers .whl

% pip install -U pip
% pip install -U setuptools
% pip install wheels
% pip wheel --wheel-dir=/tmp/wheels numpy==1.8.0
[....]
  Running setup.py bdist_wheel for numpy
  Destination directory: /tmp/wheels

% ls -l /tmp/wheels/
numpy-1.8.0-cp27-none-linux_x86_64.whl
% time pip install -f /tmp/wheels --no-index numpy==1.8.0
pip install -f /tmp/wheels --no-index numpy==1.8.0  0.96s user 0.12s system 99% cpu 1.083 total
% Et voilà numpy installé en moins d'une seconde !!

Ainsi un fichier comme Django-1.6.2-py2.py3-none-any.whl est compatible python 2 et 3 pour tout interpréteur alors qu'un fichier comme numpy-1.8.0-cp27-none-linux_x86_64.whl n'est compatible qu'avec CPython 2.7 sur linux 64 bit.

Toutefois si votre package utilise des librairies partagées (comme c'est le cas pour numpy), le fichier wheel va dépendre de la version de l'ABI de la librairie partagée. Donc il n'est pas conseillé de le partager directement sur l'index. Par contre vous pouvez très bien préparer des wheels pour un OS cible à partir d'un fichier requirements.txt.

% pip wheel --wheel-dir=/var/www/wheels/wheezy64 -r requirements.txt

Et sur la machine cible en production:

% pip install -f http://mirror/wheels/wheezy64 --no-index -r requirements.txt

Conclusion

Un pip/setuptools à jours, des wheels précompilés et voilà comment déployer du python sereinement même quand pypi.python.org est down le tout sans compilateur et en quelques secondes. Le packaging python devient enfin utilisable en tenant compte des contraintes de la production et avec les mêmes outils que le développeur utilise (pip/virtualenv/setuptools/wheel).

Voir aussi:


29/03/2014

Mon chti blog >> Une nanojail pour le courriel

Tags:
dovecot
opensmtpd
sjail

Jusqu'à présent, je confiais les courriels à destination de mon domaine à sendmail. Mais depuis ce message et un précédent billet, je dois me rendre à l'évidence: bapt@ va bien finir par virer sendmail et opensmtpd est quand même drôlement convivial.

Ce (long) billet va détailler l'installation pas à pas d'opensmtpd et de dovecot, le tout dans une nanojail.

sjail et opensmtpd

Pour commencer, je crée une nanojail mx2 et je lui ajoute opensmtpd:

dsx@blade>mkdir mx2
dsx@blade>sjail mx2 init
If you need log, don't forget to add '-l /usr/home/dsx/_jails/mx2/var/run/logpriv'
on syslogd_flags and restart (not reload) syslogd
You could edit do_init_pkg() function before adding any package to match your configuration
dsx@blade>sjail mx2 pkg install opensmtpd
Updating repository catalogue
digests.txz                                                                                                    100% 1868     1.8KB/s   1.8KB/s   00:00    
packagesite.txz                                                                                                100%   11KB  10.8KB/s  10.8KB/s   00:00    
Incremental update completed, 32 packages processed:
0 packages updated, 0 removed and 32 added.
The following 3 packages will be installed:
        Installing ca_root_nss: 3.15.4
        Installing libevent: 1.4.14b_3
        Installing opensmtpd: 5.4.2,1
The installation will require 3 MB more space
721 KB to be downloaded
ca_root_nss-3.15.4.txz                                                                                         100%  296KB 295.7KB/s 295.7KB/s   00:00    
libevent-1.4.14b_3.txz                                                                                         100%  123KB 123.5KB/s 123.5KB/s   00:00    
opensmtpd-5.4.2,1.txz                                                                                          100%  302KB 302.1KB/s 302.1KB/s   00:00    
Checking integrity... done
[1/3] Installing ca_root_nss-3.15.4... done
[2/3] Installing libevent-1.4.14b_3... done
[3/3] Installing opensmtpd-5.4.2,1...===> Creating users and/or groups.
Creating group '_smtpd' with gid '257'.
Creating user '_smtpd' with uid '257'.
Creating user '_smtpq' with uid '258'.
sed: not found
cannot create /etc/mail/mailer.conf: No such file or directory
 done
If you are upgrading from OpenSMTPD version 201303011853 or earlier, please 
follow the procedure below to update the permissions on the OpenSMTPD
spool directories:
  1. Stop 'smtpd' service:
     # /usr/local/etc/rc.d/smtpd stop
  2. Update permissions:
     # chown -R _smtpq:wheel /var/spool/smtpd/corrupt
     # chown -R _smtpq:wheel /var/spool/smtpd/purge
     # chown -R _smtpq:wheel /var/spool/smtpd/queue
     # chown -R _smtpq:wheel /var/spool/smtpd/temporary
  3. Start 'smtpd' service:
     # /usr/local/etc/rc.d/smtpd start

Je peux passer outre le message d'erreur concernant sed: je n'ai nul besoin du fichier /etc/mail/mailer.conf. En effet, je ne compte pas envoyer de courriel directement depuis cette jail (à l'aide de /usr/bin/mail par exemple). sjail est livré avec un script _sjail_opensmtpd, exécuté après l'installation d'opensmtpd et qui va créer les répertoires et fichiers manquant à son bon fonctionnement.

Passons au fichier de configuration. Sa limpidité ne mérite (à mon avis) aucun commentaire:

dsx@blade>cat mx2/etc/mail/smtpd.conf
listen on localhost
table aliases "/etc/mail/aliases"
accept for local alias <aliases> deliver to maildir
accept from any for domain "bsdsx.fr" alias <aliases> deliver to maildir
accept for any relay

Je crée mon utilisateur:

dsx@blade>sudo chroot mail pw groupadd users -g 1000
dsx@blade>echo 'bar' | sudo chroot mx2 pw useradd dsx -c 'Moi personnellement' -g users -m -s /usr/sbin/nologin -h 0

Je fais exprès d'afficher le mot de passe de mon utilisateur car avec la syntaxe suivante:

dsx@blade>sudo chroot mx2 pw useradd bar -c 'bar user' -g users -m -s /usr/sbin/nologin -h 0
password for user bar:

on ne peut pas vérifier la saisie. Il est temps de faire un premier essai:

dsx@blade>sudo chroot mail /usr/local/sbin/smtpd -n -f /etc/mail/smtpd.conf
configuration OK
dsx@blade>sudo chroot mail /usr/local/sbin/smtpd -d -f /etc/mail/smtpd.conf
info: OpenSMTPD 5.4.2p1 starting
info: startup

Depuis un autre terminal:

dsx@blade>telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 blade.bsdsx.fr ESMTP OpenSMTPD
EHLO localhost
250-blade.bsdsx.fr Hello localhost [127.0.0.1], pleased to meet you
250-8BITMIME
250-ENHANCEDSTATUSCODES
250-SIZE 36700160
250-DSN
250 HELP
MAIL FROM: <dsx@localhost>
250 2.0.0: Ok
RCPT TO: <dsx@localhost>
250 2.1.5 Destination address valid: Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: first try with telnet and localhost
Ok
.
250 2.0.0: 3f78e126 Message accepted for delivery
QUIT
221 2.0.0: Bye
Connection closed by foreign host.

Côté serveur:

smtp-in: New session 36daa667726edf1e from host localhost [127.0.0.1]
smtp-in: Accepted message 3f78e126 on session 36daa667726edf1e: from=<dsx@localhost>, to=<dsx@localhost>, size=49, ndest=1, proto=ESMTP
delivery: Ok for 3f78e126aa0adf4c: from=<dsx@localhost>, to=<dsx@localhost>, user=dsx, method=maildir, delay=16s, stat=Delivered
smtp-in: Closing session 36daa667726edf1e

Un petit tour dans mx2/home/dsx me confirme qu'un répertoire Maildir a bien été créé et peuplé:

dsx@blade>sudo ls -Rl mx2/home/dsx/Maildir/
total 24
drwx------  2 2001  1000  512 Apr  2 21:51 cur
drwx------  2 2001  1000  512 Apr  2 21:51 new
drwx------  2 2001  1000  512 Apr  2 21:51 tmp
mx2/home/dsx/Maildir/cur:
total 0
mx2/home/dsx/Maildir/new:
total 8
-rw-------  1 2001  1000  270 Apr  2 21:51 1396468291.63662.blade.bsdsx.fr
mx2/home/dsx/Maildir/tmp:
total 0

Les essais avec localhost sont concluant, qu'en est-il de mon domaine ?

dsx@blade>telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 blade.bsdsx.fr ESMTP OpenSMTPD
EHLO localhost
250-blade.bsdsx.fr Hello localhost [127.0.0.1], pleased to meet you
[ snip ]
MAIL FROM: <dsx@bsdsx.fr>
250 2.0.0: Ok
RCPT TO: <dsx@bsdsx.fr>
250 2.1.5 Destination address valid: Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: second try with telnet and domain
Ok
.
250 2.0.0: eb6d735f Message accepted for delivery
quit
221 2.0.0: Bye
Connection closed by foreign host.

Côté serveur:

smtp-in: New session d399dbeabc35b0b2 from host localhost [127.0.0.1]
smtp-in: Accepted message eb6d735f on session d399dbeabc35b0b2: from=<dsx@bsdsx.fr>, to=<dsx@bsdsx.fr>, size=47, ndest=1, proto=ESMTP
delivery: Ok for eb6d735f96e20eca: from=<dsx@bsdsx.fr>, to=<dsx@bsdsx.fr>, user=dsx, method=maildir, delay=20s, stat=Delivered
smtp-in: Closing session d399dbeabc35b0b2

Une fois mx2/etc/mail/aliases renseigné, on peut faire un dernier test:

dsx@blade>echo 'root: dsx' >> mx2/etc/mail/aliases
dsx@blade>telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 blade.bsdsx.fr ESMTP OpenSMTPD
EHLO localhost
250-blade.bsdsx.fr Hello localhost [127.0.0.1], pleased to meet you
[ snip ]
MAIL FROM: <root@localhost>
250 2.0.0: Ok
RCPT TO: <root@bsdsx.fr>
250 2.1.5 Destination address valid: Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: third try with aliases
Ok
.
250 2.0.0: de45e7b5 Message accepted for delivery
quit
221 2.0.0: Bye
Connection closed by foreign host.

Côté serveur:

smtp-in: New session c4d1141eb43fc66f from host localhost [127.0.0.1]
smtp-in: Accepted message 9bce8fd7 on session c4d1141eb43fc66f: from=<root@localhost>, to=<root@bsdsx.fr>, size=36, ndest=1, proto=ESMTP
delivery: Ok for 9bce8fd7d74d5f77: from=<root@localhost>, to=<root@bsdsx.fr>, user=root, method=maildir, delay=31s, stat=Delivered
smtp-in: Closing session c4d1141eb43fc66f

Le fichier d'alias n'a pas été pris en compte (user=root) car, comme expliqué dans le fichier de configuration livré par défaut, je n'ai pas lancé la commande kivabien:

dsx@blade>sudo chroot mx2 /usr/local/sbin/smtpctl update table aliases
command succeeded

Côté serveur:

info: Table "aliases" successfully updated

Un dernier test pour la route:

dsx@blade>echo 'pouet: dsx' >> mx2/etc/mail/aliases
dsx@blade>sudo chroot mx2 /usr/local/sbin/smtpctl update table aliases
command succeeded
dsx@blade>telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 blade.bsdsx.fr ESMTP OpenSMTPD
EHLO localhost
250-blade.bsdsx.fr Hello localhost [127.0.0.1], pleased to meet you
[ snip ]
MAIL FROM: <dsx@localhost>
250 2.0.0: Ok
RCPT TO: <root@bsdsx.fr>
250 2.1.5 Destination address valid: Recipient ok
RCPT TO: <pouet@localhost>
250 2.1.5 Destination address valid: Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: test alias
OK
.
250 2.0.0: 14a350bf Message accepted for delivery
quit
221 2.0.0: Bye
Connection closed by foreign host.

Côté serveur:

info: Table "aliases" successfully updated
smtp-in: New session cf35c16799b69887 from host localhost [127.0.0.1]
smtp-in: Accepted message 14a350bf on session cf35c16799b69887: from=<dsx@localhost>, to=<root@bsdsx.fr>, size=24, ndest=1, proto=ESMTP
smtp-in: Accepted message 14a350bf on session cf35c16799b69887: from=<dsx@localhost>, to=<pouet@localhost>, size=24, ndest=1, proto=ESMTP
delivery: Ok for 14a350bf0e11c49d: from=<dsx@localhost>, to=<root@bsdsx.fr>, user=dsx, method=maildir, delay=32s, stat=Delivered
delivery: Ok for 14a350bfceec2d5a: from=<dsx@localhost>, to=<pouet@localhost>, user=dsx, method=maildir, delay=21s, stat=Delivered
smtp-in: Closing session cf35c16799b69887

Voila mon opensmtpd fonctionnel (pas tout à fait, lire Update 3 en fin de billet). Il est temps de passer à dovecot.

sjail et dovecot

Je commence par installer dovecot (en version 2)

dsx@blade>sjail mx2 pkg install dovecot2
Updating repository catalogue
The following 1 packages will be installed:
        Installing dovecot2: 2.2.10
The installation will require 14 MB more space
3 MB to be downloaded
dovecot2-2.2.10.txz                                                                                            100% 2704KB   2.6MB/s   2.6MB/s   00:00    
Checking integrity... done
[1/1] Installing dovecot2-2.2.10...===> Creating users and/or groups.
Creating group 'dovecot' with gid '143'.
Creating group 'dovenull' with gid '144'.
Creating user 'dovecot' with uid '143'.
Creating user 'dovenull' with uid '144'.
 done
---------------------------------------------------------------------
 You can get basic IMAP and POP3 services running by enabling
 dovecot in the /etc/rc.conf file.
        dovecot_enable
                (bool) If set to ``YES'', run the dovecot command
                at boot time.
 In the basic configuration Dovecot will authenticate users against
 the system's passwd file and use the default /var/mail/$USER mbox
 files.
        dovecot_config
                (str) Path to dovecot configuration file(s).
                Default /usr/local/etc/dovecot/dovecot.conf.
 To start multiple instances of dovecot set dovecot_config to
 a space separated list of configuration files.
---------------------------------------------------------------------

Je ne vais pas utiliser l'emplacement par défaut du fichier de configuration. L'objectif est d'avoir un unique fichier qui ne définit que ce dont j'ai besoin. opensmtpd place mes courriels dans $HOME/Maildir, charge à dovecot de me les fournir.

dsx@blade>touch mx2/etc/mail/dovecot.conf
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -n
# 2.2.10: /etc/mail/dovecot.conf
# OS: FreeBSD 10.0-RELEASE amd64  
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -F

Côté client:

dsx@blade>telnet 127.0.0.1 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

Radical. En lisant mx2/usr/local/share/doc/dovecot/dovecont.conf, je me dis que mx2/usr/local/share/doc/dovecot/conf.d va devenir le dernier salon où l'on cause (cause == grep / less) Un peu de log ne me fera pas de mal. Côté client, je persiste avec telnet 127.0.0.1 143

dsx@blade>echo 'log_path = /dev/stderr' >> mx2/etc/mail/dovecot.conf
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -F
Apr 04 16:34:46 master: Info: Dovecot v2.2.10 starting up for imap, pop3, lmtp
Apr 04 16:54:35 imap-login: Fatal: /dev/urandom doesn't exist, currently we require it
Apr 04 16:54:35 master: Error: service(imap-login): command startup failed, throttling for 2 secs

Si pour l'instant j'utilise un chroot, je sais qu'avec une jail le répertoire dev sera peuplé. Pour l'instant, je passe en manuel:

dsx@blade>sudo mount -t devfs devfs mx2/dev/
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -F
Apr 04 16:57:47 master: Info: Dovecot v2.2.10 starting up for imap, pop3, lmtp
Apr 04 16:34:50 imap-login: Fatal: Couldn't parse private ssl_key: error:0906D06C:PEM routines:PEM_read_bio:no start line: Expecting: ANY PRIVATE KEY
Apr 04 16:34:50 master: Error: service(imap-login): command startup failed, throttling for 2 secs

C'est un peu tôt pour le ssl, je le désactive pour l'instant.

dsx@blade>echo 'ssl = no' >> mx2/etc/mail/dovecot.conf
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -n
# 2.2.10: /etc/mail/dovecot.conf
# OS: FreeBSD 10.0-RELEASE amd64  
log_path = /dev/stderr
ssl = no
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -F
Apr 04 16:39:34 master: Info: Dovecot v2.2.10 starting up for imap, pop3, lmtp
Apr 04 16:39:37 auth: Fatal: No passdbs specified in configuration file. PLAIN mechanism needs one
Apr 04 16:39:37 master: Error: service(auth): command startup failed, throttling for 2 secs
Apr 04 16:39:37 imap-login: Info: Disconnected: Auth process broken (disconnected before auth was ready, waited 0 secs): user=<>, rip=127.0.0.1, lip=127.0.0.1, secured, session=<mT+yfDj27QB/AAAB>

Hum, de l'authentification.

dsx@blade>cat <<EOF >> mx2/etc/mail/dovecot.conf 
? userdb {
?   driver = passwd
? }
? EOF
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -n
# 2.2.10: /etc/mail/dovecot.conf
# OS: FreeBSD 10.0-RELEASE amd64  
log_path = /dev/stderr
ssl = no
userdb {
  driver = passwd
}
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -F
Apr 04 16:46:36 master: Info: Dovecot v2.2.10 starting up for imap, pop3, lmtp
Apr 04 16:46:42 auth: Fatal: No passdbs specified in configuration file. PLAIN mechanism needs one
Apr 04 16:46:42 master: Error: service(auth): command startup failed, throttling for 2 secs
Apr 04 16:46:42 imap-login: Info: Disconnected: Auth process broken (disconnected before auth was ready, waited 0 secs): user=<>, rip=127.0.0.1, lip=127.0.0.1, secured, session=<q2cMljj2pAB/AAAB>

Et maintenant ça cause passdb

dsx@blade>cat << EOF >> mx2/etc/mail/dovecot.conf
? passdb {
?   driver = pam
? }
? EOF
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -n
# 2.2.10: /etc/mail/dovecot.conf
# OS: FreeBSD 10.0-RELEASE amd64  
log_path = /dev/stderr
ssl = no
userdb {
  driver = passwd
}
passdb {
  driver = pam
}
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -F
Apr 04 16:49:14 master: Info: Dovecot v2.2.10 starting up for imap, pop3, lmtp

Côté client:

dsx@blade>telnet 127.0.0.1 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
a0 LOGIN dsx mon_super_mot_de_passe
a0 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in
a1 select inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted.
* 113 EXISTS
* 110 RECENT
* OK [UNSEEN 1] First unseen.
* OK [UIDVALIDITY 1396496805] UIDs valid
* OK [UIDNEXT 114] Predicted next UID
a1 OK [READ-WRITE] Select completed (0.007 secs).
a2 logout
* BYE Logging out
a2 OK Logout completed.
Connection closed by foreign host.

Côté serveur:

Apr 04 17:05:41 imap-login: Info: Login: user=<dsx>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=83228, secured, session=<llLk2Tj20wB/AAAB>
Apr 04 17:05:52 imap(dsx): Info: Disconnected: Logged out in=26 out=724

Je pense que le plus dur est fait.

ssl

Les tests en local avec les mots de passe en clair, c'est pratique mais une mise en production nécessite un peu plus de sécurité.

dovecot

Je force l'utilisation de ssl et je définis l'emplacement de mon certificat et de sa clef (préalablement copiés). Cette dernière nécessitant un mot de passe, je dois passer l'option -p à dovecot:

dsx@blade>cat mx2/etc/mail/dovecot.conf
log_path = /dev/stderr
userdb {
  driver = passwd
}
passdb {
  driver = pam
}
ssl = required
ssl_cert = </etc/mail/mx2.bsdsx.fr.pem
ssl_key = </etc/mail/mx2.bsdsx.fr.key
service imap-login {
  inet_listener imaps {
    ssl = yes
  }
}
dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -p -F
Give the password for SSL keys: 
Apr 04 18:18:05 master: Info: Dovecot v2.2.10 starting up for imap, lmtp

A partir de maintenant, le service imaps disponible sur le port 993 requiert l'utilisation de ssl. Il est temps d'abandonner telnet et de passer à openssl s_client:

dsx@blade>openssl s_client -connect localhost:993
[snip des trucs ssl / x509 / toussa ]
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
a0 login dsx mon_super_mot_de_passe
a0 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in
a1 select inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted.
* 113 EXISTS
* 0 RECENT
* OK [UNSEEN 1] First unseen.
* OK [UIDVALIDITY 1396496805] UIDs valid
* OK [UIDNEXT 114] Predicted next UID
a1 OK [READ-WRITE] Select completed (0.000 secs).
a2 logout
* BYE Logging out
a2 OK Logout completed.
closed

C'est terminé pour dovecot, passons à opensmtpd.

opensmtpd

Je modifie légèrement mx2/etc/mail/smtpd.cnf:

pki bsdsx.fr certificate "/etc/mail/mx2.bsdsx.fr.pem"
pki bsdsx.fr key "/etc/mail/mx2.bsdsx.fr.key"
listen on localhost
listen on localhost smtps pki bsdsx.fr auth
table aliases "/etc/mail/aliases"
accept for local alias <aliases> deliver to maildir
accept from any for domain "bsdsx.fr" alias <aliases> deliver to maildir
accept for any relay

Côté serveur:

dsx@blade>sudo chroot mx2 /usr/local/sbin/smtpd -d -f /etc/mail/smtpd.conf
passphrase for bsdsx.fr: 
info: OpenSMTPD 5.4.2p1 starting
info: startup

Côté client:

dsx@blade>netstat -an -f inet | awk ' $4 ~ /(25|465)$/ { print }'
tcp4       0      0 127.0.0.1.25           *.*                    LISTEN
tcp4       0      0 127.0.0.1.465          *.*                    LISTEN
dsx@blade>netstat -an -f inet6 | awk ' $4 ~ /(25|465)$/ { print }'
tcp6       0      0 ::1.25                 *.*                    LISTEN
tcp6       0      0 ::1.465                *.*                    LISTEN
dsx@blade>telnet 127.0.0.1 465
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
EHLO localhost
Connection closed by foreign host.

Côté serveur:

smtp-in: New session fe52eb243336f4ef from host localhost [127.0.0.1]
smtp-in: Disconnecting session fe52eb243336f4ef: IO error: error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol

Côté client (l'encodage du login et du mot de passe sont fait à l'aide de perl -MMIME::Base64 -e 'print encode_base64("machin_a_encoder");'):

dsx@blade>openssl s_client -connect localhost:465
[ snip des trucs ssl / certificat / clef / ... ]
220 blade.bsdsx.fr ESMTP OpenSMTPD
EHLO localhost 
250-blade.bsdsx.fr Hello localhost [127.0.0.1], pleased to meet you
[ snip ]
250 HELP
AUTH LOGIN
334 VXNlcm5hbWU6
ZHN4
334 UGFzc3dvcmQ6
ABCDEFGHIJK=
235 2.0.0: Authentication succeeded
MAIL FROM: <dsx@bsdsx.fr> auth=<dsx@bsdsx.fr>
250 2.0.0: Ok
rcpt to: <root@localhost>
250 2.1.5 Destination address valid: Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: test ssl
Ok
.
250 2.0.0: d378415c Message accepted for delivery
quit
221 2.0.0: Bye
read:errno=0

Le 'rcpt to' en minuscule n'est pas une typo, 'R' est une commande pour openssl s_client comme indiqué ici:

Pressing "R" in an s_client session causes openssl to renegotiate. Try entering "rcpt to:" instead of "RCPT TO".

opensmtpd et dovecot

Il reste à relier le tout. On trouvera sur le nain ternet moultes exemples à base de

deliver to mda "/usr/local/libexec/dovecot/dovecot-lda -f %{sender} -d %{dest}"

C'est pourquoi je vais choisir une configuration basée sur le protocol lmtp. Pour dovecot, c'est assez simple:

dsx@blade>cat mx2/etc/mail/dovecot.conf
log_path = /dev/stderr
userdb {
  driver = passwd
}
passdb {
  driver = pam
}
ssl = required
ssl_cert = </etc/mail/mx2.bsdsx.fr.pem
ssl_key = </etc/mail/mx2.bsdsx.fr.key
protocols = imap lmtp
service imap-login {
  inet_listener imaps {
    ssl = yes
  }
}
service lmtp {
  unix_listener lmtp {
    mode = 0666
  }
}

Reste à trouver la socket:

dsx@blade>sudo chroot mx2 /usr/local/sbin/dovecot -F
Apr 03 22:15:32 master: Info: Dovecot v2.2.10 starting up for imap, lmtp

Et dans un autre terminal:

dsx@blade>sudo find mx2/ -type s -name lmtp
mx2/var/run/dovecot/lmtp

Pour opensmtpd c'est carrément trivial:

pki bsdsx.fr certificate "/etc/mail/mx2.bsdsx.fr.pem"
pki bsdsx.fr key "/etc/mail/mx2.bsdsx.fr.key"
listen on localhost
listen on localhost smtps pki bsdsx.fr auth
table aliases "/etc/mail/aliases"
accept for local alias <aliases> deliver to lmtp "/var/run/dovecot/lmtp"
accept from any for domain "bsdsx.fr" alias <aliases> deliver to lmtp "/var/run/dovecot/lmtp"
accept for any relay

Mise en production

La jail:

[ extrait /etc/jail.conf ]
mx2 {
    host.hostname = "$name.bsdsx.fr";
    ip4.addr = lo0|127.0.0.1; #Ne JAMAIS faire ça
    ip6.addr = lo2|2a02:27d0:100:f205:a642::9;
    exec.start  = "/usr/local/sbin/smtpd -f /etc/mail/smtpd.conf";
    exec.start += "/usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -p";
}
dsx@blade>sudo jail -c mx2
mx2: created
passphrase for bsdsx.fr:

Update 2:

Allez à la fin de ce billet pour obtenir la configuration définitive !!!

J'assume parfaitement le fait de devoir saisir 2 fois (malgré le prompt qui n'apparait qu'une fois) le mot de passe de ma clef.

dsx@blade>jls -j mx2
   JID  IP Address      Hostname                      Path
   175  127.0.0.1       mx2.bsdsx.fr                  /usr/home/dsx/_jails/mx2
dsx@blade>netstat -an -f inet | awk ' $4 ~ /(25|465|993|143)$/ { print }'
tcp4       0      0 127.0.0.1.993          *.*                    LISTEN
tcp4       0      0 127.0.0.1.143          *.*                    LISTEN
tcp4       0      0 127.0.0.1.25           *.*                    LISTEN
tcp4       0      0 127.0.0.1.465          *.*                    LISTEN
dsx@blade>netstat -an -f inet6 | awk ' $4 ~ /(25|465|993|143)$/ { print }'
tcp6       0      0 2a02:27d0:100:f2.993   *.*                    LISTEN
tcp6       0      0 2a02:27d0:100:f2.143   *.*                    LISTEN
tcp6       0      0 2a02:27d0:100:f2.25    *.*                    LISTEN
tcp6       0      0 2a02:27d0:100:f2.465   *.*                    LISTEN

Inutile d'écouter sur une adresse ipv4 publique, mon ami pf est là pour ça:

[ extrait ]
mx4 = 127.0.0.1
mx6 = une:adresse::ipv6
mon_ip_publique = 1.2.3.4
rdr pass on $ext_if inet proto tcp to $mon_ip_publique port { smtp, smtps, imaps } -> $mx4
pass in quick on $ext_if inet6 proto tcp from any to $mx6 port { smtp, smtps, imaps }

Au prochain épisode

En espérant être un peu moins long :)

Update:

Si on utilise l'imap sur localhost, il va y avoir un problème de correspondance avec le certificat (pour mx2.bsdsx.fr et le nom d'hôte (localhost). Pour éviter un message d'avertissement il suffit de rajouter une section local:

dsx@blade>cat mx2/etc/mail/dovecot.conf
userdb {
  driver = passwd
}
passdb {
  driver = pam
}
ssl = required
ssl_cert = </etc/mail/mx2.bsdsx.fr.pem
ssl_key = </etc/mail/mx2.bsdsx.fr.key
protocols = imap lmtp
service imap-login {
  inet_listener imap {
    ssl = no
  }
  inet_listener imaps {
    ssl = yes
  }
}
service lmtp {
  unix_listener lmtp {
    mode = 0666
  }
}
local localhost {
  protocol imap {
    ssl_cert = </etc/mail/localhost.pem
    ssl_key = </etc/mail/_localhost.key
  }
}

Ici par contre, la clef n'est pas protégée par un mot de passe.

Update 2:

Quand on utilise les jails, ne JAMAIS faire:

ip4.addr = lo0|127.0.0.1;

Car lors de suppression de la jail, l'adresse 127.0.0.1 sera considérée comme un alias et retirée de l'interface lo0 Je vous laisse imaginer le torrent de chokapik que peut entrainer un système où 127.0.0.1 n'est plus joignable.

Voici donc la configuration en production à ce jour:

La jail:

mx2 {
    host.hostname = "$name.bsdsx.fr";
    ip4 = inherit;
    ip6.addr = "lo2|2a02:27d0:100:f205:a642::9";
    exec.start  = "/usr/local/sbin/smtpd -f /etc/mail/smtpd.conf";
    exec.start += "/usr/local/sbin/dovecot -c /etc/mail/dovecot.conf -p";
}

dovecot:

listen = 127.0.0.1, ::

openstmpd:

listen on localhost
listen on localhost smtps pki bsdsx.fr auth

La configuration de pf reste inchangée.

Update 3:

La configuration d'opensmtpd est sujette au problème décrit ici: la jail mx2 ne considère pas les adresses "@blade.bsdsx.fr" comme étant locales et tente de les relayer, ce qui provoque une boucle. Ma configuration finale:

pki bsdsx.fr certificate "/etc/mail/mx2.bsdsx.fr.pem"
pki bsdsx.fr key "/etc/mail/mx2.bsdsx.fr.key"
listen on localhost
listen on localhost smtps pki bsdsx.fr auth
table aliases "/etc/mail/aliases"
accept for local alias <aliases> deliver to lmtp "/var/run/dovecot/lmtp"
accept from any for domain "*.bsdsx.fr" alias <aliases> deliver to lmtp "/var/run/dovecot/lmtp"
accept for any relay

En espérant en finir avec les mises à jour, toutes mes excuses par avance à ceux qui auraient eu la mauvaise idée de suivre mes indications.

Update 4:

J'aurais pu tricher et modifier 'Update 3' mais je ne mange pas de ce pain là:

pki bsdsx.fr certificate "/etc/mail/mx2.bsdsx.fr.pem"
pki bsdsx.fr key "/etc/mail/mx2.bsdsx.fr.key"
listen on localhost
listen on localhost smtps pki bsdsx.fr auth
table aliases "/etc/mail/aliases"
table domains { bsdsx.fr, blade.bsdsx.fr }
accept for local alias <aliases> deliver to lmtp "/var/run/dovecot/lmtp"
accept from any for domain <domains> alias <aliases> deliver to lmtp "/var/run/dovecot/lmtp"
accept for any relay

La der des der ?