Planet Asrall

August 21, 2016

Luc Didry

Joyeux Ray’s day à tou·­te·s !

Le Ray’s day, c’est la fête de la lecture, quelle qu’elle soit, quel que soit le support. Ce qui compte, ce sont les histoires, leurs auteurs et les lecteurs. Le Ray’s day a lieu le 22 août, jour de l’an­ni­ver­saire de Ray Brad­bury grand amou­reux des livres disparu en 2012 et qui a inspiré Neil Jomunsi pour créer cette jour­née spéciale :-)

N’écri­vant pas (j’ai bien essayé de m’y mettre l’an­née dernière, mais je n’ai jamais fini), que pouvais-je faire pour célé­brer ce jour si parti­cu­lier ? Qu’ai-je dans mes poches ? Un esprit libriste, des compé­tences en infor­ma­tiques… Diffi­cile. Puis j’ai repensé à ce que j’avais fait l’an­née dernière : outre un tirage au sort pour gagner un epub, j’avais fait un livre numé­rique du web-comic de mon cousin.

Bien, un epub, ça c’est dans mes cordes. Mais que mettre dedans ? Il faut que ce soit libre, que ce soit inté­res­sant, qu’il y en assez pour remplir un livre… Et j’ai pensé au Copy­right Madness de Lionel Maurel et Thomas Four­meux. Toutes les semaines, ils traquent les dérives de la « propriété intel­lec­tuelle » et nous rappellent que « Si la propriété, c’est le vol ; la propriété intel­lec­tuelle, c’est le LOL ! »

Un petit script en Perl par ci, un peu de Sigil par là, saupou­dré d’une pincée de feuille de style de Frama­book et d’huile de coude et voilà !

Je vous livre un recueil 2015–2016 du Copy­right Madness !

Merci à nos deux senti­nelles vigi­lantes de nous offrir cette revue hebdo­ma­daire en CC-0 et tout spécia­le­ment à Lionel Maurel d’avoir écrit la préface du recueil :-)

PS : le recueil ne court que de 2015 à 2016 car avant 2015, le Copy­right Madness se basait sur Storify et je ne suis pas sûr que ça n’en­freigne pas leurs termes de service (« Attempt to access or search the Storify Service or Service Content or down­load Service Content from the Storify Service through the use of any engine, soft­ware, tool, agent, device or mecha­nism (inclu­ding spiders, robots, craw­lers, data mining tools or the like) other than the soft­ware and/or search agents provi­ded by Storify or other gene­rally avai­lable third party web brow­sers; ») :-P

Parta­ger

Flattr this!

by Luc at August 21, 2016 10:01 PM

August 16, 2016

Sebastien Badia

Prosopopee ♥

Après avoir longtemps cherché la solution répondant à mes besoins en terme de galerie photos, je crois que j'ai trouvé :)

Solutions testées

  • ZenPhoto, Plus en mode CMS, il y a une tonne de plugins, et d'intégration, nécessite une base de données.
  • Lychee, alternative séduisante (graphiquement), assez actif niveau dev. mais pareil il faut une base de données, et la visu est en mode galerie.
  • Lazygal, bon là c'est statique, mais… il faut avoir des dons en CSS si on veut que ça ressemble à qqch :)

Prosopopee

« More or less a small clone of exposure.co in form of a static generator. For those of you who don't know what exposure.co is, this allows you to tell a story with your pictures. »

  • prosopopee, C'est une galerie statique, mais qui permet de raconter une histoire, plus en mode fil, que simple galerie. J'adore!

J'ai d'ailleurs commencé à remplir mes pérégrinations…

Tips

Bon, une galerie photo, c'est cool, mais quid de la taille des photos et de l'aisance de visualisation (petite ligne ADSL…), la solution vient peut être avec le jpeg progressif !!

Avec un petit script rapide :)

#!/bin/sh
file=$1
set -ex
# On optimse :)
jpegtran -copy none -optimize "${file}" > "temp_${file}.jpg"
rm -f "${file}"
# Puis on passe l'encodage en "Progressive DCT, Huffman coding"
jpegtran -copy none -progressive "temp_${file}.jpg" > "${file}"
rm -f "temp_${file}.jpg"
# Et enfin on vire les metadata (exif)
mat "${file}"

Il reste donc plus qu'a écrire l'histoire :)

by Sebastien Badia at August 16, 2016 06:00 AM

August 13, 2016

Florent Peterschmitt

ActiveSync avec Z-Push, le mail

Z-Push est une implémentation en PHP du protocol ActiveSync de Microsoft. Il permet de synchroniser ses mails, calendriers et contacts. Pour l’instant je ne couvrirai que le mail, le calendrier viendra plus tard éventuellement.

Le guide d’installation est assez spartiate.

Comme d’hab, je fais mes install sur CentOS 7 et avec PHP-FPM.

PHP

Déjà, installez PHP 5.6. Ça ne fonctionnera pas du tout avec PHP 7, pour le moment en tout cas. J’ai testé, laissez tomber l’idée. À moins d’avoir du temps pour dev, mais si eux n’ont pas encore sorti une version “PHP 7 proof”, c’est que ça n’est sans doute pas si simple.

https://webtatic.com/packages/php56/

IMAP et SMTP

Avoir un serveur IMAP et SMTP disponible et déjà configuré.

Normalement ces deux bouzins là sont assez connus pour qu’Internet soit truffé de tutos…

Paquets

Les paquets ne sont pas signés malheureusement :/

/etc/yum.repos.d/z-push.repo

[z-push]
name=Z-Push noarch Enterprise Linux 7 - $basearch
baseurl=http://repo.z-hub.io/z-push:/final/RHEL_7
failovermethod=priority
enabled=1
gpgcheck=0
yum makecache
yum install z-push-common z-push-backend-imap z-push-ipc-sharedmemory

On pourra utiliser z-push-ipc-memcached à la place de sharedmemory.

Nginx et PHP-FPM

/etc/nginx/conf.d/peterschmitt.fr.conf

server {
    server_name peterschmitt.fr;

    location /Microsoft-Server-ActiveSync {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;

        include fastcgi_params_z-push;
        fastcgi_param SCRIPT_FILENAME /usr/share/z-push/index.php;
        fastcgi_param DOCUMENT_ROOT /usr/share/z-push/;
        fastcgi_pass unix:/srv/php-fpm/socks/z-push;
    }
}

La configuration automatique tente de joindre le domaine de l’adresse mail à configurer, sur la location détaillée ici.

J’ai récupéré cette information depuis la configuration Apache de Z-Push.

/etc/php-fpm.d/z-push.conf

[z-push]
access.log = access.log
listen = /srv/php-fpm/socks/z-push
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

user = z-push
group = z-push

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

slowlog = www-slow.log

chdir = /usr/share/z-push

catch_workers_output = yes

php_flag[display_errors] = on
php_admin_value[error_log] = php-error.log
php_admin_flag[log_errors] = on

php_value[session.save_handler] = files
php_value[session.save_path] = /session

Système

Les paquets sont configurés pour l’utilisateur apache, car il existe un paquet embarquant de la conf Apache. On adapte tout ça :

useradd z-push
chgrp z-push /etc/z-push/*
chown -R z-push:z-push /var/log/z-push/
chown -R z-push:z-push /var/lib/z-push/
systemctl restart php-fpm
systemctl restart nginx

Configuration

Faire in tour dans /etc/z-push/imap.conf.php et adapter les dossiers IMAP en fonction de ce qui est actif sur le serveur IMAP, puis passer la define IMAP_FOLDER_CONFIGURED à true.

Configurez-y aussi la connexion au serveur IMAP.

Pour SMTP, cherchez la variable $imap_smtp_params. Le fichier de configuration est très bien documenté, l’idéal étant une configuration du type :

<?php
$imap_smtp_params = array(
    'host' => 'ssl://smtp.peterschmitt.fr',
    'port' => 465,
    'auth' => true,
    'localhost' => 'smtp.peterschmitt.fr',
    'username' => 'imap_username',
    'password' => 'imap_password');

Test

Accéder à http://localhost/Microsoft-Server-ActiveSync et tester l’authentification.

Si déjà ça a fonctionné, vous pouvez passer à la suite, à savoir configurer un client mail voulant causer ActiveSync, comme un client mail mobile par exemple.

Enfin, testez l’envoi de mail en scrutant les logs de votre serveur mail.

by Florent Peterschmitt at August 13, 2016 07:33 PM

August 12, 2016

Florent Peterschmitt

Commentaires auto-hébergés avec Isso

MAJ 2016/08/18 : sécurité : owner root:root et dossier var séparé accessible à l’utilisateur isso.

Isso, petit service sympathique, écrit en Python et qui permet d’auto-héberger des commentaires sur un blog, par exemple.

Il se présente comme une alternative à Disqus

D’après la documentation de la configuration du serveur Isso, on y trouve :

  • Une instance peut gérer plusieurs sites
  • Une modération
  • Nodifications par mail
  • Anti-spam léger, qui correspond plutôt à un rate-limit

Installation

https://posativ.org/isso/docs/install/

L’installation ne semble pas bien fonctionner, il m’a fallu installer quelques packages python en plus.

Voir cette issue GitHub

yum install -y python-virtualenv python-setuptools python-devel sqlite gcc make sqlite
useradd -m isso -s /sbin/nologin
chown root:root /home/isso
mkdir /home/isso/var
chown isso:isso /home/isso/var
export HOME=/home/isso
virtualenv /home/isso/pyvenv-isso
source /home/isso/pyvenv-isso/bin/activate
pip install isso
pip install werkzeug
pip install configparser
pip install ipaddr

Configuration Isso

Documentation

/home/isso/isso.ini

[general]
dbpath = /home/isso/var/isso.db
host = https://florent.peterschmitt.fr
log-file = /home/isso/var/isso.log
notify = smtp
max-age = 15m

[server]
listen = http://localhost:8081

[smtp]
host = localhost
port = 25
security = none
to = comments@peterschmitt.fr
from = "Isso" <isso@peterschmitt.fr>

[guard]
enabled = true
ratelimit = 2
direct-reply = 3
reply-to-self = false
require-email = false

Configuration Nginx

server {
    server_name florent.peterschmitt.fr;

    location /isso/ {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://localhost:8081/;
    }
}

Autostart

/etc/systemd/system/isso.service

[Unit]
Description=Isso Blog Comment

[Service]
User=isso
ExecStart=/home/isso/pyvenv-isso/bin/isso -c /home/isso/isso.ini run

[Install]
WantedBy=multi-user.target

Exéctuter ensuite

systemctl daemon-reload
systemctl enable isso.service
systemctl restart isso.service

Intégration

Autant aller voir la documentation directement : https://posativ.org/isso/docs/quickstart/#integration

Pour ma part le thème octopress de Pelican s’en charge via l’option ISSO_SITEURL="https://florent.peterschmitt.fr/isso".

Si samarchpa

Ouvrez la console de développement de votre navigateur, et trouvez les erreurs que JS pourrait remonter. Accédez aux URL Isso à la main, avec curl par exemple, depuis l’extérieur et depuis l’intérieur.

Exemple :

curl -H "Host: florent.peterschmitt.fr" "http://localhost:8081/?uri=%2Fletsencrypt-certbot-naemon.html&nested_limit=5"

On ne doit pas avoir de message du type il me manque l’uri.

by Florent Peterschmitt at August 12, 2016 09:58 AM

August 11, 2016

Florent Peterschmitt

Let’s Encrypt, Certbot et Naemon

Ou comment automatiser le renouvellement des certificats avec la supervision.

Le choix de Naemon s’est fait pour quelques raisons :

  • Je n’ai qu’un petit serveur et Naemon n’est pas lourd
  • Comme il n’y a qu’une seule machine, pas besoin d’un truc extra pour la conf
  • Je me fiche d’avoir une sup poussée ou d’avoir des graphes, pour mes besoins perso, même si c’est cool

En fait peu importe la méthode de supervision : il s’agit en fait de déclencher la génération des certificats en peu en avance, sur détection de l’expiration.

Alors, oui, je sais qu’on peut simplement demander à Certbot de mettre à jour et il va se débrouiller pour savoir si le certificat est sur le point d’expirer. Mais autant les graphes c’est cool, et je m’en fiche, autant un truc qui ne va se mettre en route que quand il y en a vraiment besoin, c’est d’autant plus cool =D

Principe

  • On met de la sup sur son certificat. Chez moi la vérification passe par un plugin qui check directement le service, ici un nginx
  • On configure un event handler sur cette sup
  • L’event handler va lancer certbot, via sudo et relancer les services qui ont besoin de prendre en compte les nouveaux certificats

Conf

/etc/sudoers.d/naemon

Defaults    !requiretty
naemon      ALL=(ALL) NOPASSWD: /opt/cert-renew.sh

/etc/naemon/conf.d/sup.cfg

define command {
  command_name          evth_sudo_cert_renew
  command_line          /opt/evth-cert-renew.sh $SERVICESTATE$
}

define service {
  name                  certbot-domain
  use                   generic-service
  max_check_attempts    1
  check_interval        720 ; conformement a la doc certbot, on check toutes les 12 heures
  event_handler_enabled 1
  event_handler         evth_sudo_cert_renew
  register              0
}

define service {
  service_description   Web: https://peterschmitt.fr
  host_name             localhost
  use                   local-service
  check_command         check_http!-u / -H peterschmitt.fr -S -e 403
}

define service {
  service_description   x509: peterschmitt.fr
  host_name             localhost
  use                   certbot-domain
  check_command         check_ssl_expiry!peterschmitt.fr -p 443 -c 3 -w 4 ; la commande qui vous plaira pour la verif des certificats
}

define servicedependency {
  host_name                     localhost
  service_description           Web: https://peterschmitt.fr

  dependent_host_name           localhost
  dependent_service_description x509: peterschmitt.fr

  execution_failure_criteria    p,w,c,u
}

Scripts

/opt/evth-cert-renew.sh

#!/bin/sh
#echo "evth $0: args: $*" >> /tmp/evth
case "$1" in
    CRITICAL)
        #echo "evth $0: cert-renew.sh" >> /tmp/evth
        sudo /opt/cert-renew.sh 2>&1 >> /tmp/evth
        #echo "evth $0: rcode: $?" >> /tmp/evth
        ;;
esac
exit 0

/opt/cert-renew.sh

#!/bin/sh
certbot renew --force-renewal
cat /etc/letsencrypt/live/peterschmitt.fr/privkey.pem > /etc/nginx/ssl/peterschmitt.fr.key.pem
cat /etc/letsencrypt/live/peterschmitt.fr/fullchain.pem > /etc/nginx/ssl/peterschmitt.fr.crt.pem
systemctl restart nginx

Pour les tests on pourra ajouter --dry-run à la commande certbot renew pour, il me semble, éviter de consommer le nombre max d’essais par jour.

Améliorations possibles

Ici, dès la première erreur, on lance la génération et ça sera seulement au prochain check qu’on saura si tout va bien.

On pourrait plutôt mettre deux retry, se servir de l’état SOFT pour déclencher le renouvellement, et si lors du prochain check on passe en HARD, ce qui veut dire que le renouvellement a échoué, on envoie une notification.

Pour faire ça il faudra se servir de la macro $SERVICESTATETYPE$ dans le script de l’event handler.

Ensuite, ça serait vachement mieux de laisser un outil tel que SaltStack faire le déploiement des certificats et gérer la relance des services, surtout que dans cette configuration, le renouvellement se fera trois jours à l’avance. De quoi laisser le temps à ce genre d’outil s’occuper de tout. Mais… quand on fait les choses à La Rache® parce qu’on a La Flemme®… et que ça marche… osef.

by Florent Peterschmitt at August 11, 2016 11:01 AM

August 05, 2016

Florent Peterschmitt

Vieux Centreon et réplica MySQL/MariaDB : objectif MAJ

Il sera question ici de la migration d’un vieux Centreon tout moisi, fonctionnant avec du Nagios et NDOUtils, vers un Centreon 2.7.6, un peu mieux, avec du Centreon Engine et Centreon Broker.

Cette migration a été faite chez un client et s’est passée les doigts dans le pif, et sans trop de coupures.

Je ne vais pas détailler le processus de MAJ de Centreon, ni son installation, la documentation de Centreon se suffit à elle-même, et je vais aussi partir du principe que vous connaissez les fichiers de configuration de Centreon, ainsi que les merdouilles liées au processus d’upgrade (modifier les fichiers de migration SQL à la main, tout ça…).

Ici on va parler réplication MySQL / MariaDB et reprise de service en douceur.

Note : j’ai écris de billet après la prestation, et de mémoire, en relisant la doc faite chez le client et les morceaux de tâches Ansible qui m’ont aidé pour le setup des pollers. S’il y a des erreurs, un petit mail et je corrige.

État des lieux

  • CentOS 6.x x86_64
  • Base de données MySQL 5.1
  • Centreon 2.3.3 installé avec les sources
  • Nagios 3.x + NDOUtils compatible avec Centreon
  • 5 pollers dont un local (sur la machine BDD + Web)

Objectif et étapes

L’objectif est de migrer la totalité des composants vers des outils 100% made in Centreon, et avec le moins de temps de coupure possible, et le must, sans faire de trous dans les graphes \o/

  • CentOS 6.x x86_64
  • Base de donnée MariaDB 5.5 packagée par CES (Centreon)
  • Centreon 2.7.6 installé par les paquets
  • Centreon Broker Daemon, ou cbd, remplace ndo2db
  • Centreon Engine + Centreon Broker Module, remplace Nagios et ndomod
  • Réinstallation de l’instance BDD + Web sur une autre machine, ainsi que son poller local
  • Installation de Centreon Engine en parallèlle des Nagios.

La ré-installation de la BDD + Web sur une autre machine est en fait facultative, ici c’était parce que le client avec des thunes à mettre dans une grosse machines avec des gros SSD dégoulinants d’amour tout plein.

Aussi, pour passer facilement de Nagios à Centreon Engine, on va devoir utiliser temporairement la version 2.6.6 de Centreon, qui est la dernière version à prendre en charge Nagios et NDO. Au delà, le support est largué au profit de Centreon* uniquement.

Réplication de la BDD

La première étape, c’est de répliquer tranquillement les données en base. Centreon fonctionne quasi exclusivement avec sa BDD MySQL. On s’assure ainsi un dump complet de la base, et une récupération de l’état courant sans jamais oublier personne en chemin.

Note : même si on peut voir des modules InfluxDB apparaître pour Centreon-Broker, je ne l’ai pas testé (et Centreon n’étant pas une techno qui m’intéresse particulièrement, j’ai pas trop envie de m’y coller) et de toute façon le client n’aurait pas forcément souhaité installer grafana en plus.

Configuration

Déjà, il vous faut, de préférence, une base MySQL identique à la première : même configuration et même version.

Ensuite, on va configurer comme suit notre MySQL “master”, qui est la base qui contient présentement les données :

[mysqld]
net_write_timeout = 3600
max_allowed_packet = 1G
log-bin=mysqld-log-bin
server_id=1
open-files-limit = 32000
binlog_format=MIXED

Et sur notre MySQL “slave”, qui ne contient rien du tout pour le moment :

[mysqld]
relay-log=mysqld-log-relay
net_write_timeout = 3600
max_allowed_packet = 1G
server_id=2
read-only
open-files-limit = 32000
slave-skip-errors = 1062

Pour la réplication, un utilisateur dédié est nécessaire. Le/les slave(s) vont se connecter au master via cet utilisateur.

Création sur le master :

create user 'replication_user'@'%' identified by 'the_super_password';
grant replication slave on *.* to replication_user;
flush privileges;

Enfin il ne coûte rien de vérifier que nos MySQL vont pouvoir causer entre eux :

$ mysql
MariaDB [(none)]> show variables like 'skip_networking';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| skip_networking | OFF   |
+-----------------+-------+
1 row in set (0.00 sec)


$ netstat -laputen|grep 3306
tcp        0      0 0.0.0.0:3306                0.0.0.0:\*                   LISTEN

Et là on peut redémarrer nos deux MySQL pour prendre en compte la configuration.

service mysqld restart

Initialisation

Cette étape consiste à charger un gros dump en live dans notre slave, pour ensuite lui dire de rejouer les binlog à partir d’un certain point.

Attention : il vous faut impérativement vérifier l’espace disque disponible sur vos machines, et estimer le temps que ce dump va mettre. Sinon vous risquez de ne plus avoir de place pour les binlog, et je ne vous fait pas un dessin : ça va tout planter !

Bon, déjà, je n’ai pas vraiment trouvé de bonne méthode pour faire ça très proprement, vous allez voir.

Sur le master, on va exécuter ça :

mysqldump -uroot -ppassword --all-databases --skip-lock-tables --single-transaction --flush-logs --master-data=1 --quick | head -n 30|grep '^CHANGE MASTER TO'

On va se prendre un Got errno 32 on write, ce qui est normal vu qu’avec head on a fermé stdin alors que mysqldump contiuait à écrire. C’est la même erreur qu’on se prendrait en cas de fulldisk si je ne m’abuse.

Retenez cette valeur : MASTER_LOG_POS=XXX

Exemple de retour : CHANGE MASTER TO MASTER_LOG_FILE=’mariadb-log-bin.000018’, MASTER_LOG_POS=106;

Dans l’exemple, la valeur à retenir est 106. On va s’en servir pour faire démarrer notre slave à la bonne position de départ dans le prochain log-bin qui va être créé quand on démarrera le dump.

Pour les options utilisées dans la commande mysqldump, je vous laisse man mysqldump, c’est très bien expliqué.

Bien, maintenant on va réellement lancer le dump. Préparez deux shell : un dans un screen ou tmux, et l’autre sur la console MySQL de votre master.

Dans le premier, faites feu :

mysqldump -uroot -ppassword --all-databases --skip-lock-tables --single-transaction --flush-logs --master-data=1 --quick | gzip | ssh root@host_slave "zcat | mysql -uroot"

Sans attendre, dans le second :

mysql> SHOW MASTER STATUS\G
... bla bla bla ...
Master_Log_File: mysqld-log-bin.XXXXXX
... bla bla bla ...

Ça les amis, c’est le fichier à partir duquel notre slave va devoir rejouer les instructions, pour commencer la récupération.

Donc on se retrouve au final avec ces deux infos :

MASTER_LOG_POS=106
MASTER_LOG_FILE=mysqld-log-bin.XXXXXX

Ah ouais, heu, XXXXXX, ça va être des chiffres. Mettons, pour la suite, que ce nombre est 000002.

Mise en marche du slave

Déjà, attendez que votre mysqldump ai terminé et sans erreur. À la moindre coupure, vous pouvez tout recommencer.

Si ça arrive, sachez que vous pouvez supprimer les binlog du master qui ne sont plus en activité : ils ne servent plus à rien.

Par contre, si tout va bien, ne supprimez rien du tout, car naturellement, on va en avoir besoin.

Ouvrez une console MySQL sur le slave, on va changer sa configuration et lancer le processus de réplication.

Exécutez cette commande, en adaptant avec vos valeur pour MASTER_LOG_POS et MASTER_LOG_FILE :

CHANGE MASTER TO
  MASTER_HOST='host_master',
  MASTER_USER='replication_user',
  MASTER_PASSWORD='the_super_password',
  MASTER_PORT=3306,
  MASTER_CONNECT_RETRY=10,
  MASTER_LOG_FILE='mysqld-log-bin.000002',
  MASTER_LOG_POS=106;

Vous pouvez vérifier que les infos ont bien été prises en compte avec la commande SHOW SLAVE STATUS\G.

Quand tout va bien, exécutez SLAVE START;.

Tout au long de la récupération du slave sur le master, on devra avoir quelque chose comme ça :

show slave status \G;
# On ne doit pas trouver d’erreur :
    Last_IO_Errno: 0
    Last_IO_Error: 
    Last_SQL_Errno: 0
    Last_SQL_Error:
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes

# Le compteur de retard ne doit pas sans cesse s’incrémenter :
    Seconds_Behind_Master: XXXXX

Le compteur Seconds_Behind_Master va devoir tendre vers 0 avec le temps. Il pourra momentanément augmenter, mais s’il ne fait que d’augmenter, alors vous avez un problème : votre slave n’est pas capable d’absorber la charge ou votre master ne répond pas assez vite, ou les deux.

Vous vous souvenez de l’option slave-skip-errors = 1062 dans la configuration ? Visitez directement ce lien : http://www.ducea.com/2008/02/13/mysql-skip-duplicate-replication-errors/

Ça va vous arriver, en tout cas avec Centreon. Je n’ai pas eu le temps d’investiguer sur le pourquoi du comment, en revanche je sais qu’il n’y a pas réellement de problème et qu’il n’y aura pas de corruption. Ce genre d’erreur est à confronter avec votre environnement et la/les application(s) qui utilisent vos bases.

En tout cas, il est nécessaire de zapper cette erreur, sinon vous vous retrouverez à devoir manuellement, ou scriptemochement, sauter les erreurs. MySQL a déjà une option pour ça, utilisons la.

Quand le compteur Seconds_Behind_Master tombe à zéro, on pourra poursuivre la migration.

Transfert du master vers le slave (arrêt du master)

On va maintenant reconfigurer notre slave pour être utilisé en temps que master, et abandonner le master actuel.

Connectez-vous sur votre Centreon et modifiez la conf des ndomod (ou faites le à la main, je m’en fiche du moment que c’est fait) pour qu’ils aient un fichier de rétention en cas d’injoignabilité de ndo2db.

Modifiez aussi la configuration ndo2db pour pointer sur la BDD slave. Ne relancez surtout pas ndo2db pour le moment.

Appliquez cette conf, et faites un petit test pour vous assurer que le fichier est bien créé consommé lorsqu’une règle iptables empêche notre Nagios de causer avec ndo2db, puis consommé quand on la retire.

Arrêtez tous les services Centreon (centcore et centstorage).

Quand c’est fait, coupez vos instances de ndo2db. Et là encore, attention à l’espace disque sur les pollers : il ne s’agirait pas de faire un full parce que /var est taillé à la serpe.

Avant toute chose, vérifiez que votre slave a bien fini de se synchroniser avec le master.

Arrêtez l’instance de MySQL sur le master.

Ensuite, avec MySQL 5.1, on va devoir redémarrer le slave une fois pour repasser en mode “normal”.

  1. Supprimez la configuration qui a été ajoutée pour le slave
  2. Exécutez sur le slave slave stop; reset slave;
  3. Redémarrez mysqld du slave
  4. Vérifiez avec show slave status\G que vous n’obtenez plus rien. Si ce n’est pas le cas, je me suis vautré dans les commandes précédentes \^_\^

Eh bah là on est bon les enfants. On va pouvoir redémarrer ndo2db, qui, avec sa nouvelle conf, va venir peupler notre nouvelle base, et modifier les fichiers de configuration Centreon pour que centcore et centstorage viennent taper sur notre nouvelle base.

Les fichiers de conf sont normalement dans /etc/centreon, mais si c’est une installation par les sources, vous les avez peut-être dans /usr/local/centreon/etc/. Adaptez la conf des bases.

Reprise de service

Redémarrez donc ndo2db, centcore et centstorage. Constatez la bonne reprise du service.

Pour l’instant, seule la base SQL a été migrée. On va pouvoir passer aux choses sérieuses avec la MAJ.

MAJ

Coupez encore une fois ndo2db, centcore et centstorage.

Débrouillez-vous pour passer en version 2.6.6. Avec yum-plugin-versionlock, voici le versionlock.list approprié :

centreon-2.6.6-5.el6.noarch
centreon-base-2.6.6-5.el6.noarch
centreon-base-config-nagios-2.6.6-5.el6.noarch
centreon-common-2.6.6-5.el6.noarch
centreon-installed-2.6.6-5.el6.noarch
centreon-perl-libs-2.6.6-5.el6.noarch
centreon-web-2.6.6-5.el6.noarch
centreon-plugins-2.6.6-5.el6.noarch
centreon-plugin-meta-2.6.6-5.el6.noarch
centreon-trap-2.6.6-5.el6.noarch
ndoutils-1.4b9-6.el6.x86_64
centreon-broker-2.10.5-2.el6.x86_64
centreon-broker-cbmod-2.10.5-2.el6.x86_64
centreon-broker-core-2.10.5-2.el6.x86_64
centreon-broker-cbd-2.10.5-2.el6.x86_64
centreon-broker-storage-2.10.5-2.el6.x86_64
ndoutils-1.4b9-6.el6.x86_64

Installez Centreon en utilisant centreon et centreon-base-config-nagios, copiez les fichiers de conf Centreon, puis passez le processus de MAJ de Centreon.

Vous pouvez maintenant redémarrer vos ndo2db, centcore et centstorage, et vérifier que ça marche.

Passage en Centreon-Engine + Centreon Broker

  1. Installer centreon-engine et centreon-broker-cbmod sur les pollers
  2. Installer centreon-broker-daemon sur votre Central
  3. Configurez chaque future instance de centreon-engine, ainsi que centreon-broker-module et centreon-broker-daemon
  4. Copiez le ~/.ssh de l’utilisateur centreon sur votre nouvelle machine, c’est nécessaire pour joindre les pollers

Pour cela, la documentation de centreon devrait suffire, sinon il y a d’autres tutos qui expliquent comment configurer tout ce beau monde.

Une fois que vous avez tout configuré, poussez vous conf mais ne démarrez rien.

  1. Démarrez cbd sur le central, vérifiez qu’il tourne bien et accepte les connexions
  2. Arrêtez ndo2db, votre supervision continueras de tourner et en cas de pépin, la reprise de service avec NDO est faisable simplement en relançant le service
  3. Configurez Centreon pour utiliser Centreon Broker. Ça se trouve dans les paramètres d’administration
  4. De là vous ne devriez plus avoir de status, car cbd écrit dans centreon_storage, alors que NDO écrit dans centreon_status. Le fait d’avoir configuré Centreon en mode Centreon Broker fait qu’il regarde dans centreon_storage.
  5. Lancer vos Centreon Engine. Les status devraient montés quasi immédiatement. Si ça n’est pas le cas (du style le compte d’hôte qui passe de 0 à 100, puis re à 0, puis à 200, puis à 0 etc… vous vous êtes viandé dans la conf des instances de pollers)

À partir de là, si tout fonctionne, arrêtez vos Nagios

MAJ version Centreon 2.7.x

Ben là ya pas plus simple : on arrête les services Centreon du central, on retire le versionlock.list, on upgrade tout le monde (pollers compris, centreno-engine et cbmod), et on relance.

Vous devrez aussi lancer une reconstruction des graphes à partir des données en base. Les migrations des RRD n’ont jamais bien fonctionné, même avec les rrddump et rrdrestore.

Aussi faites gaffe, vous aurez peut-être besoin de faire du nettoyage pour certaines métriques inexistantes :

use centreon_storage; # adapter...
delete from metrics where (select count(*) from data_bin as db where db.id_metric=metric_id) = 0;

by Florent Peterschmitt at August 05, 2016 09:22 AM

August 02, 2016

Luc Didry

Encore un bug avec Ganeti (mais pas tout à fait de sa faute)

Comme je l’ai dit hier, j’uti­lise Ganeti pour gérer les VMs de Frama­soft.

J’uti­lise la version 2.15, des dépôts back­ports de Debian Jessie.

Manque de pot, la version de socat des back­ports, 1.7.3.1–1~b­po8+1, pose des problèmes à Ganeti.

En effet, j’ai voulu dépla­cer une VM sur un autre nœud du clus­ter, et paf :

"disk/0 failed to receive data: Exited with status 1 (recent output: socat: E openssl-method="TLSv1": method unknown or not provided by library\n0+0 records in\n0+0 records out\n0 bytes (0 B) copied, 0.00308621 s, 0.0 kB/s)"

Heureu­se­ment, contrai­re­ment à hier, je n’ai pas du cher­cher bien loin pour trou­ver la solu­tion.

Les chan­ge­ments entre socat 1.7.2 et 1.7.3 font plan­ter le trans­fert. Il n’y a donc qu’à down­gra­der socat pour que ça roule :

apt-get install socat=1.7.2.4-2

Deux articles sur des problèmes de Ganeti coup sur coup, ça fait un peu « Mais c’est de la merde ce truc ». Bah non, je trouve que ça reste une très bonne solu­tion pour faire de la virtua­li­sa­tion sur ses serveurs de façon simple et fiable. Si, si, fiable : même quand Ganeti plante, la virtua­li­sa­tion tourne toujours. C’est le prin­cipe de Ganeti. Il n’est pas “utile” pour faire tour­ner les VMs, mais pour les mani­pu­ler. Et ça j’aime beau­coup :-)

Parta­ger

Flattr this!

by Luc at August 02, 2016 05:04 PM

August 01, 2016

Luc Didry

LE bug de merde dans Ganeti 2.15

La semaine dernière, j’ai passé tous les serveurs du clus­ter Ganeti de Frama­soft en Debian Jessie (pour ceux qui ne l’étaient pas encore).

Et là, paf, je rencontre un vilain bug : le dæmon luxid qui segfault à tout bout de champ. Bah oui, le clus­ter était encore en 2.11, la version de wheezy-back­ports. Et Ganeti 2.11 + systemd (qui nous est arrivé par la grâce de la mise à jour en Jessie), ça ne fait pas bon ménage.

Qu’à cela ne tienne, je peux passer en 2.15, la version de jessie-back­ports.

gnt-cluster upgrade --to 2.15

Hop, nickel, luxid tient la route, je suis content.

Là, je me mets à vouloir ajou­ter un nœud au clus­ter.

gnt-node add foo.exemple.org

Bam. Ça foire.

Failure: command execution error:
need more than 1 value to unpack

En cher­chant bien, on tombe sur cette page où les mecs farfouillent beau­coup pour trou­ver le problème. Ça va de « Est-ce que c’est pas la version d’openssl qui serait pas la même » à « Ajoute telle option à ton sshd_config ».

Je vous la fais courte : c’est juste que l’er­reur n’est pas correc­te­ment détec­tée. C’est un bête problème de More than one node group exists. Target group must be specified explicitly..

Donc la solu­tion est de spéci­fier le groupe auquel ratta­cher le nouveau nœud :

gnt-node -g le_groupe foo.exemple.org

Raah, il m’aura bien fait courir ce bug-là !

Parta­ger

Flattr this!

by Luc at August 01, 2016 02:27 PM

July 24, 2016

Luc Didry

Retour sur le « No poo »

Suite à mon jour­nal sur le Seitan sur LinuxFr (ou à la paru­tion de mon article de blog sur Diaspo­ra*, je sais plus), on m’a parlé du « No poo » et notam­ment de cet article. C’est un mouve­ment qui consiste à ne plus se laver les cheveux.

« Beurk, c’est dégueu­lasse ! » me direz-vous. Et bien non :-)

J’ai donc essayé le No poo. Ça fait un peu plus de deux mois main­te­nant que je ne me lave plus les cheveux qu’au bicar­bo­nate et jus de citron.

« Mais pourquoi donc faire cela ? »

Ma foi, j’ai toujours trouvé cela embê­tant de me mettre sur les cheveux un truc dont la compo­si­tion est impos­sible à comprendre à moins d’avoir un docto­rat en chimie.

Un peu moins de chimie dans la vie dans la vie quoti­dienne, ça ne peut pas faire de mal :-)

Résul­tat au bout de deux mois : je ne me lave plus les cheveux tous les jours, ils sont plus épais et plus doux, et après un lavage, ils sont aussi bien démê­lés qu’a­vec un sham­pooing clas­sique (j’ai les cheveux longs et légè­re­ment bouclés, ils s’em­mêlent faci­le­ment). Le prix ? J’ai pas fait trop gaffe… un paquet de 500g de bicar­bo­nate coûte un peu moins de 4€ et on en a pour plus de 2 mois. ± 3€ pour 50cl de jus de citron, qui dure plus de 2 mois… Alors oui, les bouteilles de sham­pooing peuvent coûter moins cher, mais si je ne dis pas de bêtises, je les vidais vite. Pour moi, c’est gagnant au niveau qualité et au niveau prix.

Je ne peux donc que vous encou­ra­ger à tester :-)

EDIT : dans le jour­nal LinuxFr que j’ai fait de cet article, Wendigo a pointé ce docu­men­taire. C’est sur le gel douche, mais ce qui s’y dit doit être valable pour les sham­pooings.

Parta­ger

Flattr this!

by Luc at July 24, 2016 12:20 PM

July 18, 2016

Luc Didry

Mise à jour de Lufi

Je viens de pous­ser la correc­tion de failles sur Lufi. Pour ceux qui l’ont installé sur leur serveur, mettez à jour rapi­de­ment !

Pour ceux qui utilisent https://demo.lufi.io ou https://frama­drop.org, ces deux instances ont été mises à jour dans la foulée du commit.

Parta­ger

Flattr this!

by Luc at July 18, 2016 12:56 PM

July 14, 2016

Luc Didry

Lance­ment de mes pages Tipeee et Libe­ra­pay

Libre ne veut pas dire gratuit. Et oui, les déve­lop­peurs de logi­ciels libres doivent manger aussi.

Le problème est que cet état de fait n’est pas toujours dans les têtes de tout le monde, parti­cu­liers comme entre­prises. Des exemples ?

Heureu­se­ment, certaines orga­ni­sa­tions comme Frama­soft (dont je suis sala­rié), à force de péda­go­gie, de répé­ti­tion et de campagnes de dons, arrivent à faire passer le message (certes, Frama­soft ne produit pas (enfin si, mais très peu) de logi­ciel, mais four­nit un énorme effort pour faire connaître le logi­ciel libre au grand public et contri­bue au logi­ciel libre par des traduc­tions, des tuto­riels, des patchs, des rapports de bugs, etc).

Mais qu’en est-il pour les déve­lop­peurs isolés ? Ceux qui n’ont pas le temps de faire leur promo ? Géné­ra­le­ment, on a droit à un pauvre petit bouton paypal sur le site du logi­ciel ou leur site person­nel. C’est déjà ça, mais ça limite le soutien à ceux qui ont un compte paypal (oui, je sais, on peut aussi payer par carte bancaire, mais je sais d’ex­pé­rience qu’il faut que la personne qui met le bouton confi­gure sa page paypal pour ça et que paypal ne s’amuse pas à chan­ger ses confi­gu­ra­tions sans rien dire) et à un don ponc­tuel. Et la sauce de Flattr n’a malheu­reu­se­ment pas pris.

Heureu­se­ment, il y a main­te­nant de nouvelles façons de soute­nir les personnes que l’on souhaite aider : Tipeee, Libe­ra­pay, Patreon et autres plate­formes de dons.

Ces plate­formes ont l’avan­tage de permettre les dons récur­rents et de four­nir une page person­na­li­sée pour le créa­teur, lui permet­tant d’ex­pliquer ce qu’il fait, pourquoi il propose de le soute­nir, et même pour certaines d’entre elles de propo­ser des contre­par­ties.

« Oui mais on peut déjà faire une page sur son site ». Oui mais c’est beau­coup plus simple de créer la page sur ces outils et surtout, cette page est la même que celle où l’on peut donner, détail d’im­por­tance.

Bref, tout ça pour dire que je lance mes pages Tipeee (pour l’as­pect plate­forme connue) et Libe­ra­pay (pour être sur une plate­forme libre, on ne se refait pas :D ).

À ma connais­sance, il n’y a pas de déve­lop­peur de logi­ciel libre sur ce genre de plate­forme (Tipeee, tout du moins), je teste­rai donc :-)
Il faut bien tester les diffé­rentes pistes à notre dispo­si­tion en atten­dant le revenu de base ou le salaire à vie.

Soyons clair : je ne cherche pas à gagner suffi­sam­ment de sous pour vivre de mes logi­ciels (bossant pour Frama­soft, je gagne déjà ma vie grâce au logi­ciel libre). Par contre, je permets à ceux qui le souhaitent de me remer­cier en me donnant de quoi me payer une bière de temps en temps, tout en rece­vant une contre­par­tie. Car oui, je propose des contre­par­ties :-) Vous pouvez voir lesquelles sur https://www.tipeee.com/fiat-tux (et quelles sont mes réali­sa­tions dans le domaine du logi­ciel libre sur https://luc.frama.io/, en cliquant sur Réali­sa­tions).

Et histoire de donner le bon exemple, sachez que je soutiens :

  • Neil Jomunsi, écri­vain libre
  • JcFrog, musi­cien/chan­teur/inter­prète paro­dique libre
  • Gee, dessi­na­teur libre
  • ZeMar­mot, film d’ani­ma­tion libre

N’hé­si­tez pas à les soute­nir, ainsi que Frama­soft, la Quadra­ture du Net et l’April :-)

Me soutenir sur Tipeee Me soutenir sur Liberapay

Parta­ger

Flattr this!

by Luc at July 14, 2016 11:15 AM

July 08, 2016

Sebastien Badia

Let's Encrypt using DNS challenge

Logo Let's Encrypt

On va encore parler de Let's Encrypt, non pas du fait que Comodo a essayé d'enregistrer la marque « Let's Encrypt » (oui rien que ça… ils ne doutent rien ces gens… voir cet article).

Mais on va parler de la possibilité de faire du challenge/response DNS pour la génération de nos certificats. En effet dans un précédant article, j'expliquais comment utiliser le client acme-tiny afin de générer des certificats SSL. Le soucis avec cette méthode (et le challenge/response en HTTP) c'est, comme son nom l'indique, qu'il utilise du HTTP(s); il faut donc obligatoirement avoir un serveur web qui va répondre aux challenges (afin de vérifier que nous avons bien le contrôle du domaine que nous souhaitons certifier).

Dans certains cas, il est nécessaire de générer des certificats sans disposer d'un serveur web (soit parce que le service est en interne et donc pas accessible depuis internet, ou alors c'est du mail ou autre… (dans mon cas)).

Yet another script to manage Let's Encrypt...

Après acme-tiny, voici letsencrypt.sh, l'avantage de celui-ci est qu'il est ultra modulaire! Il supporte les challenges par http (classique), mais aussi par DNS (ajout d'un enregistrement txt dans la zone correspondante, voir la doc pour plus d'infos).

Donc nous disions, le truc cool c'est qu'il fonctionne via des hooks, et ils sont nombreux!. Lorraine Data Network n'a pas encore de DNS contrôlé via une API, il faut donc faire un hook spécifique (en mode old-school via puppet/git :-D)

Cas concret avec l'infra de Lorraine Data Network

./letsencrypt.sh -c -t dns-01 -d webmail.ldn-fai.net -d bender.ldn-fai.net -k ./hooks/ldn.sh

Le hook en question, ce petit bout de bash fait donc:

  • Mise à jour du dépot puppet LDN local
  • Ajout de l'enregistrement TXT correspondant au domaine à certifier
  • Mise à jour du serial de la zone
  • Commit et push, puis lancement de puppet
  • Attente d'une validation / certificat de la part de letsencrypt
  • Nettoyage du TXT

Tout cela pour montrer que c'est assez trivial de tout automatiser avec ce système de hooks.

by Sebastien Badia at July 08, 2016 04:00 PM

June 25, 2016

Sebastien Badia

Bug plutôt gênant de flickering avec le noyau 4.6.x

Avec la mise à jour du noyau Linux en 4.6.0 dans Debian, est apparu un bug bien embêtant… L'écran de mon Thinkpad se met à clignoter… (ou flickering) de manière aléatoire (et ça uniquement dans une session X window).

Si ça peut aider, voici quelques pointeurs!

Correctif

Le soucis est connu, on trouve d'ailleurs pas mal de pointeur sur l'Internet! Le problème est d'ailleurs patché et releasé dans la version 4.6.2 du noyau Linux.

The default of 0 is 500us of link training, but that's not enough for
some platforms. Decoding this correctly means we're using 2.5ms of
link training on these platforms, which fixes flickering issues
associated with enabling PSR.

Liens sur les Internettes

Pour les impatient⋅e⋅s

Coté Debian, Salvator à releasé un nouveau paquet 4.6.2-1, il est à l'écriture de ce billet disponible dans Debian unstable, ou sur snapshot.d.o:

Sinon il faut juste attendre que 4.6.2-1 arrive dans testing :)

by Sebastien Badia at June 25, 2016 09:03 AM

June 19, 2016

Sebastien Badia

IPv6, NetworkManager et vie privée

noplacelike

Sur la plus part des réseaux IPv6, les adresses sont crées/distribuées via SLAAC (Stateless address autoconfiguration)

En pratique ça fonctionne comme cela:

  • L'host envoie une router solicitation request (salut, ça à l'air cool ici, il y a des routeurs dans le coin?)
  • Le routeur réponds avec un préfixe (salut, c'est moi le routeur, ton adresse devra commencer par ce préfixe)
  • L'host utilise alors le préfixe et l'adresse MAC de son interface pour générer une adresse IPv6

Le format des adresses générées par l'host est aussi appelé EUI-64. Pour plus de détails à propos de ce procédé, la page de l'IEEE explique tout, le wiki d'ArchLinux est pas mal aussi!

D'un point de vue, sécurité et vie privée

Bon SLAAC, ça marche bien et c'est pratique, mais ça permet de quand même leaker pas mal d'informations à propos du périphérique qu'on utilise… (avec l'adresse MAC, et une recherche OUI-Search, on connais facilement le périphérique), on peut aussi effectuer du tracking assez précis…

Il est aussi possible d'en extraire des informations de localisation assez précises.

Adresses temporaires

Mais comme disait l'autre, en informatique, rien n'est impossible! Il existe donc un système d'adresses temporaires. Pour Apple et Windows, je ne sais pas trop, mais pour la mojorité des Linux ce n'est pas activé par défaut.

On peut l'activer coté système, via sysctl:

# Do not use a temporary address
net.ipv6.conf.all.use_tempaddr = 0
# Set a temporary address, but do not make it the default
net.ipv6.conf.all.use_tempaddr = 1
# Set a temporary address and make it the default
net.ipv6.conf.all.use_tempaddr = 2

Via NetworkManager, c'est presque la même chose, et on peut activer les adresses temporaires via nmcli via l'attribut ipv6.ip6-privacy. Pour les interfaces filaires, on spécifie directement l'interface, et pour les connexions wifi, c'est par contre par point d'accès (via le nom du point d'accès).

nmcli con modify eth0 ipv6.ip6-privacy 2
nmcli connection modify courgette ipv6.ip6-privacy 2

courgette étant le nom d'un point d'accès wifi.

L'activation est alors automatique, l'adresse MAC de l'interface n'est alors plus utilisé pour « construire » l'adresse IPv6 globale de l'interface.

ip a s eth0

Pour briller en société

Les adresses temporaires sont construites en se basant sur l'adresse MAC et une chaine de caractères aléatoire, l'adresse assignée change alors à chaque fois. Ce n'est donc pas à envisager si vous avez besoin d'accéder à votre système par IPv6 (ip renseignée dans un DNS, serveur, ou device non-mobile).

by Sebastien Badia at June 19, 2016 12:02 PM

June 18, 2016

Sebastien Badia

Memo: Monter une image qcow2

Un billet plus en mode mémo, ou comment monter une image qcow2/qcow en vue d'accéder au système de fichier qu'il contient.

Utilisation de qemu-nbd

Dans mon cas, j'avais besoin d'accéder à une machine virtuelle (au format qcow2) mais sans la démarrer, il suffisait donc de monter le qcow2 et d'accéder direct au filesystem (un peu plus compliqué que dans le cas d'un lvm, mais ça reste simple).

modprobe nbd max_part=8
qemu-nbd -c /dev/nbd0 /srv/images/ma-super-vm.qcow2
mount /dev/nbd0p1 /mnt

On fait ce qu'on veux faire avec la partition ainsi montée… et une fois fini,

umount /mnt
qemu-nbd -d /dev/nbd0

Et voila :-)

by Sebastien Badia at June 18, 2016 09:03 AM

June 10, 2016

Romain Dessort

Upgrade to Debian Jessie, introducing smtpd_relay_restrictions in Postfix

TL;DR: since debconf appends a smtpd_relay_restrictions at the end of your main.cf file with same values of smtpd_recipient_restrictions, you have to do the same on all your services listed in master.cf. smtpd_relay_restrictions intends to replace smtpd_recipient_restrictions on next Postfix releases.

After upgrading my mail server to Debian Jessie, I was faced with a weird problem with Postfix: emails sent from authenticated clients were rejected with a “Relay access denied” error.

I have a particular setup, though not so uncommon I think, since it should be the standard: port 25 is dedicated to server-to-server communications, no authentication is supported on that port. Instead, clients which want to send emails have to submit them on submission port (obviously). Concretely on my master.cf file, I override smtpd_recipient_restrictions for submission service to allow sending of emails with minimum restrictions if clients get authenticated.

On my main.cf file:

smtpd_recipient_restrictions =
   permit_mynetworks,
   check_client_access hash:/etc/postfix/client_access,
   #check_sender_access hash:/etc/postfix/sender_access,
   check_recipient_access hash:/etc/postfix/recipient_access,
   reject_unauth_destination,
   reject_invalid_helo_hostname,
   reject_non_fqdn_helo_hostname,
   reject_non_fqdn_sender,
   reject_non_fqdn_recipient,
   reject_unknown_sender_domain,
   reject_unknown_recipient_domain,
   check_policy_service unix:private/whitelister.ctl,
   check_policy_service inet:127.0.0.1:10023,
   permit

And on my master.cf file:

submission inet n       -       -       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_sender_restrictions=permit
  -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

So in my case, it seemed that the smtpd_recipient_restrictions option passed to submission process was ignored, or the one set up on my main.cf file won. Enabling debugging didn't tell me anything, but confirmed me that the smtpd_recipient_restrictions option for submission process was ignored since I saw Postfix testing all conditions specified on my main.cf

Then after some time, I have seen a new line at the end of my main.cf file: smtpd_relay_restrictions, with all the tests of smtpd_recipient_restrictions. Searching this on postconf(5) manual confirmed me that it replace smtpd_recipient_restrictions in Postfix 2.10, although this one is always supported and not planed to be removed on the next coming versions. This directive indents to simplify and unify the use of smtpd_*_restrictions.

So debconf has added this new directive on my main.cf file, without any debconf notice as far as I remember, and, in my opinion, without reason (Postfix don't even raise a depreciation warning about other smtpd_*_restrictions), and that breaks other services set up on master.cf.

Strangely, no one on the Internet seem to have encountered a similar problem with this directive when upgrading to Jessie.

So I simply do the replacement on my submission service in master.cf and that solve my problem.

June 10, 2016 10:51 AM

June 03, 2016

Alexandre Bailly

NetBSD sur une carte Olimex LIME 2

Photo d'une carte Olimex LIME 2

Un petit article tout simple, qui explique comment installer rapidement NetBSD sur une carte Olimex LIME 2.

Ça ne servira pas forcément à grand-chose. C'est plus pour le sport/fun/amusement/parce que c'est possible (rayer les mentions inutiles).

Pour commencer, il faut :

  • Une carte Olimex LIME 1 ou LIME 2. Perso, j'ai utilisé ma Brique Internet que j'utilise pour faire les tests.
  • Une carte au format microSD (que j'appellerai SD dans l'article par commodité) et un adaptateur microSD -> SD. Le minimum serait 2 Go, j'ai utilisé une microSD de 16 Go en classe 10.
  • Un câble série à brancher sur le connecteur UART de la carte, et un logiciel (genre microcom) pour pouvoir l'utiliser.
  • Un ordinateur sous GNU/Linux (de préférence) ou *BSD. Les MACs, ça a beau être basé sur FreeBSD (+ micronoyau MACH), ça ne compte pas. Windows, on oublie. Je n'ai pas testé sur Haiku ni sur MonaOS.
  • De la place sur le disque dur.
  • Une connexion internet qui fonctionne.
  • Avoir de quoi compiler fex2bin serait un plus.

Pour être franc, je n'ai rien inventé. Je me suis basé sur la page d'installation de NetBSD pour ARM/Allwinner. J'ai utilisé le noyau de la carte BananaPi, carte qui est "relativement" proche de la LIME2. J'avais la flemme de compiler le noyau BSD exprès pour la carte.


Donc, commençons par récupérer l'image système de NetBSD, en version ARM, se trouvant là :
http://ftp.netbsd.org/pub/NetBSD/NetBSD-7.0.1/evbarm-earmv7hf/binary/gzimg/

Récupérons le bootloader (u-boot) pour la carte, en l'occurence, la LIME 2, ici :
http://dl.linux-sunxi.org/nightly/u-boot-sunxi/u-boot-sunxi-mainline/u-boot-sunxi-mainline-latest/


Décompressons l'image de NetBSD.

gunzip armv7.img.gz

Décompressons l'archive u-boot

tar xf u-boot-sunxi-mainline-a20-olinuxino-lime2.tar.xz

Déplaçons les fichiers décompressés dans le répertoire courant

mv u-boot-sunxi-mainline-a20-olinuxino-lime2-20160428T000127-e25b369/* ./

Copions le bootloader sur l'image de NetBSD, au bon endroit

dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1k seek=8 conv=notrunc

Flashons la carte SD (ici, /dev/sdb, ne vous trompez surtout pas de périphérique ou alors prévoyez un bon backup de votre machine) avec l'image modifiée de NetBSD.

sudo dd if=armv7.img of=/dev/sdb bs=1M

Éjecter et réinsérer la carte SD


À ce stade, on a une carte SD bootable avec u-boot, et contenant un système NetBSD. Cependant, le système n'est pas utilisable.


Monter la carte SD (sdb1 dans mon cas), et se déplacer dessus.

pmount /dev/sdb1 /media/sdb1
cd /media/sdb1

Comme il n'y a pas de noyau NetBSD prévu pour la LIME 2, on va utiliser celui du Banana Pi.

Copions alors le noyau, comme suit :

cp netbsd-BPI.ub netbsd.ub

Préparons le fichier de configuration pour u-boot.

vim boot.cmd

Ajoutons dans ce fichier :

setenv kernel_addr      82000000
setenv kernel           netbsd.ub
setenv bootargs         "root=ld0a"

fatload mmc 0:1 ${kernel_addr} ${kernel}
bootm ${kernel_addr}

Compilons ce fichier cmd à l'aide de mkimage (paquet u-boot-tools sous debian).

mkimage -C none -A arm -T script -d boot.cmd boot.scr

Il faut maintenant la configuration de la carte. Pour cela, télécharger le fichier a20-olinuxino_lime2.fex depuis https://github.com/linux-sunxi/sunxi-boards/tree/master/sys_config/a20.

Récupérer au passage (si ce n'est pas déjà fait) https://github.com/linux-sunxi/sunxi-tools, et compiler au moins fex2bin (pas sur la carte SD, bien entendu)

Convertir le fichier fex en fichier bin. Ne pas oublier de copier le fichier .bin sur la carte SD.

fex2bin a20-olinuxino_lime2.fex > lime2.bin

Créer (ou modifier) le fichier uEnv.txt

vim uEnv.txt

contenu du fichier uEnv.txt

bootargs=root=ld0a sysconfig=0x43000000
uenvcmd=mmc dev 0; mmc rescan; fatload mmc 0:1 43000000 lime2.bin;
fatload mmc 0:1 82000000 netbsd.ub; bootm 82000000

Si tout va bien, vous devriez avoir ces fichiers sur la carte SD (j'aurais pu effacer les kernels des autres cartes, mais bon, flemme) :

LICENCE.broadcom
a20-olinuxino_lime2.fex
boot.cmd
boot.ini
boot.scr
bootcode.bin
cmdline.txt
fixup.dat
fixup_cd.dat
kernel7.img
lime2.bin
netbsd-BEAGLEBOARD.ub
netbsd-BEAGLEBONE.ub
netbsd-BPI.ub
netbsd-CUBIEBOARD.ub
netbsd-CUBIETRUCK.ub
netbsd-HUMMINGBIRD_A31.ub
netbsd-ODROID-C1.ub
netbsd.ub
start.elf
start_cd.elf
uEnv.txt

Démonter proprement la carte avant de l'éjecter

cd
pumount /dev/sdb1

Insérer la carte SD dans le lecteur de la carte Olimex, brancher le câble série sur le connecteur UART (Bleu -> GND, Rouge -> RX, Vert -> TX), lancer microcom, et alimenter la LIME 2 pour la démarrer.

microcom -p /dev/ttyUSB0 -s 115200

Si tout va bien, u-boot devrait apparaître à l'écran

U-Boot SPL 2016.05-rc3-ge25b369 (Apr 28 2016 - 00:13:29)
DRAM: 1024 MiB
CPU: 912000000Hz, AXI/AHB/APB: 3/2/2
Trying to boot from MMC1


U-Boot 2016.05-rc3-ge25b369 (Apr 28 2016 - 00:13:29 +0200) Allwinner Technology

CPU:   Allwinner A20 (SUN7I)
Model: Olimex A20-OLinuXino-LIME2
I2C:   ready
DRAM:  1 GiB
MMC:   SUNXI SD/MMC: 0
*** Warning - bad CRC, using default environment

Après les tests initiaux, NetBSD devrait démarrer. Quelques instants plus tard, un message indiquant que le système redimensionne la partition devrait apparaître. Cette étape est nécessaire pour que toute la carte SD soit utilisable.

Growing ld0 disklabel (1111MB -> 15343MB)
Resizing /

Dès que cette opération est terminée, le système redémarre automatiquement.

Si tout va bien, le message suivant devrait apparaître

NetBSD/evbarm (armv7) (console)

login:

Se connecter via le login root. Il n'y a pas de mot de passe.


Et voilà, NetBSD est désormais utilisable (quoique, encore au stade expérimental). Je ne connais pas l'impact de l'utilisation du noyau du Banana Pi sur cette carte, je n'ai pas assez de recul. Je ne serai en aucun cas responsable en cas d'explosion du CPU.

J'espère n'avoir rien oublié lors de la rédaction de cet article.


Juste à titre indicatif, voici le log complet du démarrage de la LIME 2.

by nah at June 03, 2016 09:30 PM

May 10, 2016

Luc Didry

RequestT­ra­cker : telle­ment puis­sant

RequestT­ra­cker (RT) est un outil de tickets extrê­me­ment puis­sant et flexible. Telle­ment flexible qu’on en vient à se prendre la tête pour faire des trucs de oufs.

Je suis en train d’en mettre un en place pour Frama­soft depuis quelques semaines. Je mets long­temps à le mettre en place pour plusieurs raisons :

  • j’ai d’autres projets à fouet­ter
  • il a fallu que je fasse des aller/retours avec Pouhiou pour cerner au mieux les besoins de notre équipe de support
  • je fais faire des trucs rigo­los à RT qui sont assez galère à mettre en place

Je vais faire un petit tour des trucs que j’ai mis en place sur un RT 4.4.0.

Utili­ser le plus addres­sing

De façon simple, pour que RT traite les tickets qui arrivent sur l’adresse email dédiée, on la met dans le /etc/aliases de sa machine. Ça fait un truc comme ça :

rt:         "|/opt/rt4/bin/rt-mailgate --queue general --action correspond --url https://rt.example.org/"
rt-comment: "|/opt/rt4/bin/rt-mailgate --queue general --action comment --url https://rt.example.org/"

Vous note­rez que cela met les mails à desti­na­tion de cette adresse dans la queue (ou file) general. Or on utilise géné­ra­le­ment plus d’une queue dans un système de ticket : cela permet de diri­ger auto­ma­tique­ment vers les personnes les plus à même d’y répondre.

Le problème avec ce système, c’est qu’il faudrait ajou­ter une adresse dédiée à chaque fois que l’on crée une nouvelle file. Ça peut vite deve­nir usant.

On va donc utili­ser le plus addres­sing. Cette tech­nique, toute bête, consiste à ajou­ter un discri­mi­nant à une adresse mail, précédé géné­ra­le­ment d’un + (mais on peut confi­gu­rer son serveur de mail pour utili­ser n’im­porte quel carac­tère). rt@example.org aura alors pour alias (par exemple) rt+file_bidule@example.org.

Pour que RT puisse utili­ser cette tech­nique, il faut ajou­ter --extension=queue dans la commande du /etc/aliases :

rt:         "|/opt/rt4/bin/rt-mailgate --extension=queue --queue general --action correspond --url https://rt.example.org/"
rt-comment: "|/opt/rt4/bin/rt-mailgate --extension=queue --queue general --action comment --url https://rt.example.org/"

Voilà ! Il ne vous reste plus qu’à créer vos files via l’in­ter­face web. Atten­tion, créez-les avec un nom qui passera dans une adresse mail. Pas d’es­pace par exemple.

RT récu­pé­rera le nom de la file kiva­bien dans la partie entre le + et le @ et placera auto­ma­tique­ment le ticket dans cette file, tout en gardant la file general par défaut.

Les articles

Quoi de plus casse-pieds que de se répé­ter encore et encore en donnant toujours la même réponse ? Heureu­se­ment il y a les articles qui peuvent vous servir de réponses pré-enre­gis­trées :-)

Créa­tion des classes et des articles

Allez dans le menu Administration > Articles > Classes > Ajouter, créez vos classes (j’en ai créé une par file, n’ayant pas réussi à assi­gner auto­ma­tique­ment des articles aux files), cochez Tous les articles de cette classe doivent être disponibles sous forme de liste sur la page de réponse d'un ticket, déco­chez Inclure le résumé de l'article et Inclure le nom de l'article et cochez Include le champs personnalisé 'Content' > Value (oh la belle typo de traduc­tion) qui appa­raî­tra après avoir enre­gis­tré la classe (pour ces trois derniers, vous faites comme vous le sentez hein).

Liez la classe à une file via le menu S'applique à.

Voilà, vous n’avez plus qu’à créer vos articles dans la classe que vous venez de créer via le menu Articles > Ajouter.

Et là, magie, lorsque vous répon­dez via l’in­ter­face web, vous pour­rez choi­sir une réponse pré-enre­gis­trée.

Place­ment des articles dans la réponse

Je suis un grand fan du bottom-post­ing, mais RT place l’ar­ticle au-dessus de la cita­tion du message précé­dent. Remé­dions à cela.

cd /opt/rt4
mkdir -p local/html/Elements/
cp share/html/Elements/MessageBox local/html/Elements/
vi local/html/Elements/MessageBox

Cher­chez la ligne conte­nant

% $m->comp('/Articles/Elements/IncludeArticle', %ARGS) if $IncludeArticle;

et rempla­cez-la par

% if ($IncludeArticle) {
%    my $article = $m->scomp('/Articles/Elements/IncludeArticle', %ARGS);
%    $article    =~ s{\n}{<br />}g;
%    $article    = RT::Interface::Email::ConvertHTMLToText($article);
%    $Default   .= $article unless ($Default =~ s/(.*)(-- .*)/$1$article$2/m);
% }

Hop ! votre article se trouve main­te­nant entre la cita­tion et votre signa­ture :-)

(un redé­mar­rage de RT est peut-être néces­saire pour que cela soit pris en compte)

Ajout des articles perti­nents dans le mail de noti­fi­ca­tion d’un nouveau message

Une des forces de RT est de permettre aux inter­ve­nants de répondre aux tickets par mail. Le problème est que cela empêche de piocher dans les réponses pré-enre­gis­trées.

Qu’à cela ne tienne, ajou­tons-les au mail de noti­fi­ca­tion envoyé aux membres du support.

Allez dans Administration > Global > Modèles > Choisir. Il faut modi­fier le modèle Notification de modification HTML (oui, j’ai traduit le nom de mes modèles, mais il est simple à repé­rer, il est utilisé par les scrips 8 et 11).

Ajou­tez ceci en bas du modèle :

{ my $hotlist = RT::Articles->new( RT->SystemUser );
  $hotlist->LimitHotlistClasses;
  $hotlist->LimitAppliedClasses( Queue => $Ticket->QueueObj );
  my $content   = "-- \n<p><b>Réponses pré-enregistrées pour cette catégorie de tickets:</b></p>";

  if ($hotlist->Count) {
    while (my $article = $hotlist->Next) {
      $content .= '<p><b>'.$article->Name.'</b><br/>';
      my $class   = $article->ClassObj;
      my $cfs     = $class->ArticleCustomFields;
      my %include = (Name => 1, Summary => 1);
      $include{"CF-Title-".$_->Id} = $include{"CF-Value-".$_->Id} = 1 while $_ = $cfs->Next;
      $include{$_} = not $class->FirstAttribute("Skip-$_") for keys %include;

      while (my $cf = $cfs->Next) {
        next unless $include{"CF-Title-".$cf->Id} or $include{"CF-Value-".$cf->Id};
        my $values = $article->CustomFieldValues($cf->Id);
        if ($values->Count == 1) {
          my $value = $values->First;
          if ($value && $include{"CF-Value-".$cf->Id}) {
            $content .= '<br/>';
            my $c     = $value->Content || $value->LargeContent;
            $c =~ s/\r?\n/<br\/>/g;
            $content .= $c;
          }
        } else {
          my $val = $values->Next;
          if ($val && $include{"CF-Value-".$cf->Id}) {
            $content .= '<br/>';
            my $c     = $value->Content || $value->LargeContent;
            $c =~ s/\r?\n/<br\/>/g;
            $content .= $c;
          }
          while ($val = $values->Next) {
            if ($include{"CF-Value-".$cf->Id}) {
              $content .= '<br/>';
              my $c     = $value->Content || $value->LargeContent;
              $c =~ s/\r?\n/<br\/>/g;
              $content .= $c;
            }
          }
        }
      }
      $content .= "<br/>-----------</p>\n";
    }
  }
  $content;
}
{$content}

C’est moche et long, je sais. Dites-vous que j’ai passé plus d’une après-midi pour trou­ver ça, la docu­men­ta­tion est inexis­tante pour faire ça.

Les inter­ve­nants n’au­ront plus qu’à copier-coller l’ar­ticle qui se trouve au bas de leur mail de noti­fi­ca­tion dans leur réponse :-)

Commandes par mail

C’est beau de répondre par mail, mais il faut encore se connec­ter à l’in­ter­face web pour effec­tuer certaines actions. Comme je suis fier d’être fainéant, j’ai créé un scrip pour auto­ri­ser certaines actions par mail.

Mais avant ça, préci­sions :

  • RT permet aux inter­ve­nants de discu­ter du ticket sans que cela soit vu par le créa­teur du ticket : c’est le but de l’adresse rt-comment@example.org du début de l’ar­ticle. On va utili­ser cette adresse pour pilo­ter RT par mail
  • un scrip est une action effec­tuée par RT en réponse à un évène­ment, en utili­sant de façon option­nelle un modèle. Typique­ment, il y a un scrip qui envoie (action) un mail (d’après un modèle) aux membres du support lorsqu’un ticket est créé (évène­ment).

Créons donc un scrip. Menu Administration > Scrips > Ajouter.

  • Condi­tion (évène­ment) => Lors d’un commen­taire
  • Action => défi­nie par l’uti­li­sa­teur
  • Modèle => Modèle vide

Dans le Programme de préparation d'action personnalisé: :

if ($self->TransactionObj->Attachments->First->Content =~ m/#(JePrends|Fermeture|Spam)/i) {
    return 1;
} else {
    return 0;
}

Oui, j’au­rais pu faire un one-liner, mais il faut que ça reste lisible faci­le­ment, et quand on passe des heures à faire des bidouilles comme ça, on appré­cie les codes lisibles en un coup d’œil.

Dans le Code d'action personnalisée (commit): :

if ($self->TransactionObj->Attachments->First->Content =~ m/#JePrends/i) {
    if ( $self->TicketObj->OwnerAsString eq '' ) {
        my $id = $self->TransactionObj->Creator;
        $RT::Logger->info("Setting owner to ".$id);
        $self->TicketObj->SetOwner($id, 'SET');
    }
} elsif ($self->TransactionObj->Attachments->First->Content =~ m/#Fermeture/i) {
    $RT::Logger->info("Closing ticket");
    $self->TicketObj->SetStatus('resolved');
} elsif ($self->TransactionObj->Attachments->First->Content =~ m/#Spam/i) {
    my $ticket = $self->TicketObj;
    my ($status, $msg) = $ticket->SetStatus('rejected');
    $RT::Logger->error("Couldn't delete ticket: $msg") unless $status;

    my $requestors = $ticket->Requestor->UserMembersObj;
    while (my $requestor = $requestors->Next) {
        $requestor->SetDisabled(1);
        $RT::Logger->info("Disabling user ".$requestor->Format." because he's likely a spammer");
    }
}

return 1;

Voilà, enre­gis­trez et c’est bon.

Lorsqu’un commen­taire contien­dra une commande, elle sera exécu­tée :

  • #JePrends => l’in­ter­ve­nant s’as­signe le ticket
  • #Fermeture => le ticket est marqué comme résolu
  • #Spam => le ticket est supprimé et son auteur ne pourra plus ouvrir de tickets, son adresse mail sera black­lis­tée

Et le spam alors ?

Pour le spam, prépa­rez d’abord un spamassassin pour votre serveur de mails. Ce n’est pas l’objet de cet article, il n’y a qu’à fouiller un peu le web pour trou­ver des tutos.

On va recréer un scrip, mais avant cela on va créer une nouvelle file nommée spam (menu Administration > Files > Ajouter).

Pour notre nouveau scrip :

  • Condi­tion (évène­ment) => Lors d’une créa­tion
  • Action => défi­nie par l’uti­li­sa­teur
  • Modèle => Modèle vide

Dans le Programme de préparation d'action personnalisé: :

if ( $self->TicketObj->Subject !~ /\[ .* \]/i ) {
  my $inMessage = $self->TransactionObj->Attachments->First;

  # if no message attachment - assume web UI
  return 0 if (!$inMessage);

  # exit if not email message
  return 0 if (!$inMessage->GetHeader('Received'));

  return ($inMessage->GetHeader('X-Spam-Level') =~ m/\*+/) ? 1 : 0;
} else {
  return 1;
}

Dans le Code d'action personnalisée (commit): :

my $spamlevel = $self->TransactionObj->Attachments->First->GetHeader('X-Spam-Level');
if ($spamlevel =~ m/\*\*\*+/) {
  if ($spamlevel =~ m/\*\*\*\*\*/) {
    $RT::Logger->info("This mail seems to be a spam => deleting");
    $self->TicketObj->Delete();
  } else {
    $RT::Logger->info("This mail seems to be a spam => queue spam");
    $self->TicketObj->SetQueue('spam');
  }
}
return 1;

Avec cela, les mails ayant un score de 5 ou plus au spamLe­vel seront suppri­més, et ceux qui ont entre 3 et 5 vont au purga­toire, dans la file spam.

Prenez soin de dépla­cer ce scrip tout en haut de la liste pour qu’il soit le premier exécuté.

Plugins

En vrac, les plugins que j’uti­lise :

Les deux premiers sont main­te­nant inté­grés à RT, il n’y a pas besoin de les instal­ler, juste de les confi­gu­rer. Ils servent respec­ti­ve­ment à assu­rer l’au­then­ti­fi­ca­tion LDAP à l’in­ter­face web, et à impor­ter en masse les comptes du LDAP pour permettre à l’ad­mi­nis­tra­teur de mettre les colla­bo­ra­teurs dans les bons groupes sans attendre qu’ils se soient logués une première fois.

Le dernier plugin ajoute un S dans le menu des tickets, permet­tant de les décla­rer comme spam d’un simple clic.

Conclu­sion

On peut faire de merveilleuses choses avec RT, pour peu que l’on ait le temps de fouiller dans la docu­men­ta­tion (offi­cielle ou non)… et dans le code !

Une fois bien confi­guré, il devrait permettre d’al­lé­ger la charge de travail du groupe de support et je peux vous dire que pour en faire depuis plus de deux ans pour Frama­soft et bien plus pour mon ancien boulot, ce n’est pas quelque chose à négli­ger :-)

NB : bien évidem­ment, ce superbe logi­ciel est en Perl :D

Crédits de la photo d’illus­tra­tion : CC-BY GotC­re­dit, trou­vée sur Flickr

Parta­ger

Flattr this!

by Luc at May 10, 2016 06:51 PM

May 01, 2016

Luc Didry

#WeMa­keSei­tan

J’es­saye de manger moins de viande.

Pour une raison fort simple : l’éco­lo­gie. Le bétail consomme de l’eau, pète des gaz à effet de serre, néces­site géné­ra­le­ment la culture de céréales et autre four­rage, etc (voir par là). Tout ça pour un rende­ment éner­gé­tique (pour l’homme) moindre que si on mangeait direc­te­ment l’équi­valent de la nour­ri­ture des bêtes.

Bref, c’pas top. Et puis entre les salo­pe­ries chimiques qu’on balance sur les champs et les gavages aux médi­ca­ments des bestiaux, ben c’est pas trop la fête.

Manger unique­ment des végé­taux, ça enlève déjà la dose d’an­ti­bio­tiques qu’on ingère via la viande.

Reste les pesti­cides et autres cochon­ne­ries sur les végé­taux. Bon, là faut manger bio, et encore : « la plupart des fermes biolo­giques évitent en grande partie les pesti­cides de synthèse » (source : Wiki­pé­dia).

Même si on n’évite pas toutes les salo­pe­ries possibles en cessant de manger de la viande, réduire leur nombre dans notre alimen­ta­tion ne peut être que béné­fique, non ?

Bon. Du coup, j’es­saye de manger le moins de viande possible. Je n’em­bête cepen­dant pas mes amis et ma famille quand je vais manger chez eux, et j’adore toujours autant la viande, mais chez moi, j’évite.

Ce n’est parfois pas facile, tant je suis habi­tué à ma pièce de viande dans l’as­siette. Le plus simple est donc de trou­ver un substi­tut.

Du coup j’ai d’abord pensé au tofu. On en trouve main­te­nant même dans les super­mar­chés. Résul­tat mitigé. Soit je suis infoutu de le prépa­rer comme il faut, soit c’est vrai­ment fade avec une texture bizar­roïde.

Et puis au détour d’une conver­sa­tion avec Bram, j’ai (re)décou­vert l’exis­tence du seitan (redé­cou­vert parce que j’en avait déjà entendu parler il y a long­temps) et surtout décou­vert à quel point c’est simple d’en faire et adap­table à ses envies : du gluten, tu mélanges avec ce que tu veux et du liquide (géné­ra­le­ment du bouillon de légumes). Pouf, voilà.

En plus, géné­ra­le­ment, le gluten qu’on trouve est bio, donc c’est tout bénéf.

Ma recette (mais y en a plein d’autres sur les Inter­netz)

(les doses sont à la louche, je suis plutôt instinc­tif quand je fais à manger)

  • du gluten (moi j’ai trouvé celui-ci chez BioCoop)
  • une boîte de hari­cots rouges en conserve (poids total 400g, poids égoutté 250g)
  • de l’huile d’olive
  • du jus de citron
  • de la sauce Worces­ter­shire
  • du cumin
  • du sel

Pour la suite, on aura besoin d’un bouillon de légumes, on verra ça après.

  • Réchauf­fer les hari­cots rouges avec le jus dans une casse­role
  • Verser les hari­cots rouge avec le jus dans un sala­dier
  • Écra­ser les hari­cots avec une four­chette (ou ce que vous voulez, j’ai pris ce que j’avais chez moi, le presse-purée ou le mixer seront sans doute plus effi­caces)
  • Mettre deux gros schlouks d’huile d’olive
  • Deux gros schlouks de jus de citron aussi
  • Mettre une bonne dose de sauce Worces­ter­shire
  • Bien mélan­ger
  • Goûter pour voir si on sent bien la sauce Worces­ter­shire, en rajou­ter au besoin
  • Balan­cer du cumin et du sel selon ses goûts (ne pas hési­ter à regoû­ter)
  • Re-bien mélan­ger
  • Mettre du gluten en remuant bien. Quand il n’est plus possible de remuer avec la four­chette, pétrir le tout comme de la pâte à pain
  • Le mélange final doit avoir une consis­tance un peu comme de la pâte à mode­ler, le modèle qui rebon­dit un peu

Ensuite, il faut faire des boules avec votre pâte, genre de la taille d’un poing. Cela fera une portion pour une ou deux personnes.

seitan

C’est là qu’on en vient au bouillon de légumes évoqué plus tôt. On va faire cuire les boules de seitan dans ce bouillon de légumes pendant ± 45 minutes. Il est possible que votre boule se délite un peu dans le bouillon, mais ce n’est pas grave : on conser­vera le bouillon qui reste au congé­la­teur pour la prochaine four­née de seitan :-)

Une fois les boules cuites, on les égoutte, et on les congèle pour quand on voudra les utili­ser (ou pas, si vous souhai­ter les manger rapi­de­ment (je dirais quelques jours, mais disons le lende­main au plus tard pour plus de sûreté)).

Comment servir son seitan ?

Person­nel­le­ment, je découpe mes boules en tranches pas trop épaisses et je les fais reve­nir à la poêle avec de l’huile d’olive. D’autres personnes l’uti­lisent comme n’im­porte quelle pièce de viande : en bœuf bour­gui­gnon, dans une soupe, etc.

Moi je mange les tranches en accom­pa­gne­ment, comme de la viande, ou alors je m’en fais un sand­wich (j’adore :D).

Bref, le seitan, c’est bon, c’est facile à faire, vous en faites au goût que vous aimez et ça remplace quand même bien la viande. Pour ce qui est du prix, 500g de gluten de blé revienne à plus ou moins 6€, ce qui n’est pas très cher, sachant que je fais envi­ron 9 boules de seitan avec (donc 9 repas), soit ± 66 centimes de gluten pour une boule. Compa­rez au prix de la viande ! (alors oui, je rajoute une boîte de hari­cots, mais on n’est pas obligé hein !)

Ce chat mange un sandwich vegan :P

Ce chat mange un sand­wich vegan :-)

Crédit de la photo du chat vegan : Ariel Ophe­lia, CC-BY-NC-ND

EDIT on me souffle dans l’oreillette une recette libre de seitan : http://www.cuisine-libre.fr/seitan?lang=fr

Parta­ger

Flattr this!

by Luc at May 01, 2016 03:03 PM

April 02, 2016

Sebastien Badia

Tips GIT: nom de la remote par défaut différent de « master »

Une petite astuce en mode mémo pour changer la branch par défaut d'un repo GIT, assez pratique lorsqu'on utilise gitflow.

Via l'option set-upstream-to (Git >= 1.8.0) en local

Pour changer les informations de suivi de sa branch local vis-à-vis de l'upstream (disponible depuis git 1.8.0).

❯ git branch --set-upstream-to origin/develop

Changement aussi du coté upstream

Il faut aussi changer l'HEAD sur le repo GIT remote, les commandes suivante fonctionnent dans mon cas.

❯ git symbolic-ref HEAD refs/heads/develop
❯ git update-server-info

Coté client on vérifie:

❯ git remote show origin
* remote origin
  Fetch URL: git.debian.org:/git/collab-maint/taskd.git
  Push  URL: git.debian.org:/git/collab-maint/taskd.git
  HEAD branch: develop
  Remote branches:
    develop      tracked
    pristine-tar tracked
    upstream     tracked
  Local branch configured for 'git pull':
    develop merges with remote develop
  Local ref configured for 'git push':
    develop pushes to develop (up to date)

La HEAD branch est bien develop, c'est tout ok :-)

by Sebastien Badia at April 02, 2016 10:01 AM

March 07, 2016

Luc Didry

Retour sur mon nouveau boulot, partie 2

Après 2 mois de télé-travail pour Frama­soft, mon ressenti a-t’il changé ?

Et bien non :

  • j’ap­pré­cie toujours autant de ne pas perdre de temps dans les trans­ports en commun
  • mes horaires souples me permettent de déga­ger du temps dans l’après-midi, ce qui est toujours pratique quand on doit aller cher­cher un colis à la Poste (même si je suis là quand le facteur passe, il n’a pas l’air d’ai­mer sonner si un truc ne rentre pas dans la boîte aux lettres)
  • la théière est toujours là, ainsi que le chat, mais j’ai main­te­nant un fauteuil de bureau : je ne suis plus vautré dans un fauteuil de salon. Même si j’étais scep­tique, je dois avouer qu’a­voir un coin travail est plutôt pas mal pour sépa­rer le boulot de la vie de maison
  • je conti­nue encore et toujours de contri­buer au Libre, que ce soit par des tickets ou des patchs… j’ai même bossé pour Lstu, histoire que sa frama­sof­ti­sa­tion en frama.link soit plus simple, et pour le rendre plus robuste
  • je teste toujours tant et plus de logi­ciels pour nos prochains services (je pense que j’ai installé et testé toutes les solu­tions libres de visio-conf sur le web qui existent, ou pas loin)

Par contre, la vache ! On se tape des bugs et des problèmes bizarres, à se deman­der comment on a fait pour passer entre les gouttes jusque là. La chance sans doute ;-)

Et un bémol, tempo­raire toute­fois : je pensais que j’au­rais plein de temps pour mes projets et en fait, entre les cours pour les ASRALL et la fatigue, c’est à peine si je touche mon pc en dehors des heures de boulot. Je pense qu’une fois que j’au­rais fini les cours et que j’au­rai vrai­ment pris mes marques, ça ira mieux :-)

Parta­ger

Flattr this!

by Luc at March 07, 2016 08:35 PM

Sebastien Badia

Yet another tutorial about Let's Encrypt

Logo Let's Encrypt

Voilà 1 million de certificats Let's Encrypt délivrés (les certificats délivrés par Let's Encrypt); La littérature sur le sujet ne manque pas, mais je vais quand même en apporter une de plus, pour la partie compilation :-)

Pour rappel, Let's Encrypt, est un projet porté par l' « Internet Security Research Group » (ISRG), qui vise à automatiser, rendre accessible à tous, de manière ouverte et gratuite, des certificats SSL

Génération

Nous allons ici, ne pas utiliser le client officiel; Principalement parce qu'il intègre trop de fonctionnalités (serveur web intégré, …), mais aussi parce qu'il ne réponds pas vraiment aux besoins de cet article (arborescence flexible, serveur nginx, …; et que c'est plus facile à lire un script de 200 lignes qu'un énorme client…)

Le client que nous allons utiliser est donc le acme-tiny (écrit en python). Lors de mes pérégrinations sur la toile (oui ok ça fait un peu vieillot, j'aurais pu dire « alors que je surfais sur le web », … :-D), je suis tombé sur ce script letsencrypt.sh. Le coté FQDN à un endroit, et le rechargement lorsque les AltNames changent sont des features appréciables. Après c'est du bash, donc comme vous voulez :)

Création des certificats

De mon coté, j'ai opté pour une arborescence de ce type (certificats générés dans un répertoire dédié, avec un utilisateur dédié).

$ mkdir -p /etc/letsencrypt/{certs,challenges,csr,pem,private}
/etc/letsencrypt/
├── certs
├── challenges
├── csr
├── pem
└── private

Il suffit donc alors de :

  • Créer une clé pour le domaine en question
  • Créer une demande de signature (CSR) en y incluant les noms DNS alternatifs
  • Lancer le client (qui va se charger de créer un challenge) et signer si le challenge est ok.
  • Télécharger et concaténer le certificat obtenu avec le certificat intermédiaire de Let's Encrypt

Le challenge sert ici à ce que let's encrypt vérifie que nous contrôlons bien le domaine pour lequel nous demandons un certificat. Il faut d'ailleurs ajouter à la configuration du serveur web, l'endroit où seront stockés ces challenges.

location /.well-known/acme-challenge/ {
  alias /etc/letsencrypt/challenges/asrall.fr/;
  try_files $uri =404;
}

Coté certificat intermédiaire, ils sont disponibles sur le site de Let's Encrypt.

srg-keys

Bon donc du coup ça donne cela dans un mini-script (pas super beau…)

#!/bin/bash
# bootstrap letsencrypt

account=$1
cert=$2
dns=$3

mkdir -p /etc/letsencrypt/{certs,challenges,csr,pem,private}

pushd /etc/letsencrypt
  if [[ ! -f "./private/${account}.key" ]]; then
    openssl genrsa 4096 > "./private/${account}.key"
  fi
  if [[ ! -f ./pem/intermediate.pem ]]; then
    wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > ./pem/intermediate.pem
  fi
  echo "##### ${cert} #####"
  if [[ ! -f "./private/${cert}.key" ]]; then
    openssl genrsa 4096 > "./private/${cert}.key"
  fi
  mkdir -p "./challenges/${cert}"
  openssl req -new -sha256 -key "./private/${cert}.key" -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=%s" "${dns}")) > "./csr/${cert}.csr"
  acme_tiny.py --account-key "./private/${account}.key" --csr "./csr/${cert}.csr" --acme-dir "/etc/letsencrypt/challenges/${cert}/" > "./certs/${cert}.crt"
  cat "./certs/${cert}.crt" ./pem/intermediate.pem > "./pem/${cert}.pem"
popd

Qu'il suffit de lancer comme ceci (pour l'exemple je génère un certificate asral.fr avec comme domaines gérés asrall.fr et planet.asrall.fr (oui de la pub au passage))

$ bash bootstrap-letsencrypt.sh asrall asrall.fr 'DNS:asrall.fr,DNS:planet.asrall.fr'
##### asrall.fr #####
Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying planet.asrall.fr...
planet.asrall.fr verified!
Verifying asrall.fr...
asrall.fr verified!
Signing certificate...
Certificate signed!

Plutôt cool non? Il suffit alors d'adapter la configuration du serveur web, pour prendre en compte ces certificats. Et passer tout en HTTPS! (dans notre cas, c'est un nginx en reverse proxy qui gère le SSL et forward en HTTP sur une IP privée).

# Asrall
server {
  server_name asrall.fr planet.asrall.fr;
  rewrite ^(.*) https://$host$1 permanent;
}

# Asrall SSL
# DNS:asrall.fr,DNS:planet.asrall.fr
server {
  listen 443;
  ssl on;
  client_max_body_size 20M;
  server_name asrall.fr planet.asrall.fr asrall.sebian.fr;
  ssl_certificate /etc/letsencrypt/pem/asrall.fr.pem;
  ssl_certificate_key /etc/letsencrypt/private/asrall.fr.key;
  ssl_session_timeout 5m;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
  ssl_session_cache shared:SSL:50m;
  ssl_prefer_server_ciphers on;
  ssl_dhparam /etc/letsencrypt/dh4096.pem;
  ssl_ecdh_curve secp384r1;
  add_header Strict-Transport-Security max-age=15768000;
  resolver 127.0.0.1;
  location /.well-known/acme-challenge/ {
    alias /etc/letsencrypt/challenges/asrall.fr/;
    try_files $uri =404;
  }
  location / {
    proxy_pass       http://10.41.1.143;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-Ssl on;
  }
}

Pour la génération du dhparams (4096 bits c'est bien)

openssl dhparam -out dh4096.pem 4096

Et vous voila donc avec une super config et du HTTPS automatisé, on peut aller faire un tour sur imirhil pour un check de la conf et bien sûr pour pouvoir briller en société…

Supervision

Bon c'est bien beau, mais avec tout ça les certificats sont valables que 90j (oui mort à CertPatrol :-() mais pour le coup il va donc falloir superviser tout cela.

Via Certificate Monitor

Si vous utilisez le sympa certificatemonitor (code source) de Raymii, il suffit alors d'ajouter vos FQDN dans l'interface. Et ainsi recevoir une notification avant l'expiration de vos certificats.

Via Checkmk

Sinon si vous avez déjà une bonne veille supervision à base de nagios ou checkmk ou compatible, il suffit d'ajouter les checks via le script check_http.

Dans la conf main.mk de checkmk:

# /etc/checkmk/main.mk
legacy_checks = [
  ## Asrall
  ( ( "check-certificate!asrall.fr", "Certificate Asrall - Letsencrypt", True), ['baloo.sebian.fr']),
  ( ( "check-certificate!planet.asrall.fr", "Certificate Planet Asrall - Letsencrypt", True), ['baloo.sebian.fr']),
]

Et ne pas oublier la check_command associée (on émet un warning lorsque que le certificat expire à J-30 et un critical à J-7)

# /etc/checkmk/conf.d/commands_extra.mk
define command {
  command_name    check-certificate
  command_line    $USER1$/check_http -H $ARG1$ -C 30,7 --sni
}

Renouvellement

Il existe des scripts de renouvellement automatique:

Mais je ne sais pas encore quoi en penser, pour le moment je réagit lorsque que le check passe en warning avec ce mini script bash.

#!/bin/bash

account='asrall'
certs='asrall.fr planet.asrall.fr'

pushd /etc/letsencrypt
  for cert in $certs
  do
    echo "##### ${cert} #####"
    acme_tiny.py --account-key ./private/labriqueinternet.key --csr ./csr/${cert}.csr --acme-dir /etc/letsencrypt/challenges/${cert}/ > ./certs/${cert}.crt
    cat ./certs/${cert}.crt ./pem/intermediate.pem > ./pem/${cert}.pem
  done
popd
systemctl restart nginx

Chocolat

Même si le modèle des CA et bancal, il n'y a plus de raison maintenant de ne pas proposer du HTTPS partout!

by Sebastien Badia at March 07, 2016 07:00 PM

February 12, 2016

Luc Didry

Le coin des jardi­niers : un temps de login trop long

Une nouvelle caté­go­rie est appa­rue sur Frama­cloud : le coin des jardi­niers. C’est là que l’équipe des tech­ni­ciens Frama­soft (dont je fais partie) mettra ses petites astuces, les problèmes que nous avons pu rencon­trer ainsi que leur solu­tion. Je reco­pie­rai ici les articles que j’y écri­rai et je commence aujourd’­hui :-)

Résoudre un temps de login trop long

Sur quelques machines, nous avions un temps de login via ssh extrê­me­ment long. Un sudo su prenait égale­ment beau­coup de temps.

Sans vouloir trol­ler, le coupable était Systemd : un simple sudo systemctl restart systemd-logind.service a résolu le problème.

C’est bête, mais il fallait y penser.

Parta­ger

Flattr this!

by Luc at February 12, 2016 09:21 AM

February 10, 2016

Florent Peterschmitt

i3status - brightnessctl

MAJ : brightnessctl

Dernièrement j’ai try Rust, mais sans rien avoir à en faire. Donc c’est passé à la trappe. Et puis récemment je suis tombé sur une petite limitation de Nginx qui ne permet pas de décompresser le body d’une requête HTTP, avant de la transmettre à un backend défini avec proxy_pass.

Et comme Nginx est écrit en C, et que je suis un peu… rouillé dans ce langage, je me suis dit que s’y remettre tranquillement, ça serait une bonne idée avant d’attaquer.

brightnessctl

brightnessctl

Petit programme type daemon, écrit en C avec libX11.

On démarrera ça via son .xsession par exemple.

i3status

Du coup, tant qu’à faire, petit patch pour i3status, afin d’afficher le pourcentage actuel de luminosité de l’écran, sur un laptop.

Et la conf ~/.i3status.conf :

brightness {
    max = "/sys/class/backlight/intel_backlight/max_brightness"
    cur = "/sys/class/backlight/intel_backlight/brightness"
    #txt = "lum: "
}

Inutile au possible, je sais.

by Florent Peterschmitt at February 10, 2016 02:56 PM

Fézon du C - i3status - luminosité

Huehuehuehuehue. Fézon du C qu’y dit. MÉILÉFOU.

Dernièrement j’ai try Rust, mais sans rien avoir à en faire. Donc c’est passé à la trappe. Et puis récemment je suis tombé sur une petite limitation de Nginx qui ne permet pas de décompresser le body d’une requête HTTP, avant de la transmettre à un backend défini avec proxy_pass.

Et comme Nginx est écrit en C, et que je suis un peu… rouillé dans ce langage, je me suis dit que s’y remettre tranquillement, ça serait une bonne idée avant d’attaquer.

Donc, séance de dégrippage, petit patch pour i3status, afin d’afficher le pourcentage actuel de luminosité de l’écran, sur un laptop.

Et la conf ~/.i3status.conf :

brightness {
    max = "/sys/class/backlight/intel_backlight/max_brightness"
    cur = "/sys/class/backlight/intel_backlight/brightness"
    #txt = "lum: "
}

Inutile au possible, je sais.

by Florent Peterschmitt at February 10, 2016 02:55 PM

January 31, 2016

Romain Dessort

Québec − janvier 2016 : gastronomie québécoise

Gastronomie québécoise

En amateur de bonne bouffe, parlons un peu de la gastronomie d'ici.
Si on s'intéresse à la gastronomie du Québec, on devrait plutôt parler d'archéogastronomie, car aujourd'hui il n'en reste que quelques traces, à part les produits dérivés du sirop d'érable et la poutine (si on considère ça comme un plat) qui restent courant. La culture américaine a largement pris le dessus. Je trouve que comparativement à la France, il n'est pas rare de manger dans des resto (hors fast-food) des trucs sans goût, aseptisés, fades… En fait, après 5 mois ici, j'ai remarqué que les québécois, et je pense que c'est généralisable à tout le Canada et l'Amérique du Nord, accordent beaucoup moins d'importance aux repas, à la qualité de la nourriture et au plaisir de manger. Les « repas » sont souvent expédiés et pris sur le pouce d'ailleurs, pas question de s'éterniser à table comme on a l'habitude en France. Ils mangent presque par contrainte, juste pour satisfaire leur faim. Ou plutôt leur envie de manger, car d'un autre coté je vois régulièrement des gens obèses, dans le sens vraiment maladif.

Mais Montréal abrite pourtant des milliers de restaurants qui représentent à peu près toutes les cuisines du monde (Montréal est une ville extrêmement cosmopolite). J'ai lu souvent dans les guides touristiques que Montréal est une destination de choix pour quelqu'un qui veut gouter à la gastronomie de différent pays. Mais même si les plats sont cuisinés effectivement avec le savoir faire du pays d'origine, les ingrédients eux sont (au moins en partie) ce qu'on trouve sur le continent américains, et j'ai du mal à croire qu'une choucroute ou une pizza ici soit aussi bonne qu'en Allemagne ou qu'en Italie.

Mais bref, on trouve donc à Montréal une très grande quantité de restaurants qui reprennent la gastronomie de différents pays, sauf… celle du Canada, en particulier du Québec ! Et forcement, si elle est déjà peu cuisinée ici, en dehors du Canada elle est quasiment méconnue. Donc pour y gouter, il faut souvent cuisiner les plats soit-même.

Le blog d'À Boire et À Manger en parle à peine malheureusement (voir pas du tout malgré les 4 épisodes), donc je vais vous en parler moi, mais sans dessins…

Malgré qu'elle soit très peu connue, je trouve que la gastronomie québécoise vaut quand même le détour. Elle est assez particulière dans le sens où les associations sont souvent surprenantes et inhabituelles. C'est à l'opposé de la fine cuisine, les plats sont généralement simples, sans raffinements, copieux et bien caloriques. Tout tourne autour de la viande ou de la charcuterie.
La raison est que, premièrement, les pionniers de la Nouvelle France (je ferrai peut-être un article sur l'histoire de la Nouvelle France, c'est assez intéressant, et encore une fois complètement méconnu, je ne me souviens même pas ne serait-ce que l'avoir entrevue en cours d'histoire à l'école) étaient généralement assez pauvres (paysans ou ouvriers) et n'avaient pas une très grande variété d'aliments à leur portée. Mais ils bénéficiez quand même de beaucoup de produits importés grâce au commerce maritime entre la Nouvelle France, les Antilles et la France, ou encore entre la Nouvelle France et la Martinique. D'où la présence de sucre, de mélasse (résidu de raffinage de la canne ou betterave à sucre, bien moins cher que le sucre à l'époque), de rhum depuis les Antilles ou de vin et de sel depuis la France, dans leur cuisine.
L'omniprésence de viande s'explique par l'abondance de gibier et la liberté de chasse (dans le sens pas contrôlée par un seigneur comme en France). Le climat et le travail était difficile, donc il fallait quelque chose de très calorique.

Parmi les plus connues, et le top du top pour moi, on trouve donc les fèves au lard, appelées aussi bines, de l'anglais bean (haricot/fève) qui ne sont donc pas des fèves mais des haricots blanc (même si à l'époque c'était des gourganes appelées aussi fèves des marais, si vous suivez toujours), qu'il faut faire cuire au four pendant une dizaine d'heures à basse température, avec beaucoup de lard, de la mélasse, du coulis de tomate et des épices comme du gingembre et de la moutarde. Ça donne des haricots fondant et bien imprégné du gras du lard, vraiment très bon mais à manger avec des pommes de terre ou du pain, sinon seul c'est vraiment très gras.

Connu surtout pour les controverses quand à son origine et sa facilité de préparation, il y a le pâté chinois, qui consiste en un gratin composé d'une couche de viande hachée, une couche de maïs en grains ou en crème (aussi appelé blé d'Inde) et une couche de purée de pomme de terre. Certains affirment que ce nom a été donné car le plat était consommé quotidiennement par les ouvriers chinois lors de la construction de la ligne ferroviaire pancanadienne, d'autres pensent que ça n'a rien à voir avec les chinois, et que son origine viendrait de la traduction de china pie, une spécialité locale de la ville de South China, dans l'état du Maine. Il y a d'autres théories, mais en résumé on a perdu son origine.

Autre plat typique, pour lequel presque chaque région a sa variante, la tourtière à la viande. Au Sagenay-Lac-Saint-Jean, il s'agit de la tourtière du Lac-Saint-Jean, en Gaspésie de la cipaille, etc… chacune est à priori différente, mais le plat consiste en une couche de pâte, de la viande, hachée ou en petits cubes, de gibier, de bœuf ou de porc, éventuellement marinée, des épices, éventuellement des pommes de terre en cubes, et une seconde couche de pâte pour fermer hermétiquement. Le tout cuit au four à basse température. On peut aussi rajouter des légumes (carottes, navets…) ou remplacer la viande par de la morue, ou encore du saumon. Bref, plein de variantes existent. C'est pas très compliquer à faire, mais on en trouve assez facilement des toutes prêtes dans des boucheries ou boulangeries.

Et puis plein d'autres encore à base de viande toujours : ragout de boulettes de viande, pain de viande, bouillons et ragoût en tout genre etc…

En charcuterie, ils ont moins de chose qu'en France, mais on trouve le fameux cretons, qui peut se comparer avec de la rillettes (d'ailleurs tous les 2 ne s'écrivent qu'au pluriel !) mais fait généralement avec de la viande de porc grasse, plus éventuellement du beurre (pour faire encore plus gras). C'est un plat qui était surtout mangé au petit-déjeuner sur du pain, comme les fèves au lard. On retrouve sinon plein de pâtés (de gibier, de tête, à la bière, etc…), du jambon fumé effiloché, qui est en fait un jambon cuit (blanc) puis fumé dans lequel on prélève non pas des tranches mais des lanières de viande, etc…

Outre tout ce gras, les colons faisaient quand même une très grande consommation de soupe à base de légumes d'hiver qu'ils cultivaient (genre carottes, pommes de terre, navets, courges, betterave etc…). Soupe dans laquelle ils pouvaient rajouter, aller pour changer… un peu de viande ! C'est peut-être la seule chose qui reste autant consommée aujourd'hui, quasiment n'importe quel fastfood, boulangerie etc… qui propose des plats à emporter propose des soupes (mais il ne faut pas s'attendre à un truc exceptionnel niveau goût).

Au niveau sucré, on trouve bien sûr toute sorte de produits de l'érable, allant de l'eau d'érable (aucune transformation) jusqu'au beurre et sucre d'érable, avec la fameuse tire d'érable dans les cabanes à sucre au printemps. Idem pour ce qui est des canneberges et des bleuets (variété de grosses myrtilles), disponible sous pleins de formes différentes : fraiches, en jus, dans des tartes, etc…

En dessert, le plus consommé encore aujourd'hui est le pouding-chômeur fait, encore une fois, avec des ingrédients bon marché : farine, beurre, œuf, lait et sirop de cassonade.

D'origine bien plus plus récente, les populaires beavertails (ou queues de castor) vendues dans des camions ambulants, lors des fêtes foraines et autres animations, sont des pâtisseries faites d'une sorte de pâte à gaufre mise en forme de queue de castor, puis frittes dans l'huile et recouvertes de diverses garnitures. J'imaginais ça bien bourratif, mais en fait pas du tout.

Le Québec fait une très grande production de pomme, principalement au début de l'automne, et est donc un gros producteur de cidre et cidre de glace. Le cidre de glace est fait à partir de jus de pomme concentré par l'action du froid (le jus est stocké dehors à une température largement négative, l'eau qui a formé des cristaux de glace est ainsi retirée au fur et à mesure. Ça permet d'obtenir un cidre plus sucré et alcoolisé, plus ou moins équivalent au vin.

D'origine plus récente, On trouve aussi plusieurs spécificités plus régionales, comme la viande fumée ou les bagels à Montréal, les microbrasseries artisanales un peu partout, les produits de la mer en Gaspésie, etc…

Les trucs chiants (cette fois-ci)

Les unités de mesure… un sujet classique mais je ne me serais jamais douté que c'était autant une prise de tête !
Tout d'abord il y a ceux qui parlent en pouces. Ça c'est simple. Ensuite ceux qui parlent en pieds, mais comme ça ne tombe pas rond, soit parlent ensuite en pouces, soit en fraction de pied. Tout en sachant qu'un pied n'équivaux évidemment pas à un nombre entier de pouces.
Pour illustrer la situation, pour une rallonge électrique de même taille on peut voir noter sur l'étiquette : 3 m, 9' 10", 118", 9,84' ou encore 9' 4/5'.

Et ils aime ça les fractions de pouce pour remplacer les millimètres, ils les utilisent partout. J'ai acheté par exemple une boite de tournevis de précision, dans lequel j'ai des tournevis de 3/32", 5/64" et 1/16". Exercice : classez les du plus petit au plus grand[1]. Bon oui, après avoir réfléchit un peu et avec l'habitude ça vient plus facilement, n'empêche que c'est bien moins simple que si ils avaient utilisé des millipouces (ou des poils de jambe pour continuer dans le délire). Je n'avais lu nul part qu'il fallait réviser ses cours de math avant de venir au Québec ! Car si je veux savoir combien fait 4mm en pouce, diviser 4mm par 2,54 ne m'avancera pas beaucoup avec une bête calculette, je n'aurai pas la fraction la plus proche… Un de mes meilleurs investissements est donc un mètre ruban, gradué à la fois en mètres, pouces et pieds, en un coup d'œil je trouve la bonne fraction.

Et puis, ces histoires de pouces, ça peut devenir dangereux. Un dialogue qui aurait pu arriver chez le coiffeur :

− Et pis, combien tu veux-tu que je t'enlève de pouces?
− Euh, ne touche pas a mes pouces, coupe moi juste mes cheveux, ce sera suffisant!

[1] Réponse : et bien ils sont déjà classés, ils ne sont pas sadiques au point de ranger les tournevis dans le désordre !

January 31, 2016 05:28 PM

January 21, 2016

Romain Dessort

Getting Galaxy S2 GPS to work on Replicant

Last week I gave a talk about Replicant with a live (re)installation of it on my phone at Club Linux Atomic. You can download the slides (in french) here (and LaTeX sources here). There are available under the Creative Common BY-SA 3.0 license.

But let's come back to the topic of this post, the GPS chip of the Samsung Galaxy S2. After my talk, someone asked me how I got the GPS module to work on my phone. There is indeed no support of it on Replicant as the chip (a SiRF star IV GSD4t) is not recognized by standard free software tools like gpsd. Someones already worked on it, but without success at this time. All the work is on this Replicant's wiki page. So if you really need it, you have to use the proprietary code.

I realize that there is no documentation explaining how to install this proprietary code, so here is what I did on my phone. Bear in mind that, unlike proprietary firmwares you need for WiFi/Bluetooth chipset, the proprietary code needed for the GPS is a “real” software which run on your main SoC, and could potentially have access to all your data.

  • First, let's download the CyanogenMod archive corresponding to the Galaxy S2. Replicant is based on CyanogenMod and we are sure that the code we need is chipped with the CyanogenMod distribution.
  • Then you need to extract and upload to your phone this 2 files: gps.exynos4.so and libsecril-client.so:

    adb push system/lib/hw/gps.exynos4.so /system/lib/hw/
    adb shell chmod 644 /system/lib/hw/gps.exynos4.so
    adb push system/lib/libsecril-client.so /system/lib/
    adb shell chmod 644 /system/lib/libsecril-client.so
    

And that's it! Pretty simple, just 2 files but we should have to know the good ones.

January 21, 2016 08:24 PM

January 13, 2016

Sebastien Badia

Le mirror GIT du pauvre (remotes multi URL)

Une petit astuce bien pratique! Non on ne va pas parler du git add -p :-)

Cette astuce là concerne le cas où vous avez deux repo GIT distant et que vous souhaitez les tenir synchronisés (dans le cas où vous n'avez pas accès à ces repos bare, et donc que le git mirror est compliqué).

On assume donc que nous avons un repo GIT local, avec un origin déjà correctement configuré.

❯ git remote show origin -n
* remote origin
  Fetch URL: git+ssh://github.com:22/sbadia/repo.git
  Push  URL: git+ssh://github.com:22/sbadia/repo.git

L'astuce consiste donc à ajouter une url à origin

❯ git remote set-url --add origin git+ssh://gogs@code.ffdn.org:55555/sbadia/repo.git

Dés lors, vous pouvez tout simplement pusher sur origin pour automatiquement envoyer vers les deux repos GIT, ok c'est pas grand chose, mais ça m'a bien rendu service dans mon cas :-)

by Sebastien Badia at January 13, 2016 09:31 AM

January 12, 2016

Luc Didry

Nouvelle année, nouveau boulot

Ça ne vous aura pas échappé, on a encore changé d’an­née. C’est souvent le moment où tout le monde prend de grandes réso­lu­tions que personne ne tien­dra, ou qu’on se met à espé­rer que les (ir)respon­sables poli­tiques cesse­ront leurs clow­ne­ries (fol espoir).

Pour moi, cette nouvelle année corres­pond à un grand chan­ge­ment : j’ai changé de boulot ! Depuis le 4 janvier, je suis offi­ciel­le­ment employé par Frama­soft \o/

C’est pour moi une véri­table joie, car je vais pouvoir bosser par le Libre, pour le Libre :-) Même si dans mon précé­dent boulot, à l’uni­ver­sité de Lorraine, j’uti­li­sais énor­mé­ment d’ou­tils libres, la fina­lité n’était pas la même. Pas que mon ancien boulot m’ait déplu hein, mais être payé pour faire avan­cer la cause du Logi­ciel Libre et de la Culture Libre, c’est juste mon rêve depuis que j’ai décidé de faire la licence ASRALL.

Que vais-je y faire, à Frama­soft ? Tout simple­ment ce que j’y faisais déjà depuis plus ou moins deux ans et demi de façon béné­vole sur mon temps libre : de l’ad­mi­nis­tra­tion système. Et ça, c’est mon kif, ma drogue, mon speed. Juste ce que j’aime :D

Ça fait main­te­nant une semaine que j’ai commencé, et je vois déjà quelques petites choses qui se dégagent de mon nouveau boulot :

  • le télé-travail, c’est quand même pas mal du tout. Je bosse de chez moi, tranquille pépère, la théière et le chat à côté de moi, pas de temps de trajet, je peux faire gueu­ler la musique et si j’ai envie de rester en pyjama toute la jour­née, je peux :P
  • ça demande par contre un poil d’or­ga­ni­sa­tion pour faire ses heures et noter les tâches effec­tuées, mais je m’en sors plutôt bien avec ktime­tra­cker : une tâche du nom de la jour­née, je lance le chrono, et je rajoute des sous-tâches pour chaque tâche à effec­tuer. On ne me demande pas de comp­ter combien de temps je passe sur chaque tâche, donc ça va bien comme ça. Je peux arrê­ter le chrono de la tâche “jour­née” pour faire une pause et reprendre après.
  • avoir des horaires vrai­ment souples, c’est un pur bonheur.
  • pour l’ins­tant, les tâches à effec­tuer sont plutôt courtes, les résul­tats rapides à évaluer… c’est très agréable de voir les choses évoluer rapi­de­ment. Pas de grand truc à faire en 6 mois avec 3 ou 4 personnes de services diffé­rents : au final, c’est plutôt agile comme fonc­tion­ne­ment, sans les contraintes d’une vraie méthode agile certi­fiée truc-muche.
  • la distance entre les diffé­rents sala­riés de Frama­soft (Lyon, Toulouse, en Ariège, Nancy) n’est pas gênante : une réunion télé­pho­nique en début de semaine pour voir les trucs à faire en prio­rité, et tout le reste passe par mail ou jabber (ou SMS ou télé­phone si c’est urgent ou compliqué/trop long à expliquer à l’écrit)
  • la toute-puis­sance : je suis embau­ché comme « respon­sable infra­struc­ture et systèmes ». En gros, au niveau tech­nique, je suis le chef (vous inquié­tez pas, je suis pas un despote, j’écoute les besoins et idées des autres hein :D). Du coup, bah ça me plaît ! Je connais bien l’in­fra­struc­ture (tu parles, c’est moi qui ait fait sa refonte), son fonc­tion­ne­ment et comment on la gère au quoti­dien, donc les déci­sions sont rapides à prendre..
  • Frama­soft, c’est plein de services, donc plein d’ou­tils libres auxquels poten­tiel­le­ment contri­buer : depuis le 4 janvier, j’ai déjà fait plusieurs merge-requests sur des projets qu’on utilise. Ça fait plai­sir d’avoir plus d’oc­ca­sions de contri­buer au Libre :-)
  • bosser toute la semaine plutôt que juste sur mon temps libre, je sens que ça va bien nous aider à sortir plein de nouveaux services en 2016
  • déga­ger du temps libre, ça va aussi m’ai­der à sortir de nouveaux outils !

Bref, j’en­tame 2016 du bon pied, et confiant !

Bonne année !

Parta­ger

Flattr this!

by Luc at January 12, 2016 09:42 AM

January 11, 2016

Sebastien Badia

LDN BGP - Two AS one server

Bon ok, on arrête tout de suite la similitude scabreuse…

État actuel

Nous n'avons jamais trop communiqué sur ce sujet (si ce n'est dans nos comptes-rendus de réunion, ou d'assemblé générale), cette configuration n'est maintenant plus d'actualité puisque Alsace Réseau Neutre vole maintenant de ses propres ailes et même bien mieux, ils disposent d'une demi baie en data center!

Introduction

Dans le cadre de Lorraine Data Network (Association pour la défense d'un Internet Libre Décentralisé et Neutre, dont un des moyens d'action est d'être fournisseur d'accès à Internet), pour des contraintes techniques et de future indépendance, nous avons mis en place deux AS (Autonomous System) sur une même machine physique.

Ce type de configuration n'est pas très commune, les autres solutions sont soit de virtualiser. Mais pour des routeurs de bordure (recevant une full-view (toutes les routes d'Internet)) ce n'est généralement pas conseillé, pour des raisons de performance (les fameux paquets par secondes), soit on utilise deux machines physiques :) mais nous sommes une petite association, et le but était de lancer une association amie ARN (Alsace Réseau Neutre) à moindre frais, et donc sur un seul serveur (celui-ci étant en Data Center).

Après de longues concertations et différents tests en bac à sable, nous avons finalement opté pour une solution à base de bird (daemon libre de routage) dans des namespaces réseau (netns).

Coté implémentation

Nous gérons toutes nos configurations avec l'outil de gestion de confs Puppet, nous avons donc développé un module pour bird, puppet-bird, celui-ci se charge d'installer bird, désactiver le service/init par défaut et installer la configuration bird{,6} et le script/unit d'init correspondant. Nous avons donc deux processus bird par netns:

  • bird-ldn et bird6-ldn dans le netns ARN
  • bird-ldn et bird6-ldn dans le netns LDN

Les unit d'init ont été adaptés pour lancer les processus dans les netsns correspondants.

/sbin/ip netns exec $name_space /usr/sbin/bird -c $config_file -s $ctl_file >> "$stdout_log" 2>> "$stderr_log" &
/sbin/ip netns exec $name_space /usr/sbin/bird6 -c $config_file -s $ctl_file >> "$stdout_log" 2>> "$stderr_log" &

Coté livraison BGP (Border Gateway Protocol) avec notre transitaire, nous avons un VLAN par association, ce qui permet « d'enfouir » facilement l'interface dans le namespace correspondant.

Julien à même fait un super schéma récapitulant tout notre configuration, celui-ci est nettoyé de toutes les IP de production ainsi qu'une vidéo d'explication de notre schéma d'adressage réseau.

Sinon pour la petite pub, Gitoyen à publié sa (plutôt bien faite) configuration BGP pour bird, c'est dispo sur la forge de la Fédération FDN.

Visualisation

Pour ce qui est des looking-glass et channel de contrôle, c'est tout pareil, il suffit juste de prendre en compte la contrainte du namespace, et donc d'adapter les commandes en conséquence.

Par exemple pour la commande ctl de brid:

alias birdc-ldn='ip netns exec ldn birdc -s /var/run/bird-ldn.ctl'
alias birdc6-ldn='ip netns exec ldn birdc6 -s /var/run/bird6-ldn.ctl'

Ou pour notre looking-glass qui utilise le looking-glass bird

DAEMON="/usr/local/lookingglass-ldn/lgproxy.py"
DAEMONUSER="lookingglass-ldn"
DEAMON_NAME="lookingglass"
PID="/var/run/lookingglass.pid"
/sbin/ip netns exec ldn /sbin/start-stop-daemon --background --name $DEAMON_NAME --start --quiet \
  --pidfile $PID --make-pidfile --chuid $DAEMONUSER --exec $DAEMON

Performances et gestion

Pour ce qui est gestion, cela demande forcement plus de configuration (tout est doublé), et il faut adapter les unit d'init et confs mais aussi les commandes de contrôle et de visualisation (lg). Par contre une fois tout ceci derrière, la gestion est exactement la même. Coté accès admin, les admins de confiance des deux structures ont accès à la machine, et donc peuvent potentiellement influer sur le routeur de l'association amie. (Ce n'est pas vraiment un problème dans notre cas).

Coté performances le fait de faire tourner bird dans un netns au lieu de directement sur l'hôte est complètement négligeable, par contre il faut dimensionner sa machine en conséquence car elle accueille alors pas deux full-views, pas 3 mais oui c'est bien 4 full-view mesdames et messieurs! (deux en IPv6 et deux en IPv4).

bird> s mem
BIRD memory usage
Routing tables:    172 MB
Route attributes:  125 MB
ROA tables:       8680  B
Protocols:         124 kB
Total:             297 MB

Niveau processus, 320m en virtuel et 310m en résidentiel

by Sebastien Badia at January 11, 2016 10:53 AM