structure & meta
This commit is contained in:
parent
da6d838193
commit
b25ce65735
284 changed files with 461 additions and 1000 deletions
196
posts/2014/2014-01-02-horde-debian.md
Executable file
196
posts/2014/2014-01-02-horde-debian.md
Executable file
|
|
@ -0,0 +1,196 @@
|
|||
<!-- title: Installation de Horde Groupware -->
|
||||
<!-- categories: Hébergement Mobilité Debian -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Je remets en place progressivement les outils nécessaires sur mon serveur
|
||||
Debian. Je me suis posé à nouveau la problématique de la synchronisation des
|
||||
contacts et du calendrier entre mes appareils,<!-- more --> c'est à dire mon ordinateur
|
||||
portable sous ArchLinux avec le logiciel de courrier *Thunderbird* et son
|
||||
module de gestion de calendrier *Lightning*, mon antique téléphone BlackBerry
|
||||
Bold 9780. Un accès Web à mon calendrier et mes contacts depuis n'importe
|
||||
quelle machine quand je suis en déplacement serait un plus.
|
||||
|
||||
Le téléphone supporte la synchronisation Google de facto et SyncML en
|
||||
installant le client [Funambol](http://www.funambol.com). Je n'ai trouvé aucune
|
||||
possibilité gratuite pour faire de la synchronisation CardDAV, CalDAV ou
|
||||
ActiveSync. SyncML reste ma meilleure option. On peut installer le client
|
||||
Funambol du BlackBerry Store mais il fait plus que nécessaire car il
|
||||
s'interface avec le serveur Funambol ou bien on peut installer une version plus
|
||||
ancienne qui suffit pour la synchro des contacts, du calendrier et des tâches
|
||||
depuis [ce lien](http://www.memotoo.com/how-to-sync-your-blackberry-phone.php).
|
||||
Côté ordinateur, Lightning supporte nativement le protocole CalDav et le carnet
|
||||
d'adresse peut être synchronisé avec CardDAV en installant le [module
|
||||
complémentaire pour Sogo](http://www.sogo.nu/english/downloads/frontends.html).
|
||||
|
||||
<img src="/images/2014/logo-horde.jpg" style="float:left; margin: 0px 20px;"/>A
|
||||
l'époque de mon Motorola Droid, j'avais déjà utilisé le client Funambol pour
|
||||
synchroniser mes données avec
|
||||
[eGroupware](http://www.egroupware.org/community_edition) et je m'étais
|
||||
intéressé à *Horde*. Ce dernier semblait plus difficile à installer,
|
||||
l'interface Web était peu conviviale et j'avais mis en place eGroupware que
|
||||
j'avais utilisé 1 an avec satisfaction. J'ai su qu'une version 5 de Horde était
|
||||
sortie dans l'année et j'ai décidé de l'évaluer. Horde supporte SyncML,
|
||||
CardDAV, CalDav et son interface graphique a été rajeunie.
|
||||
|
||||
Ma cible de déploiement est mon serveur privé virtuel avec
|
||||
l'environnement technique suivant :
|
||||
|
||||
- Distribution Debian Wheezy
|
||||
- Serveur Web NginX
|
||||
|
||||
L'installation est plus complexe que la moyenne mais avec un bon tuto on s'en
|
||||
sort. Horde est modulaire : un Framework et des applications. Moi j'ai besoin
|
||||
de Kronolith (la gestion du calendrier) et de Turba (la gestion des contacts).
|
||||
J'ai décliné l'installation par le système de paquets car généralement cela
|
||||
tire le serveur Apache alors que j'utilise NginX et j'ai opté pour PEAR,
|
||||
l'outil d'installation PHP que ne connaissais pas. De ma compréhension, c'est
|
||||
l'équivalent de CPAN pour PERL ou d'APT pour Debian. Horde publie ses
|
||||
composants pour l'infrastructure PEAR [sur ce serveur](http://pear.horde.org).
|
||||
|
||||
L'installation de PEAR sur Debian est galette.
|
||||
|
||||
apt-get install php-pear
|
||||
|
||||
Puis, on enregistre le canal Horde sur Pear et on installe les composants
|
||||
nécessaires :
|
||||
|
||||
``` shell
|
||||
mkdir -p /var/www/horde
|
||||
cd /var/www/horde
|
||||
pear channel-discover pear.horde.org
|
||||
pear install horde/horde_role
|
||||
pear run-scripts horde/horde_role
|
||||
pear install -a -B horde/horde
|
||||
pear install horde/turba
|
||||
pear install horde/kronolith
|
||||
pear install horde/mnemo
|
||||
pear install horde/Horde_SyncMl
|
||||
```
|
||||
|
||||
Dans le cas de NginX sur Debian, il faut ajuster les permissions du répertoire.
|
||||
|
||||
chown -R www-data:www-data /var/www/horde
|
||||
|
||||
Et il faut créer les fichiers de configuration de chaque application à partir
|
||||
des modèles fournis :
|
||||
|
||||
``` shell
|
||||
cd /var/www/horde/config
|
||||
for f in *.dist; do cp $f `basename $f .dist`; done
|
||||
cd /var/www/horde/kronolith/config
|
||||
for f in *.dist; do cp $f `basename $f .dist`; done
|
||||
cd /var/www/horde/turba/config
|
||||
for f in *.dist; do cp $f `basename $f .dist`; done
|
||||
cd /var/www/horde/nag/config
|
||||
for f in *.dist; do cp $f `basename $f .dist`; done
|
||||
cd /var/www/horde/mnemo/config
|
||||
for f in *.dist; do cp $f `basename $f .dist`; done
|
||||
```
|
||||
|
||||
Il reste à configurer NginX. Je force l'utilisation de HTTPS en redirigeant les
|
||||
requêtes HTTP vers la version sécurisée du site.
|
||||
|
||||
``` nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name groupware.exemple.fr;
|
||||
rewrite ^ https://$server_name$request_uri? permanent;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name groupware.exemple.fr;
|
||||
root /var/www/horde;
|
||||
index index.php;
|
||||
|
||||
ssl_certificate /etc/ssl/exemple.fr.cert;
|
||||
ssl_certificate_key /etc/ssl/exemple.fr.key;
|
||||
|
||||
access_log /var/log/nginx/horde-access.log;
|
||||
error_log /var/log/nginx/horde-error.log;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /rampage.php?$args;
|
||||
}
|
||||
|
||||
location ~ \.php {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
||||
fastcgi_param PHP_VALUE "cgi.fix_pathinfo=1";
|
||||
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Horde propose le choix entre plusieurs bases de données J'utilise déjà MySQL,
|
||||
j'ai donc créé une nouvelle base pour Horde en utilisant les outils
|
||||
en ligne de commande de MySQL.
|
||||
|
||||
mysql -u root -p
|
||||
mysql> CREATE DATABASE horde;
|
||||
mysql> GRANT ALL ON horde.* TO horde@localhost IDENTIFIED BY 'horde';
|
||||
mysql> FLUSH PRIVILEGES;
|
||||
mysql> EXIT;
|
||||
|
||||
A la première connexion Web, il n'y a pas d'authentification, on est connecté
|
||||
en tant qu'administrateur sans mot de passe.
|
||||
|
||||
#### 1ère étape : définir la base de donnée.
|
||||
|
||||
1. Aller dans le menu Administration / Configuration
|
||||
|
||||
<img src="/images/2014/horde-config.png"/>
|
||||
|
||||
2. Cliquer sur le composant Horde (horde)
|
||||
|
||||
<img src="/images/2014/horde-application.png"/>
|
||||
|
||||
3. Configurer la base de donnée dans l'onglet Database
|
||||
|
||||
<img src="/images/2014/horde-database.png"/>
|
||||
|
||||
#### 2ème étape : créer un utilisateur avec les droits d'administration.
|
||||
|
||||
1. Aller dans le menu Administration / Utilisateur
|
||||
|
||||
<img src="/images/2014/horde-user.png"/>
|
||||
|
||||
2. Créer un nouvel utilisateur
|
||||
|
||||
<img src="/images/2014/horde-adduser.png"/>
|
||||
|
||||
3. Retourner dans le menu Administration / Configuration et rajouter
|
||||
l'utilisateur nouvellement créé dans les admins de l'onglet
|
||||
Authentification.
|
||||
|
||||
<img src="/images/2014/horde-setadmin.png"/>
|
||||
|
||||
4. Il est conseillé de tester le nouvel utilisateur en se déconnectant et en se
|
||||
reconnectant. Si cela fonctionne, on peut enlever l'utilisateur
|
||||
Administrator de la liste des admins.
|
||||
|
||||
#### 3ème étape : finaliser l'installation des applications
|
||||
|
||||
Dans le menu Administration / Configuration, tous les composants installés
|
||||
apparaîssent. Les boutons *mettre à jour toutes les configurations* et *mettre
|
||||
à jour les schémas de la base* doivent être cliqués pour finaliser l'installation.
|
||||
|
||||
#### Conclusion
|
||||
|
||||
L'URL CalDAV pour s'inscrire au calendrier se trouve dans les propriétés du
|
||||
calendrier de l'application Agenda, dans l'onglet *inscription*. De manière
|
||||
similaire, l'URL CardDAV se trouve dans les propriétés du carnet d'adresses.
|
||||
Quant à l'URL SyncML, c'est un point d'entrée unique pour la synchronisation de
|
||||
toutes les applications ; dans notre exemple ce serait
|
||||
http://groupware.exemple.fr/rpc.php.
|
||||
|
||||
J'ai mis en place Horde depuis 1 semaine avec une synchronisation SyncML par
|
||||
Funambol sur mon téléphone et une synchronisation CardDAV et CalDAV depuis
|
||||
Thunderbird. J'ai lu que SyncML n'était pas très bon pour gérer les conflits de
|
||||
synchronisation mais je n'ai pas rencontré de souci. L'évaluation se passe très
|
||||
bien pour l'instant.
|
||||
82
posts/2014/2014-01-22-qmail.md
Executable file
82
posts/2014/2014-01-22-qmail.md
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
<!-- title: SMTP Relay avec qmail sur Debian Wheezy -->
|
||||
<!-- category: Debian -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
J'ai cherché une alternative plus simple qu'Exim et Postfix pour que mes
|
||||
serveurs Debian puissent envoyer des emails d'alerte.<!-- more --> C'est une fonctionnalité
|
||||
utile si on installe fail2ban ou logwatch. Je n'ai pas besoin de gérer des
|
||||
utilisateurs ou de recevoir des emails, juste d'en envoyer en utilisant le
|
||||
serveur SMTP du FAI comme relais. J'ai trouvé
|
||||
[**qmail**](http://en.wikipedia.org/wiki/Qmail) en faisant quelques recherches,
|
||||
un antique MTA dont la dernière version stable 1.0.3 date de 1998 (gasp !) mais
|
||||
qui est toujours disponible dans les dépôts Debian.
|
||||
|
||||
Avant de lancer l'installation, il faut s'assurer que le hostname du serveur
|
||||
est un FQDN, c'est à dire un nom DNS complet. Si ce n'est pas le cas, qmail
|
||||
refuse de s'installer. Si le serveur n'a pas de nom DNS, on peut mettre
|
||||
n'importe quel domaine, ça ne gêne dans la configuration que nous allons mettre
|
||||
en place. On peut modifier le hostname de manière persistente en deux étapes :
|
||||
|
||||
1. éditer le fichier /etc/hostname
|
||||
2. forcer sa mise à jour avec la commande /etc/init.d/hostname.sh
|
||||
|
||||
L'installation de qmail désinstalle Postfix ou Exim4 car un seul MTA peut
|
||||
s'approprier le port 25.
|
||||
|
||||
apt-get install qmail qmail-run
|
||||
|
||||
Il s'agit d'un service local, on ne veut surtout pas ouvrir le port 25 sur
|
||||
Internet. On peut forcer qmail à n'écouter que sur l'interface loopback en
|
||||
modifiant le script de démarrage. Ce n'est pas l'idéal mais vu la fréquence de
|
||||
mise à jour de qmail, on ne craint pas trop de voir cette modification écrasée.
|
||||
Il faut remplacer *0* par *127.0.0.1* dans le fichier
|
||||
**/etc/qmail/qmail-smtpd/run**.
|
||||
|
||||
Voici la version modifiée :
|
||||
|
||||
``` shell
|
||||
QMAILDUID=`id -u qmaild`
|
||||
NOFILESGID=`id -g qmaild`
|
||||
MAXSMTPD=`cat /var/lib/qmail/control/concurrencyincoming`
|
||||
LOCAL=`head -1 /var/lib/qmail/control/me`
|
||||
|
||||
if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" -o -z "$LOCAL" ]; then
|
||||
echo QMAILDUID, NOFILESGID, MAXSMTPD, or LOCAL is unset in
|
||||
echo /var/qmail/supervise/qmail-smtpd/run
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f /var/lib/qmail/control/rcpthosts ]; then
|
||||
echo "No /var/lib/qmail/control/rcpthosts!"
|
||||
echo "Refusing to start SMTP listener because it'll create an open relay"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec softlimit -m 7000000 \
|
||||
tcpserver -v -R -l "$LOCAL" -x /etc/qmail/tcp.smtp.cdb -c "$MAXSMTPD" \
|
||||
-u "$QMAILDUID" -g "$NOFILESGID" 127.0.0.1 smtp qmail-smtpd 2>&1
|
||||
```
|
||||
|
||||
On modifie la configuration pour envoyer des emails en utilisant le serveur
|
||||
SMTP Orange en tant que root@orange.fr si on est l'utilisateur root. On
|
||||
remplace le contenu du fichier **/etc/qmail/defaulthost** avec ceci :
|
||||
|
||||
orange.fr
|
||||
|
||||
On supprime le contenu du fichier **/etc/qmail/defaultdomain** et on configure
|
||||
le relais dans le fichier **/etc/qmail/smtproutes** :
|
||||
|
||||
smtp.orange.fr <utilisateur> <mot de passe>
|
||||
|
||||
Pour tester on relance qmail :
|
||||
|
||||
qmailctl stop
|
||||
qmailctl start
|
||||
|
||||
Et on tente l'envoi d'un email avec la commande mail :
|
||||
|
||||
mail -s "Hello" someone@somewhere.fr
|
||||
Ceci est un test
|
||||
^D
|
||||
|
||||
Le fichier de log **/var/log/qmail/current** permet de vérifier l'état de l'envoi.
|
||||
162
posts/2014/2014-04-15-redis-ha.md
Executable file
162
posts/2014/2014-04-15-redis-ha.md
Executable file
|
|
@ -0,0 +1,162 @@
|
|||
<!-- title: Haute Disponibilité avec Redis -->
|
||||
<!-- category: Cluster -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
[Redis](http://redis.io/) est une base de donnée de type clef-valeur. On la
|
||||
range dans la grande famille plutôt hétérogène des bases **NoSQL** <!-- more -->qui, pour
|
||||
rappel, signifie plutôt *Not Only SQL* que *No SQL*. Ceci dit, dans le cas de
|
||||
Redis, on est vraiment dans le *No SQL at all*. La base permet de stocker par
|
||||
clef des chaînes, des listes de chaînes, des *hashtable*. Elle permet de
|
||||
stocker des valeurs avec une date d'expiration au delà de laquelle la donnée
|
||||
disparaît. Idéal pour gérer des données cache et c'est d'ailleurs
|
||||
l'utilisation principale de Redis. On peut aussi facilement implémenter
|
||||
producteur / consommateur entre plusieurs clients d'une base Redis. L'ensemble
|
||||
des commandes supportées par Redis est parfaitement documenté
|
||||
[ici](http://redis.io/commands).
|
||||
|
||||
La base est orientée performance et évolutivité :
|
||||
|
||||
- écrite en C, facilement portable car le code n'a pas de dépendance particulière,
|
||||
- stockage des données en mémoire avec différents mécanismes optionnels pour conserver une copie sur disque,
|
||||
- réplication possible d'une base maître vers un grand nombre de bases esclaves. On peut écrire dans la base maître et seulement lire dans les bases esclaves.
|
||||
|
||||
Ce qui fait (aussi) le succès de Redis, c'est que le coeur est en C et qu'il
|
||||
existe des [clients pour la plupart des langages](http://redis.io/clients).
|
||||
Pour l'instant, j'ai utilisé Jedis pour JAVA et redis-py pour Python. Enfin,
|
||||
un client en ligne de commande permet d'interagir avec la base sans écrire de
|
||||
code.
|
||||
|
||||
La dernière version stable est Redis 2.8.8. Quant à la version 3.0 à venir,
|
||||
encore en phase de bêta, elle embarque des fonctionnalités de répartition des
|
||||
données dans des configuration de type cluster, ce qu'on appelle en langue de
|
||||
Shakespeare le **sharding**. Dans le futur, elle embarquera aussi des
|
||||
fonctionnalités de Haute Disponibilité pour basculer les données lorsqu'un
|
||||
noeud du cluster s'écroule.
|
||||
|
||||
En attendant ce futur, la version actuelle apporte une solution de cluster
|
||||
actif/passif basée sur la réplication maître / esclave surveillée par des
|
||||
sentinelles chargées de promouvoir un Redis esclave en maître en cas de
|
||||
défaillance.
|
||||
|
||||
Je me suis intéressé à monter une configuration avec seulement 2 machines sous
|
||||
Debian qui peut fonctionner si l'une des machines tombe et automatiquement
|
||||
réintégrer le cluster quand elle redevient opérationnelle, sans impact pour
|
||||
les clients Redis. Ce n'est pas si trivial et je me suis heurté à quelques
|
||||
difficultés avant d'arriver à une configuration opérationnelle.
|
||||
|
||||
Comme dans la plupart des architectures clusterisées, un quorum (nombre
|
||||
minimal de votants) est nécessaire pour élire un nouveau maître. La valeur
|
||||
minimum possible est 1, signifiant qu'une sentinelle a besoin qu'au moins 1
|
||||
autre sentinelle soit d'accord avec elle pour déclarer qu'un Redis maître est
|
||||
défaillant. Il faut au minimum 2 sentinelles opérationnelles quel que soit
|
||||
l'état du cluster donc sur chaque machine on va installer un Redis et 2
|
||||
sentinelles.
|
||||
|
||||
Au début de mes expérimentations, j'attribuais un port différent aux
|
||||
sentinelles pour les exécuter sans conflit sur la même machine mais j'avais
|
||||
des problème d'indécision des sentinelles pour élire un nouveau noeud. Je
|
||||
crois que toutes les sentinelles ne communiquaient pas. La situation s'est
|
||||
arrangée quand j'ai configuré toutes mes sentinelles pour écouter sur le port
|
||||
standard 26379. Pour que ce soit possible, j'ai attaché mes sentinelles à des
|
||||
adresses IP différentes en déclarant une sous-interface sur chaque machine.
|
||||
|
||||
+–––––––––––––––+––––––––––––––+ +–––––––––––––––+––––––––––––––+
|
||||
| Sentinelle 1 | | | Sentinelle 1 | |
|
||||
+–––––––––––––––+ | +–––––––––––––––+ |
|
||||
| REDIS | Sentinelle 2 | | REDIS | Sentinelle 2 |
|
||||
+––––––––––––––––––––––––––––––+ +––––––––––––––––––––––––––––––+
|
||||
| Eth0 | Eth0:1 | | Eth0 | Eth0:1 |
|
||||
| 192.168.0.51 | 10.25.14.1 | | 192.168.0.52 | 10.25.14.2 |
|
||||
+–––––––––––––––+––––––––––––––+ +–––––––––––––––+––––––––––––––+
|
||||
Machine A Machine B
|
||||
|
||||
|
||||
Voici la configuration réseau de la machine A (/etc/network/interfaces) :
|
||||
|
||||
iface eth0 inet static
|
||||
address 192.168.0.51
|
||||
netmask 255.255.255.0
|
||||
|
||||
iface eth0:1 inet static
|
||||
address 10.25.14.1
|
||||
netmask 255.255.255.0
|
||||
|
||||
|
||||
La configuration des serveurs Redis est identique sur chaque machine :
|
||||
|
||||
port 6379
|
||||
|
||||
loglevel warning
|
||||
logfile "/var/log/redis.log"
|
||||
|
||||
maxmemory-policy noeviction
|
||||
|
||||
appendonly yes
|
||||
appendfsync always
|
||||
|
||||
auto-aof-rewrite-percentage 100
|
||||
auto-aof-rewrite-min-size 64mb
|
||||
aof-rewrite-incremental-fsync yes
|
||||
|
||||
Ce n'est pas le sujet de l'article mais je vous conseille de jeter un oeil à
|
||||
la documentation pour les paramètres liés à l'AOF et au APPEND qui vont
|
||||
réduire les risques de perte de données en configurant des écritures sur
|
||||
disque. C'est peut-être inintéressant dans le cas d'une utilisation de Redis
|
||||
comme cache mais ça le devient dans le cas d'une utilisation plus classique
|
||||
comme base de données.
|
||||
|
||||
Quand les deux serveurs Redis sont démarrés, on peut initier le rôle initial
|
||||
d'esclave de la machine B depuis le client Redis avec la commande :
|
||||
|
||||
slaveof 192.168.0.51 6379
|
||||
|
||||
Par la suite, les sentinelles se chargent de décider quel rôle est joué en
|
||||
fonction de la disponibilité des machines.
|
||||
|
||||
Voici la configuration de la sentinelle 1 sur la machine A :
|
||||
|
||||
port 26379
|
||||
bind 192.168.0.51
|
||||
|
||||
# master configuration
|
||||
sentinel monitor master 192.168.0.51 6379 1
|
||||
sentinel down-after-milliseconds master 3000
|
||||
sentinel failover-timeout master 10000
|
||||
sentinel parallel-syncs master 4
|
||||
|
||||
|
||||
Et celle de la sentinelle 2, également sur la machine A :
|
||||
|
||||
port 26379
|
||||
bind 10.25.14.1
|
||||
|
||||
# master configuration
|
||||
sentinel monitor master 192.168.0.51 6379 1
|
||||
sentinel down-after-milliseconds master 3000
|
||||
sentinel failover-timeout master 10000
|
||||
sentinel parallel-syncs master 4
|
||||
|
||||
La configuration des sentinelles de la machine B est identique à part les
|
||||
directives **bind** pour attacher les services aux adresses 192.168.0.52 et
|
||||
10.25.14.2.
|
||||
|
||||
Avec cette configuration, on a suffisamment de sentinelles pour basculer le
|
||||
rôle d'une machine à l'autre dans cas extrème où la machine A est
|
||||
injoignable par le réseau ou bien mise hors tension.
|
||||
|
||||
Je n'ai pas détaillé le code client mais il y a une étape avant de récupérer
|
||||
une connexion valide à la base Redis : s'adresser au *pool* de sentinelles
|
||||
pour obtenir l'adresse du maître et ensuite ouvrir une connexion vers celui-
|
||||
ci. Dans le cas d'une bascule du cluster, la connexion est cassée et il faut à
|
||||
nouveau s'adresser aux sentinelles pour récupérer l'adresse du Redis maître.
|
||||
|
||||
Voici un exemple typique de code en Python :
|
||||
|
||||
``` python
|
||||
from redis.sentinel import Sentinel
|
||||
sentinel = Sentinel(
|
||||
[('192.168.0.51', 26379), ('192.168.0.52', 6379)], socket_timeout=0.1)
|
||||
print("Master %s %d" % sentinel.discover_master('master'))
|
||||
```
|
||||
|
||||
Je suis le projet Redis depuis un bout de temps avec intérêt car il offre beaucoup d'applications possibles dans des architectures distribuées multi-langages.
|
||||
40
posts/2014/2014-04-28-gnome3-attendez-moi.md
Executable file
40
posts/2014/2014-04-28-gnome3-attendez-moi.md
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
<!-- title: Gnome 3, attendez moi les jeunes ! -->
|
||||
<!-- category: GNU/Linux -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Ma dernière tentative d'utiliser Gnome en environnement professionnel date de
|
||||
[fin 2011](gnome-3-pour-un-usage-professionnel.html). Le changement avait été
|
||||
trop brutal et déclenché [mon passage à XFCE](quelle-distribution-gnome-2
|
||||
-choisir-en-2012.html)<!-- more --> où je suis resté depuis, que ce soit sous Arch à la
|
||||
maison ou au bureau sous Fedora. En 2 ans, les développeurs de Gnome ont
|
||||
sacrément amélioré leur bijou :
|
||||
|
||||
- meilleures performances, cohésion de l'interface, raffinements
|
||||
- ergonomiques et esthétiques à tous les étages, ouverture grâce aux
|
||||
- extensions pour rajouter les fonctionnalités manquantes (ou écartées).
|
||||
|
||||
Par curiosité, j'ai testé quelques jours la version 3.12 à la
|
||||
maison sous Arch en mixant les usages et j'ai réalisé que je m'y faisais très
|
||||
bien. L'absence de barre de tâches ne me choque plus et je m'en sors même dans
|
||||
des usages *professionnels* avec beaucoup d'application ouvertes. Alors qu'est
|
||||
-ce qui a changé ? Certes l'interface est cohérente et agréable, la recherche
|
||||
d'applications est plus rapide qu'à l'époque, on configure sans problème
|
||||
l'utilisation multi-moniteur, c'est plus stable ... Cool mais rien de vraiment
|
||||
déterminant ! En fait, ce qui a réellement changé c'est que *le vieil
|
||||
utilisateur* que je suis a enfin digéré la rupture Gnome 2 / Gnome 3 et sauté
|
||||
le pas vers cette nouvelle interface. Il est possible que la confrontation aux
|
||||
interfaces pour mobile (Android, BB 10) ait accéléré l'acceptation d'un
|
||||
nouveau type d'interface sur le bureau.
|
||||
|
||||
J'ai aussi basculé ma Fedora XFCE Spin vers Gnome au bureau et les quelques
|
||||
jours d'utilisation sont positifs. Mon image d'utilisateur Linux avec une
|
||||
interface archaïque et des terminaux plein les écrans s'écorne... J'ai
|
||||
toujours des terminaux mais avec une interface moderne et sexy à faire saliver
|
||||
les utilisateurs de Windows 7 et tousser ceux de Windows 8
|
||||
(**troll inside**).
|
||||
|
||||
Plus sérieusement, comme d'autres j'ai douté de la
|
||||
révolution Gnome en 2011 et c'est un beau projet que je retrouve 2 ans après.
|
||||
Je ne renie pas XFCE, idéal pour les configurations plus légères que je suis
|
||||
amené à installer mais je suis **enfin reconcilié** avec Gnome.
|
||||
|
||||
203
posts/2014/2014-05-25-supervisor.md
Executable file
203
posts/2014/2014-05-25-supervisor.md
Executable file
|
|
@ -0,0 +1,203 @@
|
|||
<!-- title: Supervisor, gestion de processus -->
|
||||
<!-- category: GNU/Linux -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Quand il s'agit de déployer des programmes de son cru sur un serveur
|
||||
GNU/Linux, on réalise généralement deux actions :
|
||||
|
||||
- l'écriture d'un script de démarrage et arrêt du programme
|
||||
- la *démon-isation* du programme
|
||||
<!-- more -->
|
||||
Le premier point n'est pas complexe mais il peut être contraignant. Si on
|
||||
envisage de déployer sur Debian, Ubuntu et Fedora, il faut prévoir trois
|
||||
scripts différents : un pour les scripts à la saucce Sys V, un pour Upstart
|
||||
et un autre pour systemd. L'avantage c'est qu'on peut gérer finement les
|
||||
dépendances à d'autres services.
|
||||
|
||||
Le second point consiste à veiller à ne pas bloquer le script d'init en
|
||||
lançant le programme. On peut le gérer dans le code de notre programme en
|
||||
prévoyant deux modes de lancement de notre programme : *daemon* et
|
||||
interactif. Python, par exemple, propose [la librairie
|
||||
daemonize](https://pypi.python.org/pypi/daemonize) pour réaliser cela. JAVA
|
||||
propose des outils comme JAVA Service Wrapper pour gérer le lancement et
|
||||
garantir l'arrêt du processus. On peut aussi le gérer de manière externe au
|
||||
code, de manière rustique avec un
|
||||
[nohup](https://en.wikipedia.org/wiki/Nohup), auquel cas il faut gérer
|
||||
l'arrêt fiable du processus en manipulant son PID.
|
||||
|
||||
Voici un exemple de script d'init à la sauce Debian pour un programme
|
||||
JAVA :
|
||||
|
||||
``` shell
|
||||
### BEGIN INIT INFO
|
||||
# Provides: monprog
|
||||
# Required-Start: $local_fs $remote_fs $network $syslog
|
||||
# Required-Stop: $local_fs $remote_fs $network $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# X-Interactive: true
|
||||
# Short-Description: Start/stop monprog
|
||||
### END INIT INFO
|
||||
BOOT_LOG=/var/log/monprog-boot.log
|
||||
PID_FILE=/opt/monprog/pid
|
||||
start_java () {
|
||||
nohup java -cp "/opt/monprog/lib/*" fr.yax.monprog.Main >$BOOT_LOG 2>&1 &
|
||||
echo $! > $PID_FILE
|
||||
echo "Monprog started ..."
|
||||
}
|
||||
do_start () {
|
||||
echo "Starting Monprog ..."
|
||||
if [ ! -f $PID_FILE ]; then
|
||||
start_java
|
||||
else
|
||||
PID=$(cat $PID_FILE)
|
||||
if [ -d /proc/$PID ]; then
|
||||
echo "Monprog is already running ..."
|
||||
else
|
||||
start_java
|
||||
fi
|
||||
fi
|
||||
}
|
||||
do_stop() {
|
||||
echo "Stopping Monprog ..."
|
||||
if [ -f $PID_FILE ]; then
|
||||
PID =$(cat $PID_FILE);
|
||||
kill $PID 2>/dev/null
|
||||
echo "Monprog stopped ..."
|
||||
rm -f $PID_FILE
|
||||
else
|
||||
echo "Monprog seems not running ..."
|
||||
fi
|
||||
}
|
||||
case $1 in
|
||||
start)
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
do_stop
|
||||
;;
|
||||
restart)
|
||||
do_stop
|
||||
sleep 1
|
||||
do_start
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
C'est perfectible. Il faudrait tenter l'arrêt avec un signal moins violent
|
||||
que SIGKILL de façon à l'intercepter dans le code et faire un arrêt propre.
|
||||
Si cette méthode ne fonctionne pas au bout de plusieurs secondes, le script d'init pourrait alors opter pour un arrêt radical.
|
||||
|
||||
Cette méthode fonctionne bien mais elle nécessite une connaissance système
|
||||
pour écrire et maintenir les scripts en fonction des déploiements cible. Si
|
||||
on veut donner la possibilité à un utilisateur standard (non *root*) de
|
||||
démarrer ou arrêter un programme, il faut aussi maîtriser un peu la gestion
|
||||
des droits UNIX (avec sudo par exemple).
|
||||
|
||||
Une alternative simple pour la plupart des systèmes UNIX (GNU/Linux, FreeBSD,
|
||||
Solaris et Mac OS X) est le [programme Supervisor](http://supervisord.org).
|
||||
C'est écrit en Python (comme la plupart des programmes de qualité ! **Troll
|
||||
inside** ) et de même que MongoDB permet au développeur de reprendre la main
|
||||
au DBA sur l'administration de base de donnée, Supervisor permet au
|
||||
développeur de reprendre un peu la main à l'admin sys sur le déploiement de
|
||||
ses applications.
|
||||
|
||||
Supervisor est fourni sur la plupart des distributions. On peut l'installer
|
||||
avec le système de paquet de sa distribution ou bien opter pour une
|
||||
installation à partir de PIP, l'installeur de programmes Python. Ce dernier
|
||||
permet d'obtenir la version la plus récente de Supervisor.
|
||||
|
||||
Supervisor est composé de deux parties :
|
||||
|
||||
- un service **Supervisord**
|
||||
- un client en mode console : **Supervisorctl**
|
||||
|
||||
Le client permet d'interagir avec les programmes gérés : démarrer, stopper.
|
||||
Une interface RPC permet aussi de piloter Supervisord programmatiquement ; je
|
||||
n'ai pas encore testé cet aspect.
|
||||
|
||||
La configuration principale est dans un fichier supervisord.conf qui décrit la
|
||||
connexion du client supervisorctl (section unix_http_server), la config RPC
|
||||
(section rpcinterface) et le répertoire des configuration des programmes à
|
||||
gérer (section includes).
|
||||
|
||||
Voici une configuration type :
|
||||
|
||||
#### /etc/supervisor/supervisord.conf
|
||||
|
||||
[unix_http_server]
|
||||
file=/var/run//supervisor.sock ; (the path to the socket file)
|
||||
chmod=0770 ; sockef file mode (default 0700)
|
||||
chown=root:supervisor
|
||||
|
||||
[supervisord]
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
childlogdir=/var/log/supervisor
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisorrpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///var/run//supervisor.sock
|
||||
|
||||
[include]
|
||||
files = /etc/supervisor/conf.d/*.conf
|
||||
|
||||
Les droits sur la socket UNIX sont important. En donnant l'accès à ROOT et au
|
||||
groupe supervisor, on peut facilement donner l'accès à supervisorctl en
|
||||
ajoutant un utilisateur dans le groupe supervisor. Attention donner l'accès à
|
||||
supervisorctl c'est donner le droit de stopper n'importe quel programme géré
|
||||
par supervisor. C'est un privilège important.
|
||||
|
||||
Le reste de la configuration consiste à créer des configurations
|
||||
additionnelles décrivant des programmes à lancer simplement :
|
||||
|
||||
- par défaut un programme démarre en même temps que le service donc au
|
||||
démarrage du serveur. C'est configurable.
|
||||
- on peut définir si un programme doit être relancé automatiquement et définir sous quelle condition, par exemple en fonction du code de sortie du programme.
|
||||
- on peut opter pour l'envoi d'un signal au programme afin de demander au programme de s'arrêter proprement plutôt que de forcer un arrêt brutal.
|
||||
- on peut regrouper des programmes pour manipuler des
|
||||
groupes, faire des démarrages groupés et des arrêts groupés. C'est utile si on a beaucoup de programmes.
|
||||
- au sein d'un groupe on peut définir des
|
||||
priorités pour ordonner le lancement des programmes du groupe.
|
||||
|
||||
Voici un exemple qui définit un groupe mesprogrammes composé de 2 programmes correspondant au même binaire.
|
||||
|
||||
#### /etc/supervisor/conf.d/mesprogrammes.conf
|
||||
|
||||
[group:mesprogrammes]
|
||||
programs=monprog1,monprog2
|
||||
|
||||
[program:monprog1]
|
||||
directory=/opt/monprogram
|
||||
command=/usr/bin/java -DrunDir=/opt/monprog -cp "lib/*" fr.yax.monprog.Main --port 1234
|
||||
stopsignal=INT
|
||||
priority=500
|
||||
|
||||
[program:monprog2]
|
||||
directory=/opt/monprogram
|
||||
command=/usr/bin/java -DrunDir=/opt/monprog -cp "lib/*" fr.yax.monprog.Main --port 1235
|
||||
stopsignal=INT
|
||||
priority=501
|
||||
|
||||
Dans cet exemple, on envoie un signal SIGINT à monprog pour lui demander un arrêt propre. Voici un snippet de code JAVA pour intercepter le signal :
|
||||
|
||||
#### Interception d'un signal SIGINT en JAVA
|
||||
|
||||
``` java
|
||||
// register a shutdown hook
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
logger.info("Shutting down has been requested");
|
||||
stopCleanly();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
En conclusion, **Supervisor** est un bon outil de gestion de programmes :
|
||||
fiable, facile à installer et à configurer. En complément d'un outil de
|
||||
déploiement comme [Fabric](http://www.fabfile.org) un développeur peut
|
||||
facilement automatiser le déploiement de son programme sur une ou plusieurs
|
||||
machines cibles.
|
||||
23
posts/2014/2014-08-05-vacances.md
Executable file
23
posts/2014/2014-08-05-vacances.md
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
<!-- title: En vacances -->
|
||||
<!-- category: Humeur -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Bon, il ne faut pas se mentir, la saison chaude en Provence ça ne booste pas la
|
||||
productivité.<!-- more --> On assure l'essentiel mais l'activité de blogging en a fait les
|
||||
frais. C'est une demi excuse. L'autre moitié de l'excuse c'est que j'ai
|
||||
*mollement* codé ces dernières semaines un petit projet de gestion des
|
||||
commentaires d'un blog statique, un projet qui me tient à coeur depuis plus
|
||||
d'un an. C'est un petit projet mais j'ai pris le temps de la réflexion et
|
||||
savouré le codage dans mon [langage fétiche](https://www.python.org). Je
|
||||
termine la documentation pour pouvoir le publier décemment sous GitHub et je
|
||||
consacrerais bientôt un article dessus.
|
||||
|
||||
Pour me relaxer, j'ai travaillé un peu la cosmétique du site :
|
||||
|
||||
- mise à jour de [Pelican](http://docs.getpelican.com/en/3.4.0) en version 3.4
|
||||
- mise à jour des librairies CSS: [Pure](http://purecss.io) en version 0.5.0, [Font Awesome](http://fortawesome.github.io/Font-Awesome) en version 4.1.0
|
||||
- *subtiles retouches* de quelques détails visuels
|
||||
|
||||
Bon été à tous
|
||||
|
||||
<img src="/images/2014/apero.jpg"/>
|
||||
130
posts/2014/2014-08-07-pecosys.md
Executable file
130
posts/2014/2014-08-07-pecosys.md
Executable file
|
|
@ -0,0 +1,130 @@
|
|||
<!-- title: Pecosys, les commentaires avec Pelican -->
|
||||
<!-- categories: Hébergement Blog -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Pecosys est le projet évoqué dans mon dernier billet pour gérer des
|
||||
commentaires avec un blog statique<!-- more --> créé avec
|
||||
[Pelican](http://docs.getpelican.com/en/3.4.0). J'ai publié [l'ensemble des
|
||||
sources sur mon GitHub](https://github.com/kianby/pecosys) sous licence GPL.
|
||||
Avant d'expliquer à quoi ça sert, une présentation des types de moteurs de
|
||||
blog s'impose.
|
||||
|
||||
#### Petite intro sur les blog statiques
|
||||
|
||||
Les moteurs de blog classiques comme Wordpress ou Dotclear stockent leurs
|
||||
données (articles, commentaires) dans une base de données et ils utilisent une
|
||||
logique côté serveur pour produire les pages HTML. Au fil des ans, ces moteurs
|
||||
ont rajouté beaucoup de fonctionnalités (par l'utilisation de plugins) et on
|
||||
les appelle désormais des CMS (Content Management System) car ils peuvent
|
||||
servir à bâtir tout type de site Web, en facilitant le travail de publication
|
||||
et de collaboration aux rédacteurs qui n'ont plus besoin d'être des gens
|
||||
techniques.
|
||||
|
||||
PluXml est un moteur un peu à part, plus léger que les CMS cités ci-dessus,
|
||||
qui n'utilise pas de base de données mais stocke les données dans des fichiers
|
||||
XML. C'est un pas dans la direction des blogs statiques dans la mesure où cela
|
||||
permet de mettre son blog dans un gestionnaire de sources (comme GIT) et
|
||||
conserver une traçabilité des changements. Cela facilite aussi la migration du
|
||||
blog.
|
||||
|
||||
Pelican et Jekyll sont des vrais blogs statiques. Ils n'utilisent pas de
|
||||
langage serveur comme PHP ou Ruby, il ne stockent pas leurs données dans une
|
||||
base de données. Les articles sont écrits dans un langage Markup comme
|
||||
[Markdown](http://daringfireball.net/projects/markdown) et la construction du
|
||||
site (le build) est réalisé hors ligne. Il génère les pages à base de HTML,
|
||||
CSS et éventuellement un zeste de JavaScript. Ces pages sont transférées vers
|
||||
le serveur HTTP hébergeant le site... et hop le site est à jour.
|
||||
|
||||
Alors pourquoi s'embêter à gérer un site statique alors qu'un Wordpress
|
||||
s'installe en 5 minutes ?
|
||||
|
||||
Cela dépend de tout un chacun mais j'y suis venu pour les raisons suivantes :
|
||||
|
||||
- Les articles sont écrits dans un format simpliste (pour ma part c'est Markdown), la présentation est clairement séparée du contenu. C'est lors du build qu'on génère le code HTML en fonction de *templates* et de CSS personnalisés par nos soins. Le code HTML généré par Pelican est propre et léger. Le jour où j'ai migré de WordPress à PluXml, j'ai été horrifié par le code HTML de WordPress.
|
||||
- Le contenu du blog est un ensemble de fichier au format texte, idéal à gérer avec un gestionnaire de sources afin de garder trace des modifications. Un gestionnaire de sources devient aussi un moyen d'automatiser la mise à jour du site. On écrit et on teste sur sa machine de dev, on publie sous GIT et il suffit que le serveur rafraîchisse sa version du site quand une modification a été effectuée.
|
||||
|
||||
#### La problématique des commentaires
|
||||
|
||||
Pas de logique serveur, juste un ensemble de pages HTML avec un peu
|
||||
d'interactivité grâce à JavaScript. Comment gérer les commentaires avec un
|
||||
site statique ? La solution proposée par Pelican c'est l'utilisation des
|
||||
services de la société Disqus. Un peu de JavaScript embarqué au bon endroit et
|
||||
vos pages sont agrémentées d'un formulaire pour poster des commentaires qui
|
||||
envoie les données chez Disqus et l'affichage de la page dans le navigateur
|
||||
client par l'usage de JavaScript, envoie des requêtes à Disqus pour rapatrier
|
||||
les commentaires approuvées et les ajouter à la page HTML qui vient de votre
|
||||
serveur.
|
||||
|
||||
Est-ce que vous sentez venir l'objection ?
|
||||
|
||||
D'abord on met en place une belle mécanique,très pure, où l'on contrôle le
|
||||
contenu, l'affichage, puis on confie la partie sensible (les données
|
||||
utilisateur) à une société commerciale, qui ne demande rien en retour et qui
|
||||
propose sûrement un service aux petits oignons pour approuver les
|
||||
commentaires... mais qui garde les données. Comment une société comme Disqus
|
||||
monétise ses services ? Je ne sais pas, peu importe. Que se passe-t-il si la
|
||||
société dépose le bilan ? Là j'ai la réponse. L'ensemble des commentaires est
|
||||
perdu : une bonne partie de la richesse d'un blog, ce qui fait son histoire.
|
||||
Dommage non ?
|
||||
|
||||
#### L'approche Pecosys
|
||||
|
||||
Pecosys est un serveur de commentaires écrit en Python que vous hébergez sur le même serveur que votre blog. Il reçoit les commentaires à approuver depuis le blog par le biais d'un formulaire sur le blog. Pour cela, les *templates* de Pelican ont été adaptés afin de rajouter ce formulaire en bas de chaque article.
|
||||
|
||||
Le lien entre le blog statique et le serveur Pecosys est réalisé par grâce au serveur Web. Dans le cas de NginX, il est trivial d'associer une URL à un programme Python. Dans le cas d'Apache, c'est faisable facilement en utilisant le module Proxy. Bref, le serveur Pecosys est d'abord un serveur HTTP sur lequel on poste les commentaires entrés par un formulaire classique de création de commentaires.
|
||||
|
||||
Quand un commentaire est reçu, le serveur va faire deux trucs : sauvegarder le commentaire et le soumettre à l'administrateur du blog.
|
||||
|
||||
La sauvegarde se fait grâce à GIT. Ah j'avais pas encore parlé de GIT :-) On suppose qu'on est dans une architecture centralisée où le blog est modifié depuis une machine de développeur et poussé (au sens GIT: PUSH) vers un *bare repository*. Dans mon cas, cette référence centrale des sources est sous BitBucket car ils acceptent la création de dépôts privés gratuitement et que je ne veux pas publier les adresses emails de tous ceux qui ont laissé un commentaire sur le blog. Souvenez-vous les commentaires font désormais partie des sources du blog, on verra comment plus loin.
|
||||
|
||||
Donc, pour résumer :
|
||||
|
||||
- j'écris mes articles sur ma machine de dev perso, je publie dans GIT et je pousse mes modifications au GIT centralisé de BitBucket (au sens GIT: ORIGIN).
|
||||
- mon serveur vérifie périodiquement si le dépôt BitBucket a été modifié et si c'est le cas, il rapatrie les sources du blog et reconstruit le site grâce à sa mécanique Pelican installée localement.
|
||||
- Pecosys a sa propre version du blog (au sens GIT: CLONE) maintenue à jour de BitBucket.
|
||||
|
||||
Donc quand Pecosys reçoit un nouveau commentaire, il met à jour sa version du
|
||||
blog (la branche MASTER) et il crée une nouvelle branche XYZ pour ce
|
||||
commentaire. il sauve ce commentaire dans les sources du blog (au format
|
||||
Markdown) et il committe la branche XYZ.
|
||||
|
||||
Ensuite, le serveur va le communiquer à l'administrateur du blog par email.
|
||||
Cela suppose qu'un email dédié est utilisé par Pecosys (pourquoi pas
|
||||
blog@mydomain.com) et qu'il connaît l'email de l'administrateur du blog (vous
|
||||
!). Cet email contient le commentaire et demande une réponse.
|
||||
|
||||
L'administrateur du blog (toujours vous) doit répondre à cet email. Une
|
||||
réponse sans commentaire revient à approuver le commentaire et va lancer sa
|
||||
publication. Une réponse avec un commentaire "NO" (désolé pour l'originalité)
|
||||
signifie qu'on refuse le commentaire.
|
||||
|
||||
En fonction de cette réponse, le serveur Pecosys qui vérifie sa boite de
|
||||
réception régulièrement, va traiter le commentaire :
|
||||
|
||||
- un refus du commentaire revient à supprimer la branche GIT XYZ
|
||||
- une approbation du commentaire ramène les modifications de la branche XYZ sur la branche MASTER (au sens GIT: MERGE) et pousse les modifications sur le GIT distant (dans mon cas BitBucket)
|
||||
|
||||
Dans les deux cas, un email de confirmation de l'action réalisée est envoyé à
|
||||
l'administrateur du blog.
|
||||
|
||||
A ce stade, la branche de référence BitBucket est à jour donc le serveur va
|
||||
ramener ses modifications, reconstruire le site et par là même
|
||||
publier le commentaire.
|
||||
|
||||
Si vous avez bien suivi et je sais que c'est un peu touffu et compliqué, vous
|
||||
vous demandez comment les commentaires (ces fichiers en Markdown) sont générés
|
||||
en HTML. Et bien, pas le biais d'un plugin Pelican nommé **CaCause**, en
|
||||
hommage au projet de base initié il y a un an avec [Bruno
|
||||
Adele](http://www.jesuislibre.org) et [Nahir
|
||||
Mohamed](https://github.com/nadley) dont Pecosys est une reprise des idées
|
||||
principales mais avec une réalisation différente par son dialogue basé sur
|
||||
l'email et son utilisation *forcenée* de GIT.
|
||||
|
||||
Je teste Pecosys depuis deux semaines sur ce site et je suis prêt à donner un
|
||||
coup de main à quiconque veut se lancer. Sur GitHub, j'ai publié les sources
|
||||
du serveur mais aussi une version allégée de ce site (sans les commentaires)
|
||||
qui contient donc mes *templates* avec le formulaire et les sources du plugin.
|
||||
|
||||
En attendant je retourne à mon farniente estival :-)
|
||||
|
||||
<img src="/images/2014/lemon.jpg"/>
|
||||
123
posts/2014/2014-08-12-qemu-raspbian.md
Executable file
123
posts/2014/2014-08-12-qemu-raspbian.md
Executable file
|
|
@ -0,0 +1,123 @@
|
|||
<!-- title: Emuler la Raspbian avec Qemu -->
|
||||
<!-- categories: Debian Matériel Virtualisation -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
<img src="/images/2014/rasplogo.png" alt="Raspberry logo" style="margin: 0px
|
||||
20px; float:left;" />Je m'intéresse de plus en plus au Raspberry et je
|
||||
franchirai peut-être le pas de l'achat dans quelque temps. J'ai voulu voir à
|
||||
quoi ressemble sa distribution principale Raspbian (basée sur Debian) en
|
||||
l'émulant sous Qemu. <!-- more -->Je me suis basé sur [le tutorial pointé par beaucoup de
|
||||
gens dans les forums](http://xecdesign.com/qemu-emulating-raspberry-pi-the-
|
||||
easy-way/) et j'ai effectué des recherches annexes pour résoudre
|
||||
certains problèmes : taille des partitions, gestion de la souris sous Qemu. Ce
|
||||
qui suit est le résultat de mes manipulations pour émuler Raspbian avec Qemu
|
||||
depuis une distribution GNU/Linux 64 bits.
|
||||
|
||||
En pré-requis, on suppose que Qemu est installé sur le système hôte. On
|
||||
vérifie que le processeur ARM du Raspberry est supporté par Qemu avec la
|
||||
commande suivante :
|
||||
|
||||
``` shell
|
||||
$ qemu-system-arm -cpu ?
|
||||
```
|
||||
|
||||
Le résultat liste les types de processeur supportés. On s'assure que **arm1176** est mentionné.
|
||||
|
||||
### Installation de base
|
||||
|
||||
On se crée un répertoire de travail dans lequel on va télécharger les fichiers nécessaires :
|
||||
|
||||
- le noyau Linux [depuis ce lien](http://xecdesign.com/downloads/linux-qemu/kernel-qemu)
|
||||
- l'image de la Raspbian [depuis le site officiel](http://www.raspberrypi.org/downloads)
|
||||
|
||||
La modification d'un fichier est nécessaire pour que la distribution
|
||||
fonctionne avec Qemu. On effectue donc un premier démarrage particulier avec
|
||||
BASH en processus INIT pour la réaliser.
|
||||
|
||||
``` shell
|
||||
$ qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw init=/bin/bash" -hda 2014-06-20-wheezy-raspbian.img
|
||||
```
|
||||
|
||||
Quand Qemu a démarré BASH on modifie le fichier /etc/ld.so.preload
|
||||
|
||||
$ nano /etc/ld.so.preload
|
||||
|
||||
On commente la première ligne du fichier :
|
||||
|
||||
#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
|
||||
|
||||
On sauvegarde (CTRL-X avec nano) et on arrête l'émulation
|
||||
|
||||
exit
|
||||
|
||||
A ce stade, l'émulation Raspbian sous Qemu est fonctionnelle et on peut faire un vrai démarrage avec la commande :
|
||||
|
||||
$ qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda 2014-06-20-wheezy-raspbian.img
|
||||
|
||||
### Elargir la partition
|
||||
|
||||
Il ne reste pas beaucoup d'espace disque sur la partition root. On peut
|
||||
élargir la partition, sinon on ne pourra même pas mettre à jour Raspbian avec
|
||||
apt-get. Cela nécessite plusieurs étapes.
|
||||
|
||||
D'abord on élargit le disque avec l'utilitaire qemu-resize.
|
||||
|
||||
$ qemu-img resize 2014-06-20-wheezy-raspbian.img +2G
|
||||
|
||||
Ensuite on démarre la Raspbian avec Qemu
|
||||
|
||||
``` shell
|
||||
$ qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda 2014-06-20-wheezy-raspbian.img
|
||||
```
|
||||
|
||||
On se connecte au Raspberry avec l'utilisateur **pi** et le mot de passe
|
||||
**raspberry**. Attention si on se connecte depuis la fenêtre Qemu, le clavier
|
||||
est probablement configuré en QWERTY.
|
||||
|
||||
On lancer l'utilitaire **fdisk** pour modifier les partitions
|
||||
|
||||
$ fdisk /dev/sda
|
||||
|
||||
- supprimer la partition 2 qui commence à l'offset 122880 : commande **d** puis indiquer la partition **2**
|
||||
- recréer une partition 2 qui commence à l'offset 122880 et utilise la totalité du disque : commande **n**
|
||||
- sauvegarder les modifications : commande **w**
|
||||
- arrêter le système avec la commande **reboot**.
|
||||
|
||||
On démarre à nouveau la Raspbian avec Qemu et on lance la commande resize2fs
|
||||
pour élargir la partition 2 :
|
||||
|
||||
$ resize2fs /dev/sda2
|
||||
$ reboot
|
||||
|
||||
### Augmenter la résolution sous X
|
||||
|
||||
Par défaut, on a une résolution en 640x480 quand on lance LXDE avec
|
||||
**startx**. On peut monter en 800x600 en créant un fichier *xorg.conf*.
|
||||
|
||||
# sudo nano /etc/X11/xorg.conf
|
||||
|
||||
Ajouter ces lignes dans le fichier :
|
||||
|
||||
Section "Screen"
|
||||
Identifier "Default Screen"
|
||||
SubSection "Display"
|
||||
Depth 16
|
||||
Modes "800x600" "640x480"
|
||||
EndSubSection
|
||||
EndSection
|
||||
|
||||
Sauvegarde et redémarrer X pour voir le résultat.
|
||||
|
||||
### Déplacements erratiques de la souris
|
||||
|
||||
J'ai été confronté à ce problème lié à la configuration de Qemu. La souris se
|
||||
fige ou certaines portions de l'écrans deviennent inaccessibles. je l'ai
|
||||
résolu en lançant Qemu ainsi :
|
||||
|
||||
qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -usbdevice tablet -display sdl -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda 2014-06-20-wheezy-raspbian.img
|
||||
|
||||
Notez le paramètre *-usbdevice tablet* et *-display sdl*.
|
||||
|
||||
### Conclusion
|
||||
|
||||
L'émulation Qemu permet de se faire une bonne idée de la distribution. Bien sûr, ce n'est pas complètement fonctionnel car certains périphériques spécifiques au Raspberry ne sont pas présent (je pense aux entrées / sortie, au port HDMI) mais cela permet déjà beaucoup.
|
||||
146
posts/2014/2014-09-15-install-shinken.md
Executable file
146
posts/2014/2014-09-15-install-shinken.md
Executable file
|
|
@ -0,0 +1,146 @@
|
|||
<!-- title: Installation de Shinken -->
|
||||
<!-- category: GNU/Linux -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Dans la série "ma vie de sysadmin en semi-pro", je me suis frotté à la mise
|
||||
en place d'une supervision de type Nagios.<!-- more --> Mon besoin est la surveillance de
|
||||
quelques serveurs et services critiques et la remontée d'alertes en cas de
|
||||
souci. Nagios est la référence dans le domaine avec des centaines de greffons
|
||||
pour surveiller la plupart des applications existantes et la possiblité de
|
||||
créer ses propres greffons pour ses applications spécifiques. Par goût de la
|
||||
démarcation (mais pas seulement), j'ai opté pour
|
||||
[Shinken](https://fr.wikipedia.org/wiki/Shinken_%28logiciel%29), un
|
||||
*fork* de Nagios qui a plusieurs avantages à mes yeux :
|
||||
|
||||
- c'était une branche expérimentale de Nagios qui aurait dû succéder au Nagios actuel dont les critiques disent que le noyau n'évolue pas assez vite par rapport aux demandes des utilisateurs,
|
||||
- son architecture est saluée pour sa capacité de montée en charge (distribuée, balance de charge),
|
||||
- c'est écrit en Python et la compatibilité est totale avec les greffons Nagios.
|
||||
|
||||
La supervision en général et Nagios en particulier est un vaste sujet et des
|
||||
IT administrant des milliers de serveurs et de services ont beaucoup plus de
|
||||
légitimité que moi pour en parler. Je vais me borner à décrire les étapes
|
||||
d'une installation sans problème sur un serveur Debian Wheezy.
|
||||
|
||||
### Installation de Shinken
|
||||
|
||||
Ce qui suit s'inspire directement du [10 minutes Shinken installation guide](https://shinken.readthedocs.org/en/latest/02_gettingstarted/installations/shinken-installation.html) avec quelques adaptations pour Debian Wheezy.
|
||||
|
||||
Installation des paquets Debian nécessaires :
|
||||
|
||||
$ apt-get install python-cherrypy3 python-pip \
|
||||
python-pycurl nagios-plugins
|
||||
|
||||
Création d'un utilisateur **shinken** dédié :
|
||||
|
||||
$ adduser shinken
|
||||
|
||||
Et finalement installation de shinken lui-même avec le programme PIP (je suppose que Python et PIP 2.x sont installés sur votre Debian) :
|
||||
|
||||
$ pip install shinken
|
||||
|
||||
C'est aussi simple que cela. On a installé le moteur de Shinken mais aucune
|
||||
interface graphique. Je découvre petit à petit mais l'interface est une
|
||||
composante optionnelle et plusieurs sont proposées. J'ai choisi
|
||||
d'installer **webui**, celle recommandée qui apporte de la visualisation (la
|
||||
configuration se fait en modifiant des fichiers et en redémarrant les
|
||||
services Shinken).
|
||||
|
||||
### Installation de Webui
|
||||
|
||||
Shinken propose son propre gestionnaire de greffons avec le programme **shinken**.
|
||||
|
||||
$ shinken --init
|
||||
$ shinken install webui
|
||||
$ shinken install auth-cfg-password
|
||||
|
||||
Webui nécessite un stockage en base pour stocker les préférences
|
||||
utilisateurs. On peut se limiter à SQLite, j'ai choisir MongoDB (la base
|
||||
NoSQL) qui me sert à d'autres usages.
|
||||
|
||||
$ apt-get install mongodb python-pymongo
|
||||
$ shinken install mod-mongodb
|
||||
|
||||
Editer */etc/shinken/modules/webui.cfg* et rajouter les modules dépendants :
|
||||
|
||||
modules auth-cfg-password,mongodb
|
||||
|
||||
Editer */etc/shinken/brokers/broker-master.cfg* et rajouter le module webui :
|
||||
|
||||
modules webui
|
||||
|
||||
Il reste à définir les contacts (personnes) du système dans
|
||||
*/etc/shinken/contacts*. Par défaut, un administrateur est défini dans
|
||||
*/etc/shinken/contacts/admin.cfg*, son mot de passe est utilisé pour
|
||||
l'interface Webui.
|
||||
|
||||
Deux commandes servent régulièrement quand on modifie la configuration.
|
||||
|
||||
Vérifier que la configuration est syntaxiquement correcte :
|
||||
|
||||
$ service shinken check
|
||||
|
||||
Redémarrer les services Shinken :
|
||||
|
||||
$ service shinken restart
|
||||
|
||||
Si tout est correct, on peut se connecter sur Webui depuis un navigateur à l'adresse :
|
||||
|
||||
http://<SERVER>:7767
|
||||
|
||||
### les objets supervisés
|
||||
|
||||
Nagios introduit la notion de *host* et de *service* pour désigner les
|
||||
machines et les services s'exécutant sur ces machines. La configuration de
|
||||
Shinken après installation est minimale :
|
||||
|
||||
- les notifications par email sont activées et seront utilisées si [votre serveur peut envoyer des emails](http://blogduyax.madyanne.fr/smtp-relay-avec-qmail-sur-debian-wheezy.html)
|
||||
- la machine locale est elle-même supervisée de manière générique, je crois que le seul indicateur c'est le Ping pour vérifier qu'elle est accessible.
|
||||
|
||||
On va enrichir tout cela en installant un agent SNMP sur le serveur Shinken ce qui permet de surveiller, entre autre, l'utilisation CPU, RAM, occupation des disques.
|
||||
|
||||
On installe un agent SNMP sur la machine locale avec le paquet **snmpd** qui, par défaut, n'est accessible que par localhost :
|
||||
|
||||
$ apt-get install snmpd
|
||||
|
||||
On rajoute le greffon linux-snmp dans Shinken :
|
||||
|
||||
$ shinken install linux-snmp
|
||||
|
||||
On corrige deux soucis de l'installation sous Debian :
|
||||
|
||||
le script **check_icmp** doit avoir les droits setuid :
|
||||
|
||||
$ chmod u+s /usr/lib/nagios/plugins/check_icmp
|
||||
|
||||
Le module PERL **utils.pm** est mal référencé par les greffons Nagios ; on le
|
||||
fait pointer sur celui de notre installation de PERL dans */usr/share/perl5*
|
||||
|
||||
/usr/share/perl5$ ln -s /usr/lib/nagios/plugins/utils.pm
|
||||
|
||||
On peut modifier la configuration du *host* **localhost** en éditant le fichier */etc/shinken/hosts/localhost.cfg* :
|
||||
|
||||
define host{
|
||||
use linux-snmp
|
||||
contact_groups admins
|
||||
host_name localhost
|
||||
address 127.0.0.1
|
||||
}
|
||||
|
||||
On vérifie la configuration et on redémarre Shinken :
|
||||
|
||||
$ service shinken check
|
||||
$ service shinken restart
|
||||
|
||||
Si la configuration est correcte, la machine locale avec ses services CPU,
|
||||
Mémoire apparaît désormais dans Webui. La fréquence du *polling*, les
|
||||
notifications, tout est configurable finement par *host* , par groupe de
|
||||
*host*, par service. La documentation est riche et bien détaillée.
|
||||
|
||||
Dans le cas de GNU/Linux, la supervision par SNMP apporte les indicateurs de
|
||||
base d'un serveur. Pour avoir plus, on peut donner l'accès SSH au superviseur
|
||||
Shinken sur les serveurs ou on peut installer NRPE (Nagios Remote Plugin
|
||||
Executer). Je préfère NRPE car on ne demande pas l'accès total au serveur à
|
||||
superviser. L'installation de [NRPE est bien décrite dans cet
|
||||
article](http://xmodulo.com/2014/03/nagios-remote-plugin-executor-nrpe-
|
||||
linux.html). Pour finir, beaucoup de resources Nagios sont disponibles sur
|
||||
le site [Nagios Exchange](http://exchange.nagios.org).
|
||||
36
posts/2014/2014-10-23-pecosys-v2.md
Executable file
36
posts/2014/2014-10-23-pecosys-v2.md
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
<!-- title: Du nouveau sur Pecosys -->
|
||||
<!-- categories: Hébergement Blog -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Pecosys est le gestionnaire de commentaires pour les blog statiques créés avec
|
||||
[Pelican](http://docs.getpelican.com/en/3.4.0) présenté [dans ce
|
||||
billet](http://blogduyax.madyanne.fr/pecosys-les-commentaires-avec-pelican.html) en
|
||||
août dernier.<!-- more --> Pour rappel, il s'agit de proposer une alternative aux systèmes
|
||||
décentralisés sur des sites tiers comme Disqus et de conserver ces données qui
|
||||
font partie de l'Histoire d'un blog dans les sources du blog.
|
||||
|
||||
La présentation du projet a eu un petit succès d'estime. Je suis conscient que
|
||||
le public ciblé est réduit : du barbu (ou pas) qui écrit ses articles en
|
||||
Markdown, le construit en HTML statique gràce à Pelican et versionne les
|
||||
sources dans GIT. Sachant que Pecosys demande quelques connaissances système
|
||||
pour s'installer et qu'il est écrit en Python, on touche les gens qui ont un
|
||||
serveur dédié (physique ou virtuel) à la maison ou chez un hébergeur et qui
|
||||
aiment se faire plaisir (ou mal selon le point de vue)..
|
||||
|
||||
Pecosys est en fonction sur ce blog depuis 3 mois. Il y a eu beaucoup de
|
||||
corrections de bugs (désolé pour les commentaires perdus, ça ne devrait plus
|
||||
arriver grâce aux logs étendus de NginX) et quelques nouveautés livrées et
|
||||
installées tout récemment :
|
||||
|
||||
- Le support multi-langue dans la communication entre Pecosys et
|
||||
l'administrateur du blog. Pour l'instant, le français et l'anglais sont
|
||||
proposés.
|
||||
- Une communication plus humaine entre Pecosys et l'administrateur du blog
|
||||
avec des emails moins télégraphiques.
|
||||
- La possibilité pour les lecteurs de s'abonner par email au flux de
|
||||
commentaire d'un article et de se désabonner quand ils le souhaitent.
|
||||
- La possibilité de relancer la *génération Pelican* du blog à chaque publication d'un
|
||||
commentaire.
|
||||
|
||||
L'ensemble des sources et une documentation plus technique est publié [sur mon
|
||||
GitHub.](https://github.com/kianby/pecosys)
|
||||
98
posts/2014/2014-11-02-diaspora.md
Executable file
98
posts/2014/2014-11-02-diaspora.md
Executable file
|
|
@ -0,0 +1,98 @@
|
|||
<!-- title: Premiers pas avec Diaspora -->
|
||||
<!-- category: Humeur -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Comme pour beaucoup d'autres personnes, [l'initiative de
|
||||
Framasoft](https://framasphere.org) a été l'occasion de découvrir le réseau
|
||||
social **Diaspora** et son contrat respectueux des données de l'utilisateur.<!-- more -->
|
||||
|
||||
Mon expérience passée des réseaux sociaux est assez classique je pense dans
|
||||
notre milieu :
|
||||
|
||||
- J'ai un compte Twitter depuis 2007 que j'ai utilisé 1 ou 2 ans. Je postais un
|
||||
peu, puis à un moment je me suis senti plus concerné par mon e-Réputation et
|
||||
j'ai supprimé toutes mes photos de chats dont j'inondais la toile ;-) Je me
|
||||
suis encore servi du réseau pour suivre des sujets et des gens jusqu'à ce que
|
||||
je décroche et le compte est devenu dormant.
|
||||
- A la même époque j'ai ouvert un compte Facebook. L'histoire est plus courte ;
|
||||
je m'étais inscrit pour rester en contacts avec des gens géographiquement
|
||||
éloignées. Quelques mois plus tard, devant mon manque d'intérêt et fatigué de
|
||||
vérifier mes paramètres de diffusion suite à des changements réguliers des
|
||||
conditions d'utilisation, j'ai enlevé le peu que j'avais posté et j'ai supprimé
|
||||
mon compte officiellement.
|
||||
|
||||
De ces deux courtes expériences je me suis fait une idée, peut-être inexacte,
|
||||
des usages et des usagers de chacun des réseaux.
|
||||
|
||||
Facebook permet de rester en contact avec sa tribu, un peu comme [ce fameux
|
||||
objet connecté des années 90 précurseur du téléphone
|
||||
portable](http://www.nosannees90.com/dans-les-90s-le-tam-tam-et-le-tatoo-pour-garder-le-contact-avec-sa-tribu) :
|
||||
sa famille, les amis réels, les connaissances qu'on se noue autour de centres
|
||||
d'intérêt communs. Je pense que Google+ s'adresse aux même usages mais c'est
|
||||
une supposition, je n'ai pas eu l'occasion de tester. Ces usages concernent le
|
||||
plus grand nombre: rester en contact avec Tonton Jeannot et poster la photo du
|
||||
petit dernier, échanger des vidéos débiles avec des potes partis dans une autre
|
||||
région. C'est probablement sur ces réseaux qu'on va trouver le plus de
|
||||
futilités mais **c'est ça le social** : que fait-on dans un apéro à part
|
||||
échanger des anecdotes, se donner des nouvelles et raconter des blagues ? La
|
||||
même chose je pense et en cela ces réseaux jouent leur rôle. Et dans des pays
|
||||
où l'Internet à la maison et l'ordinateur personnel est un rêve, ces
|
||||
réseaux permettent de garder du lien entre les familles et les amis éloignés en
|
||||
allant au Cyber-Café quand on a 3 sous pour prendre des nouvelles et en donner.
|
||||
En cela, Facebook fait carton plein pour toucher le plus personnes et proposer
|
||||
une alternative Libre était crucial.
|
||||
|
||||
Twitter est assez différent. C'est plus un outil de communication pour diffuser
|
||||
de l'information de façon ciblée grâce aux fameux hashtags : un bel outil pour
|
||||
les Community Manager professionnels et en herbe.
|
||||
|
||||
### Mon premier bilan
|
||||
|
||||
Quand je me suis connecté à Diaspora et que j'ai lu un peu la FAQ, j'ai adoré
|
||||
le concept du tag *à la Twitter* mixé au réseau social plus classique *à la
|
||||
Facebook* où on peut poster ses photos. J'ai vu le meilleur des 2 mondes, la
|
||||
possibilité de créer des cercles (désolé Google y'a pas de brevet sur ce mot je
|
||||
pense) de connaissances et aussi de s'abonner à des tags pour suivre des sujets
|
||||
précis et découvrir de nouvelles personnes à suivre. Je suis quelques tag et
|
||||
cela m'a permis de découvrir quelques personnes intéressantes et retrouver ceux
|
||||
que je lis déjà en RSS et qui gravitent autour du Planet. Le concept de tag de
|
||||
Diaspora va même plus loin car on suit un tag donc la découverte s'enrichit en
|
||||
permanence par rapport à Twitter où il faut de temps lancer une recherche pour
|
||||
découvrir les nouveaux venus sur un thème donné.
|
||||
|
||||
Quatre semaines plus tard, le bilan est positif. Le réseau est sympathique à
|
||||
utiliser, les gens (du moins ceux que je suis) sont cordiaux, la version mobile
|
||||
du site permet de se connecter de son téléphone sans application spécique. Mais
|
||||
ce qui pèche, c'est le peu de contenu de mon flux alors que je suis des tag
|
||||
assez généraux.
|
||||
|
||||
### Comment faire grossir Diaspora ?
|
||||
|
||||
Si on utilise le réseau pour rester en contact avec sa tribu, la migration se
|
||||
fera par petites grappes. Untel part sur Diaspora et va attirer petit à petit
|
||||
(et sûrement difficilement) le noyau dur de ses connaissances. Difficilement
|
||||
car la majorité des gens ont un smartphone sous Android et des applications
|
||||
lourdes pour Facebook ou Twitter qui facilitent l'instantanéité: un clic pour
|
||||
partager une photo. Seul un barbu dégainera son valeureux téléphone Firefox
|
||||
pour ouvrir un navigateur sur Diaspora et ensuite naviguer sur son système de
|
||||
fichier pour trouver la photo à publier. Des bonnes applications mobiles sont
|
||||
nécessaires pour faire décoller le réseau.
|
||||
|
||||
Pour les pays émergents, Diaspora pourrait s'imposer par de la pub vers les
|
||||
utilisateurs finaux. Il faut aussi que les temps d'accès soient corrects, ce
|
||||
qui demande une multiplication des Pods et l'installation de Pods au plus près
|
||||
des utilisateurs.
|
||||
|
||||
Si on utilise le réseau pour faire de la veille technologique il faut trouver
|
||||
des arguments pour convaincre les poids lourds qui postent essentiellement sur
|
||||
Twitter et Google+ de poster aussi du Diaspora. Ces acteurs ne viendront pas
|
||||
pour la philosophie du réseau mais pour l'audience potentielle. Par exemple,
|
||||
Parleys publie des conférences techniques sur l'éco-système JAVA. Si on savait
|
||||
combien de personnes suivent le tag #java sur Diaspora ce serait un argument
|
||||
tangible pour convaincre ce site de publier aussi ses annonces sur Diaspora.
|
||||
C'est pareil pour le tag #python que je suis. Très peu de contenu alors que de
|
||||
gros agrégateurs de contenu publient sur Twitter. Peut-être que la possibilité
|
||||
de collecter des statistiques anonymes sur les utilisateurs du réseau Diaspora
|
||||
existe déjà ? Sans contenu, Diaspora restera un réseau de niche, une
|
||||
alternative à Facebook pour échanger des photos avec tata Jeanine mais pas un
|
||||
réseau qui fera venir les foules.
|
||||
80
posts/2014/2014-11-14-my-phone.md
Executable file
80
posts/2014/2014-11-14-my-phone.md
Executable file
|
|
@ -0,0 +1,80 @@
|
|||
<!-- title: Au fait... mon téléphone -->
|
||||
<!-- categories: Humeur Mobilité -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Cela fait longtemps que je n'ai pas parlé de mon téléphone.<!-- more --> J'ai connu les
|
||||
années très hétérogènes où chaque constructeur proposait son système
|
||||
d'exploitation. Puis est arrivée l'ère de la consolidation avec iOS sur iPhone
|
||||
et surtout Android. C'était logique et attendu par le marché. Et nous a permis
|
||||
d'avoir les smartphones hyper puissants et... hyper-couteux d'aujourd'hui. Moi
|
||||
j'ai toujours la nostalgie de cette époque pour sa diversité que ce soit des
|
||||
équipements ou des systèmes d'exploitation mobiles. C'est aussi mon goût du
|
||||
chaos qui parle et le fait avéré que je suis vieux.
|
||||
|
||||
Aujourd'hui tout téléphone est rectangulaire, le plus plat possible et le constructeur se
|
||||
démarque par deux éléments :
|
||||
|
||||
- la noblesse des matériaux utilisés (donc le positionnement en prix),
|
||||
- une décision cornélienne : le style des coins : carrés ou arrondis ?
|
||||
|
||||
Quelle prise de risque ;-) Mais où sont enterrés les téléphones à clapet et les
|
||||
systèmes exotiques ? Au fait, qui a eu un téléphone Bosch avec une fonction
|
||||
thermomètre (d'ambiance hein pas médical, le téléphone n'était pas IP6x) dans
|
||||
les années 2000 ? Moi : +1
|
||||
|
||||
Mon premier smartphone fut un [Nokia
|
||||
E61i](http://fr.wikipedia.org/wiki/Nokia_E61i). Il m'a beaucoup marqué, le
|
||||
système Symbian c'était cool et facilement bidouillable. Puis j'ai rêvé d'avoir
|
||||
un N900 avec Maemo, un système *GNU inside* avec un système Debian-like. le
|
||||
Libre allait étendre son emprise sur le monde de la mobilité. J'ai raté le
|
||||
cocher pour l'acheter, Nokia a jeté Maemo (leur plus grosse erreur), fin du
|
||||
rêve. Du coup j'ai rejoint le train Android avec un Motorola Milestone
|
||||
(coulissant avec clavier). Un bilan a été mitigé : toutes les applications du
|
||||
monde mais un système alors peu stable (c'était la 2.0) puis j'ai eu un ras le
|
||||
bol croissant de voir des téléphones semblables sortir chaque semaine avec le
|
||||
même OS. Je parle des années 2009-2011 quand Android a littéralement inondé le
|
||||
marché. Et pendant cette période, il m'apparaissait de plus en plus clairement
|
||||
que Android basé sur Linux c'est cool, mais Google, icône du Web à mes yeux
|
||||
depuis 15 ans, c'était de moins en moins cool pour la protection de sa vie
|
||||
privée.
|
||||
|
||||
Une envie de voir autre chose et une fixation sur les claviers physiques car
|
||||
je suis une quiche en tactile m'a amené chez BlackBerry pour un modèle Bold
|
||||
9780. Là j'ai retrouvé un OS beaucoup plus rustique, non tactile mais avec
|
||||
une richesse fonctionnelle qui mettait loin derrière Apple et Google en 2012.
|
||||
J'ai poussé ce téléphone dans ses retranchements et il ne m'a jamais trahi dans
|
||||
ma période de grand voyageur. Il est encore en état mais la batterie est
|
||||
fatiguée. Il a donc été décidé de le changer au printemps dernier.
|
||||
|
||||
J'étais tenté par Firefox OS mais il n'y avait pas encore de téléphone
|
||||
disponible en France. Mon inquiétude concernait les fonctionnalités. Mon mobile
|
||||
me sert aussi professionnellement donc un niveau minimum de fonctionnalité
|
||||
m'est nécessaire : point d'accès 3G, GPS (hors ligne et en ligne), calendrier
|
||||
partagé, accès à des bases de données de mots de passe Keepass , copier-coller
|
||||
intensif entre les applications. C'était encore un peu tôt pour Firefox OS.
|
||||
|
||||
Hors de question de partir sur Android et de jouer à degoogler l'appareil.
|
||||
L'iPhone est trop bridé. J'ai pensé à Windows Phone... marrant car Microsoft ce
|
||||
devrait être le mal pour un linuxien ;-) Mais le fait est que leur système est
|
||||
fluide, bien optimisé sur du matériel d'entrée/moyenne gamme. Certes il faut un
|
||||
ID Windows pour accéder au Store mais on n'a pas tout un écosystème imposé. Je
|
||||
me suis dit "pourquoi pas" puis je me suis intéressé au nouveau système
|
||||
BlackBerry 10 de RIM et j'ai replongé pour un téléphone 4G à clavier physique
|
||||
et écran tactile à moins de 200 euros, [le
|
||||
Q5](http://en.wikipedia.org/wiki/BlackBerry_Q5). Mon propos n'est pas d'en
|
||||
faire l'article mais de souligner que c'est un bon rapport qualité / prix et
|
||||
que le système BlackBerry 10 est intéressant et très bien conçu en reprenant
|
||||
les bonnes idées du passé, en repensant ingénieusement les *gestures tactiles*
|
||||
au lieu de copier ses concurrents: le système est basé sur le rachat de QNX
|
||||
et il a été développé en moins de 3 ans pendant une période où la société était
|
||||
à deux doigts de mettre la clef sous la porte. C'est une belle réussite
|
||||
technologique et humaine.
|
||||
|
||||
Ce téléphone répond à toutes mes attentes donc je suis paré pour un moment. Et
|
||||
je continue à suivre de près l'actualité de Firefox OS, les sorties de nouveaux
|
||||
modèles et les expérimentations (quelle application pour faire ceci, comment
|
||||
compiler la nouvelle version du sytème) dans la zone [Entraide
|
||||
Libre](http://www.blog-libre.org/ask/) de Blog Libre. Dans 2 ou 3 ans, je ne
|
||||
doute pas que le choix des téléphones Firefox OS sera étoffé, que le système
|
||||
sera plus riche et Firefox OS sera une option évidente pour moi, en accord avec
|
||||
mes convictions.
|
||||
120
posts/2014/2014-12-05-oracle-xe.md
Executable file
120
posts/2014/2014-12-05-oracle-xe.md
Executable file
|
|
@ -0,0 +1,120 @@
|
|||
<!-- title: Installer Oracle Express sur Centos -->
|
||||
<!-- category: GNU/Linux -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Oracle est la base de données phare de l'éditeur du même nom, utilisée pour des
|
||||
grosses applications et des gros volumes de données.<!-- more --> Toute une suite de
|
||||
produits de l'éditeur existe autour de la base pour administrer, optimiser,
|
||||
déployer... Oracle fournit aussi une version limitée de son produit pour les
|
||||
développeurs, il s'agit de **Oracle Express**. C'est une base qu'on va utiliser
|
||||
pour développer et distribuer de modestes applications ou pour mettre au point
|
||||
du code déployé sur des *vraies bases* Oracle en production. Les limitations
|
||||
sont les suivantes : un seul processeur exploité, 1 Go de RAM max utilisé et
|
||||
stockage de 11 Go de données maximum.
|
||||
|
||||
Oracle Express est proposée pour Ms Windows et **GNU/Linux en 64 bits** en
|
||||
paquet RPM. J'ai décrit ci-après l'installation type sur un serveur Centos. La
|
||||
procédure n'est pas complexe mais il y a quelques écueils qui justifient cet
|
||||
article.
|
||||
|
||||
J'ai effectué l'installation de base d'un Centos 6.6 en 64 bits. Un pré-requis
|
||||
à respecter, sinon Oracle refuse de s'installer, est la création d'une partition
|
||||
de swap au moins égale à 2x la quantité de RAM de la machine.
|
||||
|
||||
On télécharge Oracle Express depuis [le site
|
||||
officiel](http://www.oracle.com/technetwork/database/database-technologies/express-edition/downloads/index.html).
|
||||
On récupère un fichier ZIP qui contient le paquet RPM. On installe *unzip* sur
|
||||
Centos et le paquet *bc* nécessaire à l'installeur Oracle.
|
||||
|
||||
$ yum install unzip bc
|
||||
|
||||
Oracle a besoin que le nom du serveur (aka hostname) soit associé à une adresse
|
||||
IP. La solution simple est d'éditer le fichier */etc/hosts* du serveur et
|
||||
ajouter une entrée avec le nom du serveur et son adresse IP. Désormais, nous
|
||||
sommes prêt à démarrer l'installation. On dézippe l'archive et on installe
|
||||
paquet *rpm* :
|
||||
|
||||
$ unzip oracle-xe-11.2.0-1.0.x86_64.rpm
|
||||
$ rpm -ivh oracle-xe-11.2.0-1.0.x86_64.rpm
|
||||
|
||||
Quand le paquet *oracle-xe* est installé, il reste à configurer la base avec la
|
||||
commande *configure* du service *oracle-xe* :
|
||||
|
||||
$ /etc/init.d/oracle-xe configure
|
||||
|
||||
Oracle Database 11g Express Edition Configuration
|
||||
-------------------------------------------------
|
||||
This will configure on-boot properties of Oracle Database 11g Express
|
||||
Edition. The following questions will determine whether the database should
|
||||
be starting upon system boot, the ports it will use, and the passwords that
|
||||
will be used for database accounts. Press <enter> to accept the defaults.
|
||||
Ctrl-C will abort.
|
||||
|
||||
Specify the HTTP port that will be used for Oracle Application Express [8080]:
|
||||
|
||||
Specify a port that will be used for the database listener [1521]:
|
||||
|
||||
Specify a password to be used for database accounts. Note that the same
|
||||
password will be used for SYS and SYSTEM. Oracle recommends the use of
|
||||
different passwords for each database account. This can be done after
|
||||
initial configuration:
|
||||
Confirm the password:
|
||||
|
||||
Do you want Oracle Database 11g Express Edition to be started on boot (y/n) [y]:y
|
||||
|
||||
Starting Oracle Net Listener...Done
|
||||
Configuring database...Done
|
||||
Starting Oracle Database 11g Express Edition instance...Done
|
||||
Installation completed successfully.</enter>
|
||||
|
||||
En laissant les choix par défaut, on confime le port HTTP, le port du Listener,
|
||||
on choisit un mot de passe pour les comptes SYS et SYSTEM et on confirme le
|
||||
démarrage de la base au boot du serveur.
|
||||
|
||||
A ce stade, la base est démarrée et accessible localement. Le pare-feu de
|
||||
Centos est installé par défaut donc il faut ajouter des règles pour ouvrir l'accès
|
||||
distant ou plus brutalement désactiver le pare-feu avec la commande :
|
||||
|
||||
$ lokkit --disabled
|
||||
|
||||
L'accès local par SQLPlus nécessite de modifier l'environnement du Shell. On
|
||||
peut s'éviter de le faire à chaque coup en rajoutant ce qui suit à la fin du
|
||||
fichier */etc/profile* :
|
||||
|
||||
export ORACLE_SID=XE
|
||||
export ORACLE_BASE=/u01/app/oracle
|
||||
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/xe
|
||||
export ORACLE_TERM=xterm
|
||||
export NLS_LANG=FRENCH_FRANCE.utf8
|
||||
export TNS_ADMIN=$ORACLE_HOME/network/admin
|
||||
export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data
|
||||
export LD_LIBRARY_PATH=$ORACLE_HOME/lib
|
||||
export PATH=$ORACLE_HOME/bin:$PATH
|
||||
|
||||
Finalement, on peut créer un utilisateur *normal* que l'on
|
||||
utilisera dans notre développement depuis SQLPlus :
|
||||
|
||||
SQL> connect
|
||||
SQL> create user joelafrite idenfied by <password-for-joe>;
|
||||
SQL> grant CREATE SESSION, ALTER SESSION, CREATE DATABASE LINK, -
|
||||
CREATE MATERIALIZED VIEW, CREATE PROCEDURE, CREATE PUBLIC SYNONYM, -
|
||||
CREATE ROLE, CREATE SEQUENCE, CREATE SYNONYM, CREATE TABLE, -
|
||||
CREATE TRIGGER, CREATE TYPE, CREATE VIEW, UNLIMITED TABLESPACE -
|
||||
to joelafrite;
|
||||
|
||||
L'interface Web appelée "Application Express" permet d'effectuer les tâches
|
||||
courantes d'administration. Je ne peux pas en dire grand chose, je ne l'ai pas
|
||||
utilisé. Je me cantonne à SQLPlus et JDBC. Mais cette interface est accessible
|
||||
depuis un navigateur à l'adresse
|
||||
[http://localhost:8080/apex](http://localhost:8080/apex) avec les informations
|
||||
de connexion suivantes :
|
||||
|
||||
- Workspace: *ce que vous voulez*
|
||||
- Username: ADMIN
|
||||
- Pasword: *celui de l'utilisateur SYS et SYSTEM*
|
||||
|
||||
Les références pour écrire cet article :
|
||||
|
||||
- [http://www.davidghedini.com/pg/entry/install_oracle_11g_xe_on](http://www.davidghedini.com/pg/entry/install_oracle_11g_xe_on)
|
||||
- [https://stackoverflow.com/questions/18028942/oracle-xe-database-configuration-failed](https://stackoverflow.com/questions/18028942/oracle-xe-database-configuration-failed)
|
||||
- [http://blog.warp11.nl/2011/05/fully-freeware-apex-environment-i-centos-oracle-xe-11g](http://blog.warp11.nl/2011/05/fully-freeware-apex-environment-i-centos-oracle-xe-11g)
|
||||
98
posts/2014/2014-12-14-protectionnisme.md
Executable file
98
posts/2014/2014-12-14-protectionnisme.md
Executable file
|
|
@ -0,0 +1,98 @@
|
|||
<!-- title: Deviens-t-on protectionniste avec l'âge ? -->
|
||||
<!-- category: Humeur -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Le titre est un peu provocateur bien que je l'ai adouci en remplaçant
|
||||
"nationaliste" par "protectionniste".<!-- more --> Le nationalisme m'a toujours fait
|
||||
peur, je l'assimile à l'égoïsme, le repli sur soi, la peur de l'Autre.
|
||||
L'Histoire est jonchée d'horreurs perpétrées en son nom. C'est un
|
||||
peu injuste car la fierté du sentiment d'appartenance à un groupe n'est pas
|
||||
malsaine : supporter un club de sport, faire partie de la communauté des
|
||||
développeurs du langage Blurg ou des gamers du jeu Zygoom, je trouve ça naturel
|
||||
car les gens partagent une passion. Se sentir partie intégrante d'une
|
||||
communauté à l'échelle d'un village je comprends aussi. Au delà, à l'échelle
|
||||
d'une région ou d'un pays je ne suis plus. Qu'est-ce que je partage avec
|
||||
quelqu'un né à l'autre bout de la France ? Est-il plus proche de moi que
|
||||
l'italien à 3h de voiture de chez moi ? Pourquoi ? parce qu'on parle la même
|
||||
langue ? Parce qu'on est circonscrit par les mêmes frontières ?
|
||||
|
||||
A une époque où on noue plus de liens en ligne qu'IRL (In Real Life comme
|
||||
disent les jeunes) ces frontières semblent abstraites. Elles délimitent un
|
||||
espace avec des lois communes, soumis à une certaine fiscalité, protégé par des
|
||||
militaires et des policiers qui risquent leur vie (hommage à leur dévouement).
|
||||
Mais qu'est-ce qu'on partage réellement à l'intérieur de cet espace ?
|
||||
|
||||
Pendant des années j'aurais dit pas grand chose. Tourné vers le monde extérieur
|
||||
j'ai été engouffré consentant dans la spirale de la Mondialisation avec ses
|
||||
bons côtés : rencontrer des gens d'autres cultures, voyager, travailler avec 3
|
||||
fuseaux horaires. Et avec ses mauvais côtés : gagner plus sur le dos
|
||||
d'économies plus faibles donc de gens aussi capables que vous mais qui seront
|
||||
payés moins parce qu'un système économique a fixé les règles, travailler pour
|
||||
des sociétés dont le but est d'amasser pour reverser à des actionnaires. A
|
||||
cette époque je me sentais plus citoyen du monde que français.
|
||||
|
||||
Tout s'est calmé en 2008 quand une certaine crise a mis certains de nos clients
|
||||
devant les caméras, pointés du doigt à raison comme responsables de
|
||||
l'écroulement d'un système sous respiration artificielle depuis des années. Ma
|
||||
société a rassemblé ses forces, en se repliant, donc en laissant des gens sur
|
||||
le carreau, l'occasion pour moi de préparer un nouveau départ (merci Pôle
|
||||
Emploi j'ai réalisé à cette époque qu'on était bien couvert en France) et de
|
||||
faire un auto-bilan. Je suis reparti avec quelques idées phares : rester dans
|
||||
l'informatique et le logiciel, faire du logiciel plus utile, et renouer avec le
|
||||
Libre et GNU, une passion mise en sommeil 10 ans auparavant.
|
||||
|
||||
Quant à la fameuse crise, les gouvernements (donc les citoyens) ont payé la
|
||||
note, les casseurs du système ont fait leur mea culpa (plus jamais ça, moins de
|
||||
dérégulation, nécessité de transparence, plus de contrôle). Six ans plus tard,
|
||||
même en étant optimiste, il est évident que les mauvaises habitudes ont repris,
|
||||
que les lynchés d'hier ont pris du pouvoir, dans la vie politique européenne
|
||||
notamment. D'ailleurs, pour échapper à information atone et sans sous-titre des
|
||||
journaux télévisuels, je vous engage à lire [le blog de Paul
|
||||
Jorion](http://www.pauljorion.com/blog) => suivez le lapin blanc.
|
||||
|
||||
Pour ma part, depuis six ans je me fais plaisir et pas que professionnellement.
|
||||
Les fins de mois sont plus dures, comme pour le français moyen, ce français
|
||||
auquel je m'identifie désormais totalement mais je suis en accord entre ce que
|
||||
je fais et pour qui je le fais.
|
||||
|
||||
Pourquoi toute cette tirade et quel rapport entre le Libre et la Mondialisation ?
|
||||
|
||||
On critique beaucoup les américains mais leur sentiment national est une force
|
||||
pour protéger leur économie. Ils sont prêts à payer un peu plus cher pour
|
||||
acheter américain. L'initiative [Dégooglisons
|
||||
Internet](http://degooglisons-internet.org) a démarré comme un refus de vendre
|
||||
sa vie privée à des sociétés commerciales. Depuis quelques temps, je lis aussi
|
||||
des volontés individuelles de se passer d'Amazon afin de supporter les petites
|
||||
librairies, même si ça coûte quelques euros de plus. A titre personnel, je me
|
||||
force à limiter mes achats sur Internet et à faire le tour des enseignes
|
||||
locales auparavant pour leur donner leur chance. Je serais peiné que la FNAC
|
||||
disparaisse par exemple. Je privilégie [O2Switch](http://www.o2switch.fr) et
|
||||
[OVH](https://www.ovh.com/fr) pour mes hébergements et pas seulement par
|
||||
protection de mes données personnelles : je ne veux pas que mon pays devienne
|
||||
un désert.
|
||||
|
||||
20 ans en arrière l'open source c'était du code C dans un kernel et il fallait
|
||||
parler finlandais pour y comprendre quelque chose ;-) Aujourd'hui l'open source
|
||||
s'étend progressivemet à d'autres domaines : l'électronique (Arduino, les
|
||||
imprimantes 3D), l'art, l'architecture, l'agriculture (pour se protéger des
|
||||
brevets sur les semences). L'open source sert la contestation et le
|
||||
protectionnisme : pas celui du repli mais celui de la résistance. Quand on
|
||||
regarde les gens qui débarquent sur [Framasphere](https://framasphere.org) (au
|
||||
passage : fabuleuse idée que celle du tag #nouveauici et #nouvelleici),
|
||||
certains fuient la société de surveillance (Google, Facebook) mais beaucoup
|
||||
affichent aussi de l'intéret pour l'écologie, [les
|
||||
AMAP](https://fr.wikipedia.org/wiki/Association_pour_le_maintien_d%27une_agriculture_paysanne),
|
||||
les médecines alternatives (je n'ai pas parlé du système économique qui a pris
|
||||
le controle de la Santé et règle tout problème de façon médicamenteuse d'ailleurs).
|
||||
|
||||
Tous ces sujets se rejoignent et annoncent l'émergence d'une prise de
|
||||
conscience citoyenne mondiale : trouver des solutions localement avec moins
|
||||
d'impact sur l'environnement, préserver, gagner en autonomie et en liberté,
|
||||
répliquer ce qui marche ailleurs. Ca se passe ici mais aussi là bas dans les
|
||||
pays émergents grace à Internet comme vecteur de communication. Et le mouvement
|
||||
Open Source et le Libre ne sont rien de moins que les outils pour résister, se
|
||||
libérer, trouver des alternatives plus propres et moins chères dans de plus en
|
||||
plus de domaine. Le [DIY](https://en.wikipedia.org/wiki/Do_it_yourself) a
|
||||
beaucoup d'avenir et on n'a pas encore pris la mesure de l'impact de l'Internet
|
||||
sur le collectif mondial, de sa capacité à connecter les gens autrement et à
|
||||
propager les bonnes solutions.
|
||||
32
posts/2014/2014-12-20-bilan-herbergement.md
Executable file
32
posts/2014/2014-12-20-bilan-herbergement.md
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
<!-- title: Bilan 2014 de l'hébergement -->
|
||||
<!-- category: Hébergement -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Déjà une année que j'ai migré l'hébergement de mes services d'un serveur à la
|
||||
maison vers un hébergeur, en l'occurence OVH et son VPS Classic 2, sur un
|
||||
container OpenVz dédié.<!-- more -->
|
||||
|
||||
Les services hébergés sont à peu près les mêmes avec quelques nouveautés :
|
||||
|
||||
- ce blog statique et [son serveur de commentaires](http://blogduyax.madyanne.fr/du-nouveau-sur-pecosys.html),
|
||||
- une instance de Shaarli pour les favoris [merci SEB Sauvage](http://sebsauvage.net/wiki/doku.php?id=php:shaarli),
|
||||
- un lecteur de flux RSS : [Tiny Tiny RSS](http://tt-rss.org),
|
||||
- l'analyseur du trafic du blog : [Piwik](http://piwik.org),
|
||||
- mon cloud personnel [ownCloud](http://owncloud.org) auquel j'ai confié récemment le partage de quelques fichiers et de mon calendrier,
|
||||
- l'interface Web de consultation des e-mails [Roundcube](http://roundcube.net) mais les e-mails restent chez Gandi.
|
||||
|
||||
Dans le choix des distributions GNU/Linux, je reste fidèle :
|
||||
|
||||
- ArchLinux, ma distrib de coeur à la maison,
|
||||
- Debian sur mes serveurs personnels (Debian ou CentOS sur mes serveurs pro),
|
||||
- Fedora sur mon poste professionnel.
|
||||
|
||||
J'ai commencé à utilisé [Wallabag](https://www.wallabag.org) depuis quelques
|
||||
semaines, c'est la pièce qui me manquait dans mon processus de veille, entre le
|
||||
lien récupéré en vitesse et avant l'ajout du lien dans mes favoris Shaarli s'il
|
||||
en vaut la peine. Je l'utilise dans le cadre du projet
|
||||
[Framabag](https://www.framabag.org) mais je prévois d'installer ma propre
|
||||
instance d'ici peu.
|
||||
|
||||
Au niveau budget je suis en dessous de 7 euros par mois entre la location du
|
||||
VPS et le nom de domaine chez Gandi.
|
||||
Loading…
Add table
Add a link
Reference in a new issue