Sunday, February 7 2016

Transformer une découpeuse laser avec Arduino et Grbl

De nombreuses découpeuses laser sont disponibles sur AliExpress (plateforme de vente chinoise) à des tarifs défiant toute concurrence. L'usage d'une découpeuse laser était d'ailleurs présentée dans le numéro de décembre de Linux Pratique (page 24, "Réalisez des gravures laser à l'aide d'Inkscape").

flowRoot4158.jpg

Attention ! Une découpeuse laser est un outil dangereux : les lasers utilisés sont très puissants et provoqueraient la cécité totale de toute personne qui regarderait le faisceau même brièvement. Équipez-vous de lunettes avec un abattement optique suffisant dans la longueur d'onde de travail et ne regardez jamais le faisceau même équipé. Méfiez-vous également des réflexions lumineuses scélérates ! Enfin, les matérieux découpés peuvent s'enflammer sous l'action du laser. L'usage d'une découpeuse laser nécessite une attention constante !

La découpeuse laser sur laquelle je mettais la main dernièrement avait un défaut majeur : elle n'était contrôlable qu'à l'aide de deux binaires chinois impossibles à exécuter sous Linux et à la qualité médiocre... Qu'à cela ne tienne : conservons le matériel mais remplaçons l'intelligence par un Arduino équipe de Grbl.

À propos de Grbl

Grbl (https://github.com/grbl/grbl) est un micrologiciel libre développé sur Arduino pour contrôler des graveuses CNC (Computer Numerical Control), i.e. des fraiseuses munis d'une tête mobile contrôlée en X, Y et Z par un ordinateur. Grbl interprète du G-code (cf. plus bas) et déplace en conséquence un outil sur 3 axes (X, Y et Z) et contrôle la puissance de cet outil. Il comprend de multiples optimisations sur l'usage et le déplacement des moteurs afin de gérer correctement les accélérations, les trajectoires...

Dans le cas de notre laser, nous n'aurons pas d'axe Z et nous nous contenterons d'utiliser Grbl pour contrôler X, Y et la puissance du laser (que l'on contrôlera comme la vitesse de rotation d'une fraise).

À propos de G-code

Le G-code est un langage de programmation inventé dans les années 1950 pour le contrôle des machines CNC. Il comprend un certain nombre d'instructions pour le contrôle d'équipements, par exemple :

G21 (définit l'unité de travail comme étant le millimètre)
M5 (éteint l'outil : la fraise, le laser)
F400 (choisit une vitesse de déplacement de 400 mm/min)
S500 (définit la puissance de l'outil : 500 RPM pour la fraise)

G00 X5 Y5 Z5 (déplacer l'outil vers [x,y,z] = [5,5,5] en laissant la machine choisir le chemin)
G01 X10 Y10 (déplacer l'outil vers [x,y] = [10,10] en effectuant une ligne droite, on ne change pas Z)
G02 X20 Y10 I5 J0 (effectuer un arc de cercle de centre [x,y] = [15,10] jusqu'au point [x,y] = [20,10])
M3 (démarre l'outil à la puissance sélectionnée auparavant i.e. S500)
...
M5 (éteint l'outil)

Il est à noter que Grbl ne supporte pas toutes les instructions du G-code (il y a des commandes exotiques qui n'ont pas un intérêt sensationnel et qui alourdiraient le code chargé sur Arduino) mais les principales sont bien gérées.

Mise en pratique

On supprime donc l'électronique chinoise embarquée initialement et on la remplace par un Arduino couplé à deux easydrivers pour contrôler les moteurs (stepper motors) contrôlant les axes X et Y ainsi que le laser. Le laser est contrôlé par 3 fils : une alimentation, une masse et un fil de contrôle par modulation TTL i.e. envoi d'un signal carré avec une fréquence de plus en plus élevée (jusqu'à 10 kHz) qui commande la puissance.

Le circuit ressemble alors à ceci : laser_sketch.png

On peut alors charger le micrologiciel Grbl sur l'Arduino comme décrit ici. Si on se connecte en série à l'Arduino (avec un baud rate à 115 200), on doit alors voir à l'allumage :

Grbl 0.9j ['$' for help]

Grbl (version 0.9j) est prêt à recevoir nos commandes !

On peut alors lancer les commandes de son choix dans le port série pour interagir avec Grbl et contrôler la découpeuse laser.

Pour plus d'aisance, on pourra installer un logiciel de contrôle tel que UniversalGcodeSender disponible ici.

Screenshot_2016-02-07_05-57-43.png

La machine est désormais prête à recevoir des instructions en G-code. Il ne reste plus qu'à utiliser la méthode de son choix pour générer les G-codes de ses créations.

Générer des G-codes avec Inkscape

Il existe des extensions pour générer les G-codes à partir de chemins vectoriels dans Inkscape. L'extension de base est même installée par défaut dans Inkscape :

Screenshot_2016-02-07_06-05-01.jpg

On pourra se référer à ces documentations pour l'utiliser, éventuellement en adaptant quelque peu au cas du laser pour lequel l'axe Z ne compte pas et les vitesses peuvent être plus élevées :

Quelques ordres de grandeur

Avec un laser de 5.5W à la longueur d'onde de 450 nm (laser bleu) :

  • on dessine joliment sur du carton brun à F400 / S600
  • on découpe 1 mm de bois avec F200 / S1000 en repassant 4 fois sur le trait
  • on grave le bois clair avec F200 / S1000 et un seul passage

Bonne gravure et bon découpage laser !

Saturday, February 6 2016

ino pour Arduino : compiler, envoyer et écouter en série sans l'IDE Arduino

L'Arduino IDE est super pour débuter. Mais rapidement, on peut se sentir un peu à l'étroit dans l'outil. Je l'ai donc avantageusement remplacé par mon éditeur de texte habituel (Atom) et "ino" (http://inotool.org/) pour communiquer avec les planches Arduino.

Installer ino

ino s'installe facilement sur une machine munie de Python2.7 par :

pip install ino

ou alors en récupérant les sources d'ino ici.

Il faut également installer l'IDE Arduino et picocom pour la communication sur le port série - sur Debian Jessie on pourra l'installer ainsi :

apt install arduino picocom

Utiliser ino

Avant toute chose, on crée un nouveau projet :

mkdir mon_projet
cd mon_projet
ino init

On place alors le code de son choix dans le fichier 'sketch.ino' placé dans le dossier 'src'.

Pour compiler :

ino build

Pour envoyer sur l'Arduino :

ino upload

Et pour écouter sur le port série :

ino serial

Pour aller plus loin

On pourra lancer :

ino --help

ou aller lire ici : http://inotool.org/quickstart

Constuire un photomètre avec Arduino

Nous allons expliquer ici comment fabriquer un photomètre avec la plateforme Arduino et le composant BH1750 (encore appelé GY-30, fiche technique ici) que l'on trouve pour quelques euros chez les bons revendeurs électroniques.

Un photomètre qui parle en série

Une première version du photomètre sera simple : nous utiliserons les facultés d'Arduino à communiquer via un port série pour afficher le niveau de luminosité mesuré. Le circuit est alors assez simple (cf. représentation ci-dessous) :

  • le pin VCC du capteur se connecte au pin 5V de l'Arduino
  • le pin GND du capteur se connecte au pin GND de l'Arduino
  • le pin SDA du capteur se connecte au pin A4 (Analogique 4) de l'Arduino
  • le pin SDL du capteur se connecte au pin A5 (Analogique 5) de l'Arduino

Uno_et_BH1750.png

On compile alors le code suivant et on le charge sur l'Arduino (par exemple avec l'IDE Arduino) :

#include <Wire.h>
 
int BH1750_address = 0x23; // i2c Addresse
byte buff[2];
 
void setup() {
  
  Wire.begin();
  BH1750_Init(BH1750_address);
  
  delay(200);
  Serial.begin(9600);
  Serial.println("Démarrage du système... patientez svp !");
}
 
void loop() {
  
  float valf=0;
 
  if(BH1750_Read(BH1750_address)==2){
    valf=((buff[0]<<8)|buff[1])/1.2;
  
    if(valf<0) {
      Serial.print("> 65535");
    }
    else {
      Serial.print((int)valf,DEC);
    }
    Serial.println(" lx"); 
  }
  delay(1000);
}
 
void BH1750_Init(int address) {
  Wire.beginTransmission(address);
  Wire.write(0x10); // 1 [lux] aufloesung
  Wire.endTransmission();
}
 
byte BH1750_Read(int address) {
  byte i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()) {
    buff[i] = Wire.read(); 
    i++;
  }
  Wire.endTransmission();  
  return i;
}

Et hop, sur le port série, on peut voir :

Démarrage du système... patientez svp !
92 lx
92 lx
92 lx
75 lx
47 lx
342 lx
43 lx

Un photomètre avec son propre écran LCD

Rajoutons un écran LCD pour afficher le résultat sans avoir à ouvrir un port série ! Nous allons donc brancher un LCD Keypad Shield (tel qu'ici) sur l'Arduino, et nous allons modifier le code comme suit :

#include <Wire.h>
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int BH1750_address = 0x23; // i2c Addresse
byte buff[2];

void setup() {

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Look the world");

  Wire.begin();
  BH1750_Init(BH1750_address);

  delay(200);
  Serial.begin(9600);
}

void loop(){
  float valf=0;
  if(BH1750_Read(BH1750_address)==2) {
    valf=((buff[0]<<8)|buff[1])/1.2;
    if(valf<0) {lcd.setCursor(0,0); lcd.print("> 65535 lx");}
    else {lcd.setCursor(0,0); lcd.print((int)valf,DEC); lcd.print(" lx                    ");}
  }
  else {
    lcd.setCursor(0,0); lcd.print("Error...             "+BH1750_Read(BH1750_address));
  }
  delay(1000);
}

void BH1750_Init(int address) {
  Wire.beginTransmission(address);
  Wire.write(0x10); // 1 [lux] aufloesung
  Wire.endTransmission();
}

byte BH1750_Read(int address){
  byte i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()){
    buff[i] = Wire.read();
    i++;
  }
  Wire.endTransmission();
  return i;
}

On compile et on charge sur l'Arduino, et hop le tour est joué !

photometre.jpg

Friday, February 5 2016

ownCloud : erreur dans mise à jour de 8.2.1.4 vers 8.2.2.2

ownCloud refusait obstinément de se mettre à jour automatiquement vers la version 8.2.2.2 avec ce message d'erreur :

Update failed.Unable to move /var/www/owncloud/_oc-upgrade/8.2.2.2/core/resources to /var/www/owncloud/resources

Le message d'erreur a disparu et la mise à jour s'est effectuée sans encombre après avoir ajouté une ligne

"resources"

au fichier owncloud/apps/updater/lib/files.json dans la section "8.1"...

Si cela peut aider qqn...

Thursday, February 4 2016

OpenSSL : détecter la péremption d'un certificat avec l'option -checkend

Dans un précédent article (ici), je proposais une méthode pour renouveler les certificats Letsencrypt en l'absence d'un mécanisme officiel pour le moment. Dans cette méthode (enfin ce script), je vérifiais la date du certificat avec "date -r", extrapolant la date de fin de validité à l'aide de la date de création du certificat et de la connaissance de la durée de validité par défaut des certificats de Letsencrypt.

Il y a en fait beaucoup plus intelligent ! Merci à mon beau-frère pour cette idée (toujours écouter au moins d'une oreille son beau-frère !)

Le manuel d'OpenSSL nous apprend l'existence de l'option suivante :

-checkend arg
checks if the certificate expires within the next arg seconds and exits non-zero if yes it will expire or zero if not.

Dès lors, il est facile de détecter si un certificat périme dans les 30 jours (2 592 000 secondes) :

if openssl x509 -checkend 2592000 -noout -in file.pem
then
  echo "Certificat valide encore au moins 30 jours"
else
  echo "Certificat périmant dans les 30 jours... à renouveler !"
fi

Monday, February 1 2016

Letsencrypt : renouveler intelligemment malgré les limites de la bêta

Depuis Mai 2016, le service Let's Encrypt n'est plus en bêta et les limitations de la bêta évoquées ici ne sont plus mordantes !

Depuis Mai 2016, le client letsencrypt est devenu certbot (https://certbot.eff.org/) ! les commandes évoquées plus bas sont sans doute valables en remplaçant letsencrypt-auto par certbot ! Il faut aussi noter que le client certbot dispose désormais de fonctions de renouvellement plus élaborées qu'auparavant ! Cet article est conservé pour archive et inspiration.

Letsencrypt se présente comme le futur du chiffrement sur internet. Bien que déjà fonctionnel, le service offert est encore en phase de test (bêta) et par conséquent certaines contraintes s'appliquent aux usagers testeurs. Parmi ces contraintes, les 2 les plus bloquantes sont :

  • pas de système de renouvellement automatique pour le moment (c'est prévu, vivement !)
  • limite imposée de 5 certificats par domaine par semaine (i.e. qu'il faut attendre une semaine pour pouvoir créer des certificats pour un nouveau sous-domaine d'un domaine qui possède déjà 5 certificats de sous-domaine)

Pour Letsencrypt qui émet des certificats à la validité courte de 3 mois, le renouvellement doit être fait régulièrement et il correspond ni plus ni moins à l'édition d'un nouveau certificat.

La contrainte évoquée plus haut est bloquante pour le renouvellement : en effet il n'est pas possible de renouveler plus de 5 certificats par semaine pour un même domaine...

Principe du renouvellement à terme

A terme, un système de renouvellement automatique sera intégré à Letsencrypt et il suffira de lancer tous les 2 mois (par exemple via cron) la commande demandant le renouvellement de tous les certificats en approche de péremption. Vivement cela !

Une méthode fonctionnelle aujourd'hui

Aujourd'hui, à nous de créer l'automatisme qui va bien et qui permettra aussi de contourner la limite des 5 renouvellements par semaine (en réalisant un roulement). Nous allons détailler ici un script qui, appelé chaque semaine, :

  • détecte les certificats qui ont moins de 30 jours de validité (2592000 secondes)
  • demande le renouvellement de chaque certificat dans ce cas

Voici le code du script :

#!/bin/bash
declare -a list=(
"/etc/letsencrypt/live/domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine1/website -d domaine1.tld -d www.domaine1.tld"
"/etc/letsencrypt/live/sous.domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/sous/domaine1/website -d sous.domaine1.tld -d www.sous.domaine1.tld"
"/etc/letsencrypt/live/domaine2.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine2/website -d domaine2.tld -d www.domaine2.tld"
)

for line in "${list[@]}"
do
	IFS=";" read -ra stuff <<< $line
	folder=${stuff[0]}
	command=${stuff[1]}
        if openssl x509 -checkend 2592000 -noout -in $folder/fullchain.pem
        then
                echo "Nothing to do for $folder"
        else
                $command
                rm -f $folder/total.pem
                cat $folder/fullchain.pem $folder/privkey.pem > $folder/total.pem
                echo "Done for $folder"
        fi
done

Rapidement :

  • on commence par lister dans un tableau chaque domaine dont il faut s'occuper (en indiquant le chemin correspondant à ce domaine dans le dossier /etc/letsencrypt/live/) et, séparée par ";", la commande Letsencrypt utilisée pour le renouvellement. Il s'agit de la même commande que pour la création initiale du certificat sauf que l'on ajoute l'option "--renew-by-default"
  • on parcourt ensuite le tableau élément par élément :
    • en vérifiant l'âge du certificat (avec openssl)
    • en lançant la commande de renouvellement s'il est trop proche de la péremption

Si l'on utilise Letsencrypt avec Pound, on ajoutera 2 actions :

  • remplacer le fichier .pem utilisé par Pound par la nouvelle version obtenue
  • redémarrer Pound

Le script devient alors :

#!/bin/bash
declare -a list=(
"/etc/letsencrypt/live/domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine1/website -d domaine1.tld -d www.domaine1.tld"
"/etc/letsencrypt/live/sous.domaine1.tld;certbot --renew-by-default -a webroot --webroot-path /path/to/sous/domaine1/website -d sous.domaine1.tld -d www.sous.domaine1.tld"
"/etc/letsencrypt/live/domaine2.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine2/website -d domaine2.tld -d www.domaine2.tld"
)

for line in "${list[@]}"
do
	IFS=";" read -ra stuff <<< $line
	folder=${stuff[0]}
	command=${stuff[1]}
        if openssl x509 -checkend 2592000 -noout -in $folder/fullchain.pem
        then
                echo "Nothing to do for $folder"
        else
                $command
                rm -f $folder/total.pem
                cat $folder/fullchain.pem $folder/privkey.pem > $folder/total.pem
                echo "Done for $folder"
        fi
done
service pound restart

Archive

Dans une ancienne version de ce billet, on utilisait le morceau de script suivant se basant sur la date de dernière modification du fichier de certificat plutôt que d'utiliser openssl, mais c'est moins propre. Pour archivage, voici le test qui était alors utilisé (renouvellement des certificats plus vieux que 60 jours) :

	timesincelastchange=$(expr $(expr $(date +%s) - $(date +%s -r $folder/fullchain.pem )) / 86400)
	if [ $timesincelastchange -gt 60 ]
	then
		$command
		echo "Done for $folder"
	else
		echo "Nothing to do for $folder"
	fi

Dé-bannir une adresse IP avec Fail2ban

fail2ban-client set JAILNAME unbanip IPADDRESS

où l'on remplacera JAILNAME par le nom de la "jail" de Fail2ban à l'origine du bannissement et IPADDRESS par l'adresse bannie.

Par exemple :

fail2ban-client set ssh unbanip 1.2.3.4

Fail2ban & NAT avec des règles PREROUTING

Par défaut, les règles de Fail2ban s'appliquent à la chaîne INPUT. Or cette dernière chaîne n'est pas consultée lors de redirections de paquets avec des règles de type NAT (PREROUTING).

Pour que l'action de Fail2ban soit efficace, il faut alors lui indiquer d'inscrire les adresses à bannir dans la chaîne FORWARD qui est consultée dans le cas d'une redirection NAT.

Concrètement, dans /etc/fail2ban/jail.local, dans la section de son choix, on ajoute la ligne :

chain    = FORWARD

Et le tour est joué !

Monday, December 28 2015

Let's Encrypt et Gitlab

Pour permettre la génération d'un certificat avec Let's Encrypt pour Gitlab, il m'a été nécessaire d'effectuer les opérations suivantes :

  • Modifier la gestion des fichiers d'assets dans gitlab/config/environments/production.rb,
config.serve_static_assets = true
  • Redémarrer Gitlab par
service gitlab restart
  • Puis effectuer la génération du certificat avec le script Let's Encrypt en pointant le webroot vers le dossier public :
certbot certonly -a webroot --webroot-path /path/to/gitlab/public -d mongit.domaine.tld

Sunday, December 20 2015

Let's Encrypt et le load-balancer Pound

Pound est un reverse-proxy et un load-balancer libre fort performant. Il est très pratique en frontal d'un ensemble de services web et peut notamment se charger d'effectuer la compression TLS des flux. Il est bien sûr possible de l'utiliser avec Let's Encrypt tel que décrit ici.

Pour ce faire, imaginons que nous venons de lancer la commande suivante :

certbot certonly -a webroot --webroot-path /var/www/mon-site/ -d mondomaine.tld

Un nouveau dossier a été créé : /etc/letsencrypt/live/mondomaine.tld/. Il contient le certificat et également la clé privée utilisée pour ce certificat. Afin que Pound fonctionne, il faut regrouper le certificat et la clé privée dans un même fichier :

cat /etc/letsencrypt/live/mondomaine.tld/fullchain.pem /etc/letsencrypt/live/mondomaine.tld/privkey.pem > /etc/letsencrypt/live/mondomaine.tld/total.pem

et il faut alors référencer le fichier total.pem dans la configuration de Pound :

ListenHTTPS
	Address 2001:2002:2003:2004::
        Port    443
	Cert	    "/etc/letsencrypt/live/mondomaine.tld/total.pem"

et il ne reste plus qu'à redémarrer Pound par :

service pound restart

Saturday, December 19 2015

Utiliser Let’s Encrypt avec ownCloud/Nextcloud, Piwik, Dotclear, Drupal, Wordpress, des applications Rails et des sites statiques !

Depuis le début du mois, il est possible d'utiliser "Let's Encrypt" pour obtenir des certificats TLS/SSL pour sécuriser ses sites et services en ligne (bien que le système soit toujours annoncé en bêta). Ce matin, je décidais donc de m'y mettre et de remplacer mes certificats StartSSL.

Depuis Mai 2016, le service Let's Encrypt n'est plus en bêta et les limitations de la bêta évoquées ici ne sont plus mordantes !

Depuis Mai 2016, le client letsencrypt est devenu certbot (https://certbot.eff.org/) ! les commandes évoquées plus bas sont sans doute valables en remplaçant letsencrypt-auto par certbot !

Première étape : comprendre le fonctionnement

Le principe est assez simple et n'est pas très différent de celui déjà rencontré pour l'obtention de certificats auprès des opérateurs "classiques" (les StartSSL et consors). Classiquement, (i) on démontre la possession réelle du nom de domaine, (ii) on génère une clé privée et une clé publique et on transmet la clé publique à l'opérateur de certification qui (iii) fournit en retour un certificat attestant le lien entre le nom de domaine et la paire de clés crypto utilisées pour l'établissement de communications sécurisées. Avec Letsencrypt, ces étapes ont lieu mais automatiquement. Dans l'utilisation commune, Letsencrypt vient avec un script Python (letsencrypt-auto) qui va faire tout le travail :

  • le script va créer un fichier mondomaine.tld/.well-known/acme-challenge/chaîne-choisie-au-hasard et le serveur distant cherchera à accéder à ce fichier pour authentifier la possession/maîtrise du domaine mondomaine.tld
  • puis le script génère et échange les clés cryptographiques avec l'autorité de certification Letsencrypt
  • et le certificat est rapatrié
  • enfin, dans certains cas, le script se charge même de l'installer !

Par rapport à ce qui est fourni habituellement par les acteurs privés :

  • la chaîne de bout en bout est plus transparente et libre
  • le certificat est gratuit
  • le certificat n'a une validité que de 90 jours (mais le renouvellement est gratuit et peut être géré automatiquement par le script tous les 2 mois par exemple)
  • les certificats n'autorisent pas les wildcards (e.g. *.mondomaine.tld) ce qui a déjà été fort amplement débattu partout sur le web mais ne semble pas devoir changer.

Deuxième étape : installer Let’s Encrypt

Nous allons commencer par le cas simple d'un site statique. Le script letsencrypt se télécharge sur la machine d'hébergement à l'aide de git :

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

puis on peut lancer le script (qui va effectuer les installations supplémentaires nécessaires) par :

./letsencrypt-auto

Cela fonctionne très bien sur Debian Jessie et sans doute les autres systèmes récents (c'est la version de Python qui semble être un des facteurs limitants pour les "vieilles" distributions). On reviendra sur ce point plus loin.

Troisième étape : utiliser Let’s Encrypt pour un site statique

Commençons par le cas simple d'un site statique hébergé dans /var/www/mon-site/ et servi par Apache.

./letsencrypt-auto certonly -a webroot --webroot-path /var/www/mon-site/ -d mondomaine.tld

certonly car nous demandons à Let’s Encrypt de générer le certificat et de s'arrêter là (donc de ne pas l'installer lui-même). -a webroot car nous indiquons à Let’s Encrypt où se trouve la racine du site afin qu'il puisse y placer le fichier de "challenge" (.well-known/acme-challenge/chaîne-choisie-au-hasard). Et -d mondomaine.tld pour indiquer le domaine. Il est possible d'indiquer plusieurs domaines s'ils partagent le même webroot par exemple :

./letsencrypt-auto certonly -a webroot --webroot-path /var/www/mon-site/ -d mondomaine.tld -d www.mondomaine.tld

Dans ce cas le certificat contiendra les 2 domaines en SAN (Subject Alternative Names).

Au premier lancement, le script demande de saisir l'adresse courriel qui sera rattachée au compte (et qui recevra les éventuelles notifications de péremption des domaines non renouvelés).

Et hop, le script travaille et un certificat tout neuf (et valide !) est déposé dans /etc/letsencrypt/live/mondomaine.tld/fullchain.pem. La clé privée correspondante se trouve dans /etc/letsencrypt/live/mondomaine.tld/privkey.pem. Ce certificat peut alors être utilisé comme il l'a toujours été (par ex. appelé dans la configuration d'Apache ou de votre load balancer) - je détaille ici comment l'utiliser avec le load balancer Pound.

Let’s Encrypt et un blog dotclear

Aucune surprise ni difficulté avec dotclear :

./letsencrypt-auto certonly -a webroot --webroot-path /chemin/vers/blog/dotclear -d blog.bandinelli.net

et hop, /etc/letsencrypt/live/blog.bandinelli.net/fullchain.pem est créé ! Une commande pour un certificat, c'est classe et pratique !

Let’s Encrypt et Piwik

Aucune surprise ni difficulté avec Piwik :

./letsencrypt-auto certonly -a webroot --webroot-path /chemin/vers/racine/piwik -d piwik.mondomaine.tld

et hop, /etc/letsencrypt/live/piwik.mondomaine.tld/fullchain.pem est créé !

Let’s Encrypt et Wordpress

Aucune surprise ni difficulté avec Wordpress :

./letsencrypt-auto certonly -a webroot --webroot-path /chemin/vers/racine/wordpress -d mondomaine.tld

et hop, /etc/letsencrypt/live/mondomaine.tld/fullchain.pem est créé !

Let’s Encrypt et Drupal 7

Une petite astuce est nécessaire ici : par défaut le moteur de Drupal demande au serveur web de réécrire toutes les adresses et empêche l'accès à certaines adresses. Ainsi, le fichier .htaccess se trouvant à la racine d'un site Drupal contient la ligne suivante :

RewriteRule "(^|/)\." - [F]

Cette ligne ordonne à Apache de renvoyer vers la page "Accès interdit" toute requête qui débuterait par ".". Il faut bien évidemment désactiver cette sécurité pour Letsencrypt :

RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
RewriteRule "(^|/)\." - [F]

La condition RewriteCond désactive la redirection qui suit pour le challenge de letsencrypt seulement.

Une fois cela effectué, on peut utiliser la commande classique pour obtenir le certificat valide dans /etc/letsencrypt/live/mondomaine.tld/fullchain.pem :

./letsencrypt-auto certonly -a webroot --webroot-path /chemin/vers/site/drupal/ -d mondomaine.tld

Let’s Encrypt et ownCloud/Nextcloud

Une petite astuce est nécessaire ici : par défaut le moteur d'ownCloud demande au serveur web de réécrire toutes les adresses et empêche l'accès à certaines adresses. Ainsi, le fichier .htaccess se trouvant à la racine d'une instance ownCloud/Nextcloud contient la ligne suivante :

RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]

elle renvoie vers 404 tous les appels à un chemin démarrant par ".". Il est bien sûr nécessaire de désactiver cette ligne conditionnellement :

RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]

Ensuite, sans surprise, pour obtenir le certificat valide dans /etc/letsencrypt/live/mondomainecloud.tld/fullchain.pem :

./letsencrypt-auto certonly -a webroot --webroot-path /chemin/vers/owncloud/ -d mondomainecloud.tld

Let’s Encrypt et une application Ruby on Rails

Aucune surprise ni difficulté avec une application Ruby on Rails servie en production par Unicorn, à condition de bien choisir le dossier public comme webroot :

./letsencrypt-auto certonly -a webroot --webroot-path /chemin/vers/application/public -d domaine.tld

et hop, /etc/letsencrypt/live/domaine.tld/fullchain.pem est créé !

Let’s Encrypt sur une vieille distribution ?

Si Let's Encrypt ne peut être lancé sur votre machine de production car elle dispose de versions trop anciennes des fichiers, rien n'est perdu ! Il est en effet possible de fournir au script un webroot qui serait par exemple partagé via SSH ! Par exemple :

apt install sshfs
mkdir /mnt/webroot-distant
sshfs user@machine:/path/to/webroot /mnt/webroot-distant
./letsencrypt-auto certonly -a webroot --webroot-path /mnt/webroot-distant -d mondomaine.tld

Conclusion

Très efficace et rapide, comment ne pas tomber sous le charme de Letsencrypt ? Il reste à valider : la procédure de renouvellement et la pérennité dans le temps de la structure. Pour y aider, on peut toujours faire un petit don sur la page d'accueil de Let’s Encrypt !

Friday, December 18 2015

Asterisk : automatiser un redémarrage hebdomadaire

Pour forcer un redémarrage hebdomadaire d'Asterisk, vous pouvez utiliser la commande suivante :

/usr/sbin/asterisk -r -x "core restart gracefully"

ou encore

/usr/sbin/asterisk -r -x "core restart now"

si vous ne voulez pas attendre la fin des appels en cours (cela provoquera une coupure des appels en cours !)

Pour que le redémarrage s'effectue une fois par semaine, à 2h52 du matin, voici la ligne que vous pourrez introduire dans /etc/crontab :

25 2    * * 7   root    /usr/sbin/asterisk -r -x "core restart gracefully"

Xivo/Asterisk, message audio personnalisé pour la messagerie

Si, comme moi, vous avez longuement cherché le moyen de modifier le message d'absence dans l'interface de Xivo, ne cherchez plus ! Il se paramètre très facilement sans passer par l'interface graphique en plaçant le fichier .wav adapté à cet emplacement :

/var/spool/asterisk/voicemail/contexte_du_client/numéro_boite_vocale/unavail.wav

Il suffit de le savoir !

Apache 2 : SetEnvIf et variables d'environnement, e.g. n'autoriser que certaines IP ou UserAgent à se connecter

Le serveur web Apache est extrêmement modulable quand il s'agit de filtrer des requêtes. Si tout le monde connaît les habituelles commandes Require all denied, Require all granted, Require Host example.org, nous allons voir ici comment utiliser une variable interne d'environnement et l'utiliser comme contrôle d'accès à un hôte virtuel.

Imaginons par exemple le cas suivant : nous souhaitons n'autoriser que certaines IP à se connecter, sauf pour les navigateurs dotés d'un User-Agent très spécifique.

Avant toute chose, il est nécessaire d'activer le module SetEnvIf (https://httpd.apache.org/docs/2.4/mod/mod_setenvif.html) qui permet de paramétrer une variable d'environnement d'Apache. Sous Debian (ou dérivé), cela se fera par :

a2enmod setenvif

Commençons par placer une condition sur l'IP :

SetEnvIf Remote_Addr 1.2.3.4 variable

ou alors si le serveur se trouve derrière un proxy qui fournit l'adresse d'origine dans le champ X-Forwarded-For :

SetEnvIf X-Forwarded-For 1.2.3.4 variable

La valeur fixe 1.2.3.4 peut-être remplacée par toute expression régulière de son choix.

Puis filtrons sur le User-Agent :

SetEnvIf User-Agent ^MaValeurPerso variable

Et finalement, expliquons à Apache qu'il faut interdire l'accès si aucune des conditions n'a été atteinte :

Require env variable

Dès lors, une fois la configuration rechargée, Apache n'autorisera l'accès qu'aux requêtes provenant de 1.2.3.4 ou émises par un navigateur au User-Agent correspondant à l'expression régulière ^MaValeurPerso. Ces éléments de configuration offrent beaucoup de richesse !

Thursday, December 3 2015

Traitement en lot d'images, ajouter un texte sur toutes les photos d'un répertoire avec mogrify et convert

Avec les outils inclus dans la suite ImageMagick, il est assez facile de modifier en lot les images d'un répertoire.

Par exemple, pour redimensionner tout un lot d'images (la plus grande dimension à 800 pixels), on pourra faire :

mogrify -resize 800x800 *.jpg

Pour effectuer des rotations de 180° sur plusieurs images, on fera :

mogrify -rotate 180 *.jpg

Plus compliqué, pour ajouter un texte (par exemple le nom du photographe) sur chaque photo, on pourra faire :

for file in *.jpg; do  convert $file -pointsize 20 -draw "gravity SouthEast fill white text 1,11 'Voici mon texte ' " $file; done

Cela transforme alors l'image comme suit : overlaytext.jpg

Compresser tous les répertoires en 7z

Imaginons une dizaine de dossiers que l'on souhaite chacun compresser sous la forme d'une archive. Rien de plus simple sous Linux :

for D in *; do 7z a archive-$D.7z $D ; done

On pourra bien sûr remplacer * par la chaîne de caractères commune à tous les dossiers... ou utiliser la commande 'find . -maxdepth 1 -type d'.

Exiftool pour manipuler les données EXIF d'une photo

Les photos prises avec les appareils modernes sont le plus souvent étiquetées de nombreuses données EXIF (nom de l'appareil, type d'objectif, ouverture, coordonnées GPS de la prise...). Il est parfois souhaitable de supprimer les données EXIF. Heureusement, exiftool existe sous Linux.

Il s'installe comme tout autre paquet, par exemple sous Debian :

apt install exiftool

Pour supprimer les données EXIF d'une photo, on exécute la commande :

exiftool -all= photo.jpg

et pour traiter toutes les images d'un répertoire :

exiftool -all= *.jpg

Si on ne veut supprimer qu'une seule valeur EXIF, par exemple la valeur d'orientation de la photo, on pourra faire :

exiftool -Orientation="" photo.jpg

ou bien pour la modifier :

exiftool -Orientation=1 photo.jpg

L'outil exiftool permet de faire bien plus que cela : afficher toutes les données EXIF, en réécrire certaines, créer de nouvelles données... l'imagination est presque la seule limite. Le manuel de l'outil vous fournira le détail sur les commandes ainsi qu'un grand nombre d'exemples.

Thursday, November 19 2015

ZSH dit "GREP_OPTIONS is deprecated; please use an alias or script" sans relâche

Depuis quelques temps, ZSH sur Debian Jessie ne cessait de cracher "GREP_OPTIONS is deprecated; please use an alias or script".

Le solution vint en ajoutant cette ligne dans le fichier ~/.zshrc :

unset GREP_OPTIONS

Si GREP_OPTIONS était utilisé pour mettre certais contenus en couleur, cela pourra être avantageusement remplacé par cet alias :

alias grep="grep --color=auto"

Saturday, September 12 2015

Réparer PG::UniqueViolation: ERROR: Duplicate Key Value Violates Unique Constraint 'nom_de_votre_table_pkey'

Postgresql conserve en mémoire la valeur maximale attribuée au champ 'id' et utilise cette valeur pour générer un nouvel 'id' quand un nouvel enregistrement est pris en base. Cependant, si vous avez importé des données (par exemple depuis un fichier csv avec pgadmin3, important ainsi leurs 'id' initiaux), il se peut que la valeur maximale gardée en mémoire ne corresponde plus à la table existante. Lors d'un nouvel enregistrement, si la liste importée était plus longue que la liste initiale, ce message d'erreur risque d'apparaître :

PG::UniqueViolation: ERROR: Duplicate Key Value Violates Unique Constraint 'nom_de_votre_table_pkey'

Pour corriger l'information dans la base Postgresql, il est possible d'exécuter cette commande :

SELECT setval('nom_de_votre_table_id_seq', (SELECT MAX(id) FROM nom_de_votre_table));

SELECT MAX(id) FROM nom_de_votre_table) calcule la valeur maximale d'id existant dans les données de la table. SELECT setval('nom_de_votre_table_id_seq', value) attribue une nouvelle à la chaîne 'nom_de_votre_table_id_seq').

Sunday, September 6 2015

Poplab - Imprimer un bouchon pousseur (Push Cap) pour Kenwood Chef ou Major de remplacement

Le bouchon pousseur du robot ménager Kenwood familial ayant failli, il fallut le remplacer. Qu'à cela ne tienne, mon beau-frère démarra son logiciel de modélisation et fort rapidement cet objet émergea de l'imprimante 3D :

kenwood_pushSwitch_large.jpg

kenwood_pushSwitch_packshot.jpg

kenwood_pushSwitch_packshot2.jpg

kenwood_pushSwitch_slicer.jpg

Les fichiers de modèle 3D sont disponibles :

Ces 2 fichiers sont distribués sous licence Creative Commons - Attribution - Share Alike (Push Cap for Kenwood (Chef or Major) food processor by poplab is licensed under the Creative Commons - Attribution - Share Alike license).

Efficace et fonctionnel !

- page 5 of 14 -