Tag - linux

Entries feed

Saturday, June 3 2017

Get shutter counter for Canon cameras on Linux

It can be useful to know the shutter counter for your Canon reflex camera, for example to compare with the data available here: http://www.olegkikin.com/shutterlife/.

Wait no more, it is easy to access the shutter counter with gphoto2 on Linux.

Let's start with the installation of gphoto2 (replace apt with your favorite package manager):

apt install gphoto2

Then plug the camera to the computer with an USB cable and then:

gphoto2 --auto-detect

It should show something like this:

Model                          Port                                            
----------------------------------------------------------
Canon EOS 700D                 usb:001,007
/// 


Then

gphoto2 --get-config /main/status/shuttercounter


and this is it:

Label: Shutter Counter Type: TEXT Current: 14611 ///

Sunday, February 19 2017

Réduire l'empreinte mémoire de GitLab en contrôlant le nombre de processus Sidekiq

Par défaut, GitLab démarre 25 processus Sidekiq pour gérer les travaux de tâche de fond de GitLab. Si ce nombre est justifié sur une instance à fort traffic, il y a fort à parier qu'un bien plus petit nombre de processus suffit pour gérer une instance de GitLab de petit volume.

Le nombre de processus Sidekiq se règle aisément dans le fichier /path/to/gitlab/config/sidekiq_queues.yml par ajout de la ligne suivante :

:concurrency: 2

où l'on remplacera "2" par le nombre de processus souhaités. 2 semble suffisant pour ma petite installation GitLab personnelle et ses quelques utilisateurs et dizaines de projets.

Voilà de quoi optimiser l'empreinte mémoire et processeur de GitLab !

Adjust number of Sidekiq processes for GitLab

By default, GitLab starts 25 processes of Sidekiq. If this certainly makes sense on systems with high load, this could be overkill for simple instances of GitLab with only a handful of users and active projects. To reduce memory usage, it is possible to reduce the number of concurrent processes for Sidekiq by adding the following line to the /path/to/gitlab/config/sidekiq_queues.yml file:

:concurrency: 2

Install NodeJS v7.x on Debian Jessie

It is rather easy to deploy NodeJS v7.0 on Debian Jessie. First, it is necessary to add the deb repository for nodejs in /etc/apt/sources.list.d/nodesource.list:

deb https://deb.nodesource.com/node_7.x jessie main
deb-src https://deb.nodesource.com/node_7.x jessie main

Then, let's add a package preference in /etc/apt/preferences.d/node:

Package: nodejs
Pin: release o=Node Source
Pin-Priority: 1200

or

Package: *
Pin: release o=Node Source
Pin-Priority: 1200

I am rather reluctant to use the second option (with the wildcard) as it would imply that the nodesource.com deb repository could replace any package. Without the wildcard, there is a risk to see some dependences not deployed as expected... at the time of writing, it seems that limiting the priority to "nodejs" is sufficient ti have version 7.5.0 installed.

Enjoy!

Wednesday, February 15 2017

Installer john (theripper) avec support de multiples coeurs sous Debian Stretch

Par défaut sous Debian Stretch, john (theripper), ami de l'adminsys testeur de la solidité des mots de passe, fonctionne en utilisant un seul coeur/processeur.

Il est nécessaire de recompiler john pour faire usage de multiples processeurs. Pas de panique, cela se fait très aisément.

Il faut d'abord install gcc et make pour permettre la compilation :

apt install gcc make

Ensuite, on télécharge la dernière version de john sur le site d'Openwall :

wget http://www.openwall.com/john/j/john-1.8.0.tar.xz

On décompresse l'archive :

tar xvf john-1.8.0.tar.xz

(si tar ne reconnaît pas tar.xz, c'est qu'il faut installer le paquet xz-utils)

On rentre dans le dossier source de john

cd john-1.8.0/src/

et on modifie le fichier Makefile pour décommenter les lignes OMPFLAGS. Ainsi :

#OMPFLAGS = -fopenmp
#OMPFLAGS = -fopenmp -msse2

devient

OMPFLAGS = -fopenmp
OMPFLAGS = -fopenmp -msse2

On lance alors la compilation par la commande

make linux-x86-64-avx

(attention, la cible peut être différente selon votre processeur et votre système... make vous proposera tous les choix possible si vous l'appelez sans paramètre)

Une fois la compilation terminée, vous pouvez lancer john :

cd ../run/
./john --test

et modifier lors de l'exécution le nombre de coeurs à utiliser si vous le souhaitez :

OMP_NUM_THREADS=1 ./john --test

Sunday, October 30 2016

Rotated backups for RethinkDB

Very simple bash script to rotate the backups (dumps) of RethinkDB:

#!/bin/bash
# DAILY BACKUPS
# Delete daily backups DAYS_TO_KEEP days old or more
# Config
BACKUP_DIR=/var/backups/rethinkdb/
DAYS_TO_KEEP=7
# Actions
find $BACKUP_DIR -maxdepth 1 -mtime +$DAYS_TO_KEEP -name "rethinkdb_dump_*" -exec rm -rf '{}' ';'
cd $BACKUP_DIR
rethinkdb dump

This assumes rethinkdb python utilities have been installed with:

pip install rethinkdb

Sunday, October 23 2016

dd to split file

dd is one these magical GNU tools for which you can always find new usage! I recently discovered that dd could be used to split files:

dd if=~/input_file bs=1M skip=50 count=1000 iflag=skip_bytes,count_bytes of=~/output_file status=none

in details and with no surprise:

  • if for the input file
  • of for the output file
  • bs for the block size
  • skip to indicate the starting point in the input file
  • count to indicate the length of the file to copy
  • status=none is optional, it is used to make dd quiet
  • iflag is important as it gives important parameters to dd in this case:
    • skip_bytes forces dd to understand the skip parameter in bytes (and not blocks)
    • count_bytes forces dd to understand the count parameter in bytes (and not blocks)

Always useful!

Saturday, October 22 2016

Init script for Rails app served by Unicorn with RVM

Here is an init script for a Rails app served by Unicorn with RVM.

#!/bin/bash
### BEGIN INIT INFO
# Provides:          APP_NAME, with Unicorn serving
# Required-Start:    $all
# Required-Stop:     $network $local_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start APP_NAME unicorn at boot
# Description:       Enable APP_NAME at boot time.
### END INIT INFO

set -u
set -e

# Change these to match your app:
APP_NAME="APP_NAME"
APP_ROOT="/path/to/app"
PID="/path/to/app/tmp/pids/unicorn.pid"
ENV="production"
RVM="2.3.0@gemset"
USER="user"

UNICORN_OPTS="-D -E $ENV -c $APP_ROOT/config/unicorn.rb"

SET_PATH="cd $APP_ROOT; rvm use $RVM > /dev/null;"
CMD="$SET_PATH unicorn $UNICORN_OPTS"

old_pid="$PID.oldbin"

cd $APP_ROOT || exit 1

sig () {
	test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
	test -s $old_pid && kill -$1 `cat $old_pid`
}

start () {
        echo "Starting $APP_NAME unicorn..."
        sig 0 && echo -e >&2 "\e[31mAlready running" && exit 0
        su - $USER -c "$CMD" > /dev/null
        echo -e "$APP_NAME has \e[32mstarted\e[0m, PID is `cat $PID`"
}

stop () {
        echo "Stopping $APP_NAME unicorn (signal QUIT)..."
        sig QUIT && echo -e "$APP_NAME has \e[32mstopped" && exit 0
        echo >&2 "Not running"
}

case ${1-help} in
start)
	start
	;;
stop)
	stop
	;;
force-stop)
	echo "Force stopping $APP_NAME unicorn (signal TERM)..."
	sig TERM && echo "$APP_NAME has stopped" &&exit 0
	echo -e >&2 "\e[31mNot running"
	;;
reload)
	echo "Reloading $APP_NAME unicorn (signal USR2)..."
	sig USR2 && echo -e "$APP_NAME has \e[32mreloaded" && exit 0
	echo -e >&2 "\e[31mCouldn't reload\e[0m, starting instead"
	start
	;;
status)
	sig 0 && echo -e "$APP_NAME \e[32mrunning\e[0m with PID `cat $PID`" && exit 0
	echo -e "$APP_NAME is \e[31mnot running!"
	;;
*)
 	echo >&2 "Usage: $0 <start|stop|reload|status|force-stop>"
 	exit 0
 	;;
esac

Beware that the reload calls USR2. In the documentation of Unicorn, it is said that USR2 should be followed by QUIT. Otherwise the good signal to reload is HUP.

However, I use the following unicorn.rb config file inspired from Github's and you will see that it specifies that the new instance of Unicorn shall send a QUIT signal to the old one!

rails_root = "/path/to/app"
rails_env = ENV['RAILS_ENV'] || 'production'

# 4 workers, may be changed to 1 for the tests
worker_processes (rails_env == 'production' ? 4 : 1) 

# Load rails+app into the master before forking workers
# for super-fast worker spawn times
preload_app true

# Restart any workers that haven't responded in 30 seconds
timeout 30

before_fork do |server, worker|
  ##
  # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
  # immediately start loading up a new version of itself (loaded with a new
  # version of our app). When this new Unicorn is completely loaded
  # it will begin spawning workers. The first worker spawned will check to
  # see if an .oldbin pidfile exists. If so, this means we've just booted up
  # a new Unicorn and need to tell the old one that it can now die. To do so
  # we send it a QUIT.
  # Using this method we get 0 downtime deploys.

  old_pid = rails_root + '/tmp/pids/unicorn.pid.oldbin'
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
  # Unicorn master loads the app then forks off workers - because of the way
  # Unix forking works, we need to make sure we aren't using any of the parent's
  # sockets, e.g. db connection
  ActiveRecord::Base.establish_connection
end

Wednesday, October 19 2016

Grafana & InfluxDB en HTTPS avec Let's Encrypt

Grafana et InfluxDB forment une jolie paire quand il s'agit de stocker et d'analyser des flux de données. J'ai donc voulu en sécuriser l'accès pour mes utilisateurs en permettant une connexion en HTTPS grâce aux certificats de Let's Encrypt.

Méthodologie

Pour Grafana comme InfluxDB, je n'ai pas réussi à faire accepter un dossier .well-known aux serveurs web empaquetés avec chacun des outils. J'ai donc fait intervenir le reverse proxy placé devant Grafana et InfluxDB.

Sommairement:

  1. toute requête de la forme http://url.de.grafana/.well-known/... ou http://url.de.influxdb/.well-known/... est renvoyée vers un hôte virtuel d'un serveur Apache
  2. toute autre requête est envoyée comme il se doit au serveur Grafana ou au serveur InfluxDB

Ainsi, quand Let's Encrypt effectue le test de possession du domaine, il trouve aux adresses http://url.de.grafana/.well-known/... ou http://url.de.influxdb/.well-known/... le fichier qu'il recherche et accepte alors la génération des certificats.

En pratique

La pratique dépend du reverse proxy. Dans mon cas, le reverse proxy est Pound. Dès lors on ajoute à la configuration de Pound le paragraphe suivant (avant les autres pour capturer la requête avant envoi vers un autre service) :

        Service
                HeadRequire "Host: .*(url.de.influxdb).*"
                URL "/.well-known/acme-challenge/.*"
                BackEnd
                        Address 1.2.3.4
                        Port    8000
                End
        End

avec 1.2.3.4 un serveur (par exemple Apache) qui répond sur le port 8000 en retournant le contenu de /var/www/pour-letsencrypt.

Il suffit alors d'appeler

certbot certonly --renew-by-default -a webroot --webroot-path /var/www/pour-letsencrypt/ -d url.de.influxdb

pour générer le certificat valide que l'on pourra ensuite utiliser pour protéger l'accès à InfluxDB ou Grafana !

Monday, October 17 2016

Gitlab, empty repository mystery, when a workhorse comes to help a unicorn!

Gitlab is a wonderful piece of open source software, incredibly pleasant to use to manage development projects. My own instance, installed from source, is updated version after version. Today, I was faced with a weird issue:

  1. all downloads of archive (whatever the format .tar.gz, .zip, .tar.bz2) of the files of the projets were failing, more precisely only empty (0 byte) archives were returned
  2. when cloning with git clone http://urlofgitlab/group/repo.git, I consistently obtained warning: You appear to have cloned an empty repository.
  3. interestingly, cloning the same repository with git clone git@urlofgitlab:group/repo.git worked seamlessly.

After some research, it appeared my Gitlab instance was not using Gitlab-workhorse at all. The magic unicorn was the only one serving the content of the instance without any help from the local workhorse :-)

Some context

It appears that Gitlab-workhorse was developed and added to Gitlab 8 to circumvent some limitations of Unicorn when serving large files (some history here)... and since then big files would not be served anymore by Unicorn.

As a consequence, if the requests are not treated by Gitlab-workhorse, then the git clone over HTTP and download of large archive files would not complete.

How did it happen?

My instance is regularly updated from version to version and pre-dates Gitlab 8. Before Gitlab 8, it was normal to have my reverse proxy/load balancer (Pound) point directly to the Unicorn server. When upgrading to Gitlab 8, I should have changed the setting of the reverse proxy/load balancer to point to Gitlab-workhorse instead of Unicorn. And then it was necessary to properly set Gitlab-workhorse to rely on Unicorn.

How fix it?

Well, 3 steps.

Step 1: fix the link between Gitlab-workhorse and Unicorn Gitlab-workhorse expects to connect to Unicorn through a Unix socket. It is therefore necessary to make sure that Unicorn is set up accordingly in /home/git/gitlab/config/unicorn.rb, with this line active:

listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 1024

Step 2: make sure that Gitlab-workhorse is well set to connect to this socket. This can be done by tweaking the parameters in /etc/default/gitlab, with inspiration from /home/git/gitlab/lib/support/init.d/gitlab.default.example.

Step 3: make sure that the reverse proxy correctly points to workhorse. As a default, Gitlab-workhorse uses a socket. In my case, I had to make it use a TCP connection/port so that the reverse proxy could use it. Again, based on the settings found in /home/git/gitlab/lib/support/init.d/gitlab.default.example, I tweaked the /etc/default/gitlab file to read:

gitlab_workhorse_options="-listenUmask 0 -listenNetwork tcp -listenAddr a.b.c.d:8181 -authBackend http://127.0.0.1:8080 -authSocket $socket_path/gitlab.socket -documentRoot $app_root/public"

Last, with the reverse proxy pointing to a.b.c.d:8181 everything worked very fine.

I am relieved to know that my Unicorn is now so efficiently supported by the Workhorse!

Sunday, October 2 2016

Tapoter pour cliquer sur Debian Stretch ou Buster

Tapoter pour cliquer, "tap-to-click" en anglais, une fonctionnalité bien utile non activée par défaut sur Debian Stretch ou Buster.

Le comportement s'active facilement :

Sur Debian Stretch

Pour l'activer, il suffit de modifier le fichier '/usr/share/X11/xorg.conf.d/60-libinput.conf' afin d'ajouter l'option suivante à la section "InputClass" :

      Option "Tapping" "on"

Sur Debian Buster

Pour l'activer, il suffit de modifier le fichier '/usr/share/X11/xorg.conf.d/40-libinput.conf' afin d'ajouter l'option suivante à la section "InputClass" qui correspond au "touchpad" :

      Option "Tapping" "on"

Asus UX360C et Linux Debian Stretch

Bonjour,

Voilà un petit article bloc-note pour commenter le support du PC portable Asus Zenbook UX360C sous Linux Debian Stretch: la situation est assez simple, tout fonctionne parfaitement avec cet UX360.

L'installation se fait sans surprise avec l'installateur Debian netboot placé sur une clé USB.

  • L'écran tactile fonctionne
  • La carte son est reconnue sans problème et les boutons physique de volume sur le côté sont reconnus par défaut
  • Carte Wifi parfaitement fonctionnelle (en installation le firmware iwlwifi)
  • ... tout fonctionne bien

Voilà ce que retourne lspci :

00:00.0 Host bridge: Intel Corporation Sky Lake Host Bridge/DRAM Registers (rev 08)
00:02.0 VGA compatible controller: Intel Corporation Sky Lake Integrated Graphics (rev 07)
00:04.0 Signal processing controller: Intel Corporation Skylake Processor Thermal Subsystem (rev 08)
00:13.0 Non-VGA unclassified device: Intel Corporation Device 9d35 (rev 21)
00:14.0 USB controller: Intel Corporation Sunrise Point-LP USB 3.0 xHCI Controller (rev 21)
00:14.2 Signal processing controller: Intel Corporation Sunrise Point-LP Thermal subsystem (rev 21)
00:15.0 Signal processing controller: Intel Corporation Sunrise Point-LP Serial IO I2C Controller (rev 21)
00:15.1 Signal processing controller: Intel Corporation Sunrise Point-LP Serial IO I2C Controller (rev 21)
00:16.0 Communication controller: Intel Corporation Sunrise Point-LP CSME HECI (rev 21)
00:17.0 SATA controller: Intel Corporation Sunrise Point-LP SATA Controller [AHCI mode] (rev 21)
00:1c.0 PCI bridge: Intel Corporation Device 9d13 (rev f1)
00:1f.0 ISA bridge: Intel Corporation Device 9d46 (rev 21)
00:1f.2 Memory controller: Intel Corporation Sunrise Point-LP PMC (rev 21)
00:1f.3 Audio device: Intel Corporation Sunrise Point-LP HD Audio (rev 21)
00:1f.4 SMBus: Intel Corporation Sunrise Point-LP SMBus (rev 21)
01:00.0 Network controller: Intel Corporation Wireless 8260 (rev 3a)

et lsusb :

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 8087:0a2b Intel Corp. 
Bus 001 Device 003: ID 0bda:57f4 Realtek Semiconductor Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Une super machine avec un écran brillant toutefois (tactile oblige).

Thursday, September 22 2016

Phpmyadmin et open_basedir sur Debian Sid

Stupéfaction hier quand, sur Debian Sid, phpmyadmin cessa de fonctionner... Sans doute une mise à jour récente avait-elle cassé le subtile équilibre propice à phpmyadmin.

L'examen de logs (dans /var/logs/apache2/error.log) montre que :

[Tue Sep 20 07:17:39.550343 2016] [:error] [pid 4509] [client ::1:57788]
PHP Fatal error:  require_once(): Failed opening required
'/usr/share/php/php-gettext/gettext.inc' (include_path='.') in
/usr/share/phpmyadmin/libraries/common.inc.php on line 77
[Tue Sep 20 07:17:40.162663 2016] [:error] [pid 4505] [client ::1:57790]
PHP Warning:  require_once(): open_basedir restriction in effect.
File(/usr/share/php/php-php-gettext/gettext.inc) is not within the
allowed path(s):
(/usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/)

La seconde ligne (Warning PHP) est assez explicite sur l'erreur. Il semble donc nécessaire d'ajouter le chemin vers /usr/share/php/php-gettext/ dans l'instruction open_basedir.

Pour ce faire, ouvrir le fichier de configuration de l'hôte phpmyadmin en écriture :

nano /etc/apache2/conf-available/phpmyadmin.conf

et repérer la ligne "open_basedir" qui doit ressembler à

php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/

Il faut alors la transformer par un ajout judicieux en :

php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/:/usr/share/php/php-gettext/

Et, après un redémarrage d'Apache, tout fonctionne à nouveau.

Friday, August 26 2016

Updatengine : désinstaller un logiciel avant d'en installer un nouveau

Nous avons déjà parlé d'Updatengine dans ces pages : c'est un logiciel libre de déploiement de logiciels pour Windows composé de clients sur chaque poste contrôlés par un serveur développé sous Python/Django. Je l'utilise avec bonheur en production sur un parc d'une trentaine de machines avec grande satisfaction.

Récemment, j'ai cherché à désinstaller un logiciel avant d'en installer la mise à jour.

Possibilité 1 : le logiciel est déployé avec Windows Installer

Si le logiciel a été déployé avec Windows Installer, alors l'utilitaire "wmic" permet de le désinstaller. Le script de désinstallation pourra alors ressembler à :

wmic product where "name like 'Logiciel%'" call uninstall
logiciel-nouvelle-version.exe /s
section_end
download_no_restart

Par exemple, pour désinstaller les anciennes versions de Java avant d'en installer une nouvelle, on pourra utiliser :

wmic product where "name like 'Java%'" call uninstall
jre-8u101-windows-x64.exe /s
section_end
download_no_restart

Possibilité 2 : s'il n'est pas visible/désinstallable avec WMIC

On peut alors simplement exécuter le désinstallateur (à condition d'en connaître le chemin) :

IF EXIST "C:\Program Files\Logiciel\uninstall.exe" ("C:\Program Files\Logiciel\uninstall.exe" /s Logiciel-nouvelle-version-install.exe /s) ELSE (Logiciel-nouvelle-version-install.exe /s) )

Par exemple pour SumatraPDF, lecteur PDF libre pour Windows, cela pourra devenir :

IF EXIST "C:\Program Files\SumatraPDF\uninstall.exe" ("C:\Program Files\SumatraPDF\uninstall.exe" /s SumatraPDF-3.1.2-install.exe /s) ELSE (IF EXIST "C:\Program Files (x86)\SumatraPDF\uninstall.exe" ("C:\Program Files (x86)\SumatraPDF\uninstall.exe" /s SumatraPDF-3.1.2-install.exe /s) ELSE (SumatraPDF-3.1.2-install.exe /s) )

Bon entretien de vos machines !

Saturday, June 4 2016

vnstat sur Raspberry Pi pour surveiller le trafic réseau

Nous allons voir ici comment installer vnstat pour surveiller le trafic réseau et afficher une petite page de synthèse sur l'utilisation du trafic. Cela peut-être utile par exemple pour mesurer le trafic traversant une passerelle Raspberry Pi construite tel que raconté ici.

vnstat en ligne de commande

Tout commence avec (e.g. sous Raspbian Jessie) :

apt install vnstat vnstati

Demandons alors à vnstat de créer une base de données du trafic pour l'interface que l'on veut surveiller :

vnstat -i eth0 -u

Désormais, un appel à la commande vnstat affiche en ligne de commande une synthèse sur le trafic réseau :

vnstat -u #Mise à jour des informations
vnstat #Affichage de la synthèse
Database updated: Sat Jun  4 13:02:00 2016

   eth0 since 29/05/16

          rx:  136.26 MiB      tx:  411.92 MiB      total:  548.18 MiB

   monthly
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
       May '16    134.72 MiB |  410.23 MiB |  544.94 MiB |    1.67 kbit/s
       Jun '16      1.55 MiB |    1.69 MiB |    3.24 MiB |    0.09 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated         8 MiB |       8 MiB |      16 MiB |

   daily
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
      29/05/16    134.72 MiB |  410.23 MiB |  544.94 MiB |   51.67 kbit/s
         today      1.55 MiB |    1.69 MiB |    3.24 MiB |    0.57 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated         1 MiB |       1 MiB |       2 MiB |

vnstat sur une page web

vnstati est une commande parente de vnstat qui génère une image de synthèse plutôt qu'un tableau. Pratique pour nous, êtres humains, qui aimons la bigarrure ! Alors demandons à vnstati de nous géréner quelques images à l'aide de ce script que l'on pourra placer dans cron :

#!/bin/bash
vnstat -u -i eth0
vnstati -s -i eth0 -o /var/www/html/summary.png
vnstati -h -i eth0 -o /var/www/html/hourly.png
vnstati -d -i eth0 -o /var/www/html/daily.png
vnstati -t -i eth0 -o /var/www/html/top10.png
vnstati -m -i eth0 -o /var/www/html/monthly.png

Et pour afficher ces images, nous allons utiliser une petite page web et nginx :

apt install nginx

puis remplaçons la page par défaut /var/www/html/index.nginx-debian.html par index.html contenant :

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Statistics</title>
</head>

<body>
<h2 align="center">Network Statistics</h2>
<hr align="center">
<p align="center"><img src="summary.png" alt="Summary"/><br/>
  Summary
</p>
<hr align="center">
<p align="center"><img src="hourly.png" alt="Traffic stats on a hourly basis for the last 24 hours "/><br/>
  Traffic stats on a hourly basis for the last 24 hours
</p>
<hr align="center">
<p align="center"><img src="daily.png" alt="Traffic stats on a daily basis for the last 30 days"/><br/>
  Traffic stats on a daily basis for the last 30 days
</p>
<hr align="center">
<p align="center"><img src="monthly.png" alt="Traffic stats on a monthly basis for the last 12 months"/><br/>
  Traffic stats on a monthly basis for the last 12 months
</p>
<hr align="center">
<p align="center"></p>
<p align="center"><img src="top10.png" alt="All time top 10 traffic days"/><br/>
  All time top 10 traffic days</p>
<hr align="center">
</body>
</html>

et si l'on pointe un navigateur vers l'adresse IP du Raspberry Pi, on voit alors s'afficher :

Screenshot_2016-06-04_15-28-00.png

Un Raspberry Pi en passerelle IPv4, pour surveiller des flux réseaux par exemple

Nous allons voir dans ce billet comment paramétrer un Rasperry Pi pour qu'il joue le rôle de passerelle IPv4. Attention, avec son interface ethernet 100 Mbps et sa puissance limitée, il est évident que le montage présenté ici peut convenir dans un environnement domestique mais sans doute pas au-delà.

Matériel

Prenons donc un Raspberry Bi (muni de Raspbian Jessie) et munissons-le d'un port ethernet USB. Le Pi dispose alors de 2 interfaces ethernet eth0 et eth1 :

pi-bi-eth.jpg

Il n'est pas obligatoire d'avoir deux interfaces réseaux mais cela est plus commode et permet un suivi plus fin du trafic (avec une seule interface, tout ce qui rentre ressort par la même interface et il est dès lors plus délicat de comparer flux entrants et flux sortants puisqu'ils s'annulent au niveau de l'interface unique.

Paramétrage du réseau

Attribuons des paramétrages réseau fixes à eth0 et eth1 dans /etc/dhcpcd.conf comme expliqué ici :

interface eth0
static ip_address=192.168.1.235/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

interface eth1
static ip_address=192.168.1.234/24

L'interface eth0 est paramétrée avec une IP fixe et utilise comme passerelle de sortie le routeur local (192.168.1.1 dans cet exemple). L'interface eth1 se voit attribuer seulement une adresse IP fixe mais pas de passerelle de sortie. Ainsi, la seule route vers l'extérieur passe au travers d'eth0, ce que nous confirme la commande ip route :

default via 192.168.1.1 dev eth0  metric 202 #La sortie par défaut via eth0, pas de sortie via eth1 !
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.235  metric 202 
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.234  metric 203

Il faut maintenant permettre au Raspberry Pi de faire transiter les paquets d'une interface à une autre. Pour ce faire, nous allons activer cette ligne dans /etc/sysctl.conf :

net.ipv4.ip_forward=1

et on ajoutera également ces 3 lignes pour s'assurer que le Raspberry Pi n'enseigne pas aux périphériques autour de lui à le "by-passer" (ce qu'un routeur fait par défaut pour garantir la performance et éviter les noeuds inutiles) :

net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth1.send_redirects = 0

Pour activer cette configuration, on peut redémarrer ou exécuter :

sysctl -p

Désormais, le Raspberry Pi est capable de faire passer les communications d'eth1 à eth0 mais la route retour ne passe pas nécessairement par le Pi (le routeur n'a aucune raison, lui, de faire transiter le trafic retour vers le Pi s'il peut accéder directement au périphérique final ; évidemment ce cas ne se présente pas si le schéma de câblage fait du Pi le seul lien physique vers la porte de sortie).

Pour forcer la retour par le Pi, on exécutera cette commande iptables :

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Désormais, tout ce qui sort par eth0 voit son adresse source modifiée (filtre MASQUERADE appliquée en POSTROUTING) pour correspondre à l'adresse du Pi : au retour les paquets passeront donc forcément par le Pi qui renverra ensuite vers la bonne destination.

Et sur les périphériques ?

Sur chaque périphérique, il est alors possible d'indiquer comme passerelle l'adresse IP du Pi sur eth1 soit 192.168.1.234 dans cet exemple. Chacun saura comment indiquer à son DHCP local si nécessaire de transporter cette information plutôt que celle par défaut. Dès lors, le Pi devient le point de passage obligé du trafic réseau.

Pour quoi faire ?

Par exemple, nous pouvons maintenant examiner le flux traversant, mesurer le débit avec iftop, couper l'accès à internet à certaines heures, ... On pourra par exemple installer vnstat sur le Pi pour afficher des statistiques d'usage de la bande passante. Les idées ne manquent pas :-)

Passer de letsencrypt-auto à certbot, pas de problème

Let's Encrypt gagne en maturité et voici deux nouvelles importantes :

  • la période bêta est terminée (et avec elle certaines limites d'usage disparaissent)
  • le client letsencrypt-auto devient certbot et bénéficie d'une nouvelle maison
  • et la procédure de renouvellement est désormais beaucoup mieux gérée par le client

Place à certbot!

Si, comme moi, vous utilisiez letsencrypt-auto synchronisé depuis le dépôt Git du client, pas de panique, la transition vers certbot s'effectue sans problème.

D'abord, c'est l'occasion d'utiliser les dépôts Debian qui contiennent désormais certbot. Sur Jessie, pour installer certbot, on utilisera la commande suivante :

apt-get install certbot -t jessie-backports

Et ensuite ? Et bien il n'y a qu'à remplacer les appels vers letsencrypt-auto par des appels vers certbot ! Facile ! A noter que le paquet Debian vient avec un renouvellement automatique paramétré dans /etc/cron.d/certbot, il sera facile de commenter la ligne active si cela ne correspond pas à votre besoin.

Et les renouvellements ?

Comme je l'annonçais en introduction, les renouvellements sont maintenant bien mieux gérés par le client certbot.

La commande

certbot renew

réalisera le renouvellement de tous les certificats qui le nécessitent sur la base des paramétrages contenus dans /etc/letsencrypt/renewal/mon.domaine.tld.conf. On pourra tester le renouvellement sans l'exécuter à l'aide de l'option supplémentaire --dry-run. Enfin, il est possible de paramétrer une action à effectuer avant ou après chaque renouvellement à l'aide des options --pre-hook, --post-hook, --renew-hook. Au moment où j'écris ces lignes, il ne semble pas possible de paramétrer ces options dans les fichiers de renouvellement de configuration mais cela viendra peut-être !

Bons renouvellements !

Wednesday, June 1 2016

Git 2.8+ sur Debian Jessie pour Gitlab 8.5

Si vous hébergez Gitlab sur Debian Jessie, alors la mise à jour de la version 8.4 à la version 8.5 vous aura sans doute demandé une version de Git plus récente que Git 2.1.4 actuellement disponible sur Jessie. Pas de panique : il est possible presque sans effort d'installer une version plus récente de Git depuis les dépôts testing/stretch.

Dans /etc/apt/sources.list, on ajoute ces lignes :

deb http://debian.mirrors.ovh.net/debian/ stretch main
deb-src http://debian.mirrors.ovh.net/debian/ stretch main

deb http://security.debian.org/ stretch/updates main
deb-src http://security.debian.org/ stretch/updates main

Il faut ensuite indiquer à la distribution l'ordre de priorité d'installation en plaçant dans un fichier /etc/apt/preferences.d/mes_priorites (le nom du fichier est tout à fait personnalisable) le contenu suivant :

ackage: *
Pin: release l=Debian-Security
Pin-Priority: 1000

Package: *
Pin: release a=stable
Pin-Priority: 999

Package: *
Pin: release a=testing
Pin-Priority: 50

Package: *
Pin: release a=unstable
Pin-Priority: 50

A ce stade, la commande apt update doit rapatrier les informations de la version testing/stretch mais ne doit pas automatiquement proposer une mise à jour car la priorité donnée à testing (& unstable) est bien moindre que celle donnée à la branche stable.

Pour forcer alors l'installation de la version de Git disponible dans testing/stretch, il faut exécuter :

apt install git/stretch git-man/stretch

Sunday, May 29 2016

IP statique sur Raspbian Jessie : DHCPCD fait la loi !

Sur Raspbian Jessie, le système n'obéit pas au classique /etc/network/interfaces quand il s'agit de paramétrer le réseau ! Inutile donc de vous escrimer (comme moi) à modifier les paramétrages de ce fichier pour basculer vers une adresse statique au lieu du DHCP par défaut !

En effet, sur Raspbian Jessie, le réseau est paramétré par le service DHCPCD. C'est donc à son niveau qu'il faut agir.

Ainsi, pour attribuer une IP fixe au Pi, ouvrons le fichier /etc/dhcpcd.conf et ajoutons ces lignes à la fin du fichier :

interface eth0
static ip_address=192.168.1.234/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

Saturday, May 14 2016

RIP demo.ovh.eu, alternatives open source

Pour partager des fichiers temporairement avec des amis/collaborateurs/proches, j'utilisais fréquemment l'outil demo.ovh.eu. Cet outil avait pour avantage d'être "share & forget" ce qui est idéal pour un document partagé que l'on ne veut pas conserver soi-même.

Malheureusement OVH a décidé d'éteindre demo.ovh.eu et d'inciter les gens à utiliser la plateforme Hubic (qui est très bien mais il est pénible de se connecter et de partager une photo que l'on ne veut pas conserver et qui peut être supprimée quelques jours après le partage).

J'ai donc cherché un outil équivalent Open Source et suis tombé sur Uguu qui répondait à mon cahier des charges mais qui était compliqué à déployer car il contenait tous ses paramètres "en dur" dans le code.

J'ai donc 'forké' Uguu et livre la communauté une version d'Uguu plus facile à déployer et paramétrer : https://github.com/pierre-alain-b/Uguu/

Screenshot_2016-05-14_12-16-35.png

Et d'ailleurs, le mainteneur de la version initiale a accepté le 'Pull request' et a fusionné toutes mes modifications dans l'arbre principal de développement, il est peut-être donc même préférable de se rendre ici : https://github.com/nokonoko/Uguu.

En espérant qu'il puisse rendre service à d'autres !

Et si Uguu ne vous convient pas, il y a aussi :

Merci à François B. pour ces suggestions !

- page 2 of 8 -