Blog de dada

DevOps, bidouilleur et routard plein de logiciels libres

Cloud

De retour du FOSDEM 2019

Rédigé par dada / 07 février 2019 / Aucun commentaire


Qu'on aime ou pas cet événement, la Réunion Européenne des Développeurs de Logiciels Libres et Open Source est devenue mon week-end préféré de l'année. Ou presque.
C'est toujours avec un plaisir fou que je me retrouve entouré des gens avec qui je ne peux discuter qu'à travers un écran le reste de l'année : du suisse, de l'allemand, du français, du finlandais et, nouveauté 2019, un américain ! Bref, des copains, trop d'anglais, des bières belges et des discussions jusqu'à pas d'heure.

Cette année et contrairement aux autres fois, j'ai réussi à assister à des conférences et à boire de la bière avec modération ! Je vous assure que ce n'est pas une mince affaire quand on connaît le talent de nos amis belges en matière de brasserie. Le vin est à la France ce que la bière est à la Belgique !

Voici un aperçu de ce que j'ai vu. Tout est en anglais et je ne crois pas qu'il existe un moyen de mettre des sous-titres. Si la langue d'Ed Sheeran n'est pas votre fort, passez votre chemin.

Ceph storage with Rook : Running Ceph on Kubernetes


Je connaissais déjà la bête et vous êtes en plein dedans si vous lisez cet article. Je pensais pouvoir découvrir deux ou trois trucs mais la démonstration qui devait être faite à la fin de la présentation n'a pas pu se faire : souci d'écran.

Loki - Prometheus for logs


Sur celle-là, j'ai carrément jubilé ! Ce truc a l'air vraiment super sympa. J'ai déjà essayé de le faire tourner dans mon cluster mais ce n'est pas vraiment stable. En plus clair, ça fait tomber les nodes un par un à cause d'une consommation de mémoire vive ahurissante.

ActivityPub Panel

 

Assez inévitable quand on est à fond dans le Fédiverse : la table ronde autour d'AP. C’était intéressant et je vous encourage à la regarder même si Chris Webber et son accent américain fatiguent rapidement les oreilles.

Matrix in the French State

 

Assister à une conférence qui parle à la fois de Matrix et de l'État Français, je ne pouvais pas rater ça ! C'était fichtrement intéressant, même si le bonhomme s'est amusé à comparer l'ANSSI à la NSA...

The Cloud Is Just Another Sun

 

Je ne savais pas trop à quoi m'attendre en allant voir cette conférence. Faut dire que j'avais pas totalement lu le descriptif. On y apprend qu'il faut se méfier du Cloud. Je vous invite vivement à la regarder, le mec est clair, et à vous forger une opinion sur le sujet.

Pour le lolz

On est allé, avec les gars de Feneas, voir la conférence autour du réseau social basé sur la blockchain : Hey. Pas grand chose à en dire. C'était technique et très concentré autour de la chaîne de blocs. Je n'ai pas compris grand chose.

Bref

Des litres de bières, des rencontres, des sujets qui font du bien au cerveau et surtout, mais surtout, des gens avec qui on n'arrive jamais à capter : c'est ça le FOSDEM, mon FOSDEM, que j'aime tant !

Merci aux organisateurs et à l'année prochaine !

Nextcloud, PHP-FPM, Nginx et Kubernetes

Rédigé par dada / 14 janvier 2019 / 7 commentaires




Ma première installation de Nextcloud dans Kubernetes était basée sur l'image Docker contenant Apache2. Aucun souci notable au niveau de la synchro des agendas, des fichiers ou encore des contacts. Par contre, la génération des miniatures des photos s'est révélée être un drame : Apache s'emballait et entraînait le nœud sur lequel il tournait avec lui, dans la tombe. Il me fallait une solution, j'ai donc décidé de changer de conteneur et de prendre celui basé sur PHP-FPM.

Un pod avec deux conteneurs

On entend souvent la rumeur racontant qu'un pod ne contient qu'un conteneur. C'est souvent vrai, mais c'est aussi faux. Dans l'exemple qui va suivre, le pod gérant Nextcloud contiendra le conteneur officiel de Nextcloud et un conteneur Nginx.

Contexte

Pour suivre, sachez que mon cluster, celui grâce auquel vous lisez ces quelques lignes, gère son système de fichier avec Rook, dont j'ai déjà parlé ici. Mes nœuds sont chez Hetzner, ce sont des CX21, du cloud public donc, et mes services sont exposés en NodePort derrière un Nginx configuré en LoadBalancer. Maintenant que vous savez ça, on peut y aller.

Le Deployment

On va commencer par balancer le Yaml qui marche :
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextcloud-deployment
spec:
  selector:
    matchLabels:
      app: nextcloud
  replicas: 1
  template:
    metadata:
      labels:
        app: nextcloud
    spec:
      containers:
      - name: nginx
        image: nginx:1.15
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
        - name: pv-nextcloud
          mountPath: /var/www/html
        lifecycle:
          postStart:
            exec:
             command: ["bin/sh", "-c", "mkdir -p /var/www/html"]
      - name: nextcloud
        image: nextcloud:14.0-fpm
        ports:
        - containerPort: 9000
        volumeMounts:
        - name: pv-nextcloud
          mountPath: /var/www/html
        resources:
          limits:
            cpu: "1"
      volumes:
      - name : nginx-config
        configMap:
           name: nginx-config
      - name: pv-nextcloud
        flexVolume:
          driver: ceph.rook.io/rook
          fsType: ceph
          options:
            fsName: myfs
            clusterNamespace: rook-ceph
            path: /nextcloud2

Il n'y a pas le Service associé pour la simple et bonne raison que chacun fait comme il le veut. Si vous êtes chez DigitalOcean, OVH ou chez un des GAFAM qui propose du k8s, vous aurez un LoadBalancer qui va bien. Si vous êtes comme moi, vous êtes réduit à faire du NodePort.

Ce qu'il faut comprendre

Vous remarquerez qu'il y a deux conteneurs : Nginx et Nextcloud-FPM. Nginx écoute sur le port 80 et va router le trafic à travers vers le port 9000 du conteneur de Nextcloud.

Nginx

      - name: nginx
        image: nginx:1.15
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
        - name: pv-nextcloud
          mountPath: /var/www/html
        lifecycle:
          postStart:
            exec:
             command: ["bin/sh", "-c", "mkdir -p /var/www/html"]
On va faire gober à Nginx deux points de montage : sa configuration et les sources de Nextcloud. Sans les sources de l'application, Nginx ne pourra pas avoir accès aux fichiers PHP, et ne servira donc à rien. On va donc prendre le point de montage originalement dédié à Nextcloud pour le monter une deuxième fois dans un deuxième conteneur, celui de Nginx.

Lifecycle

Remarquez la présence de la section lifecycle, elle permet d’exécuter ce que vous voulez au démarrage du conteneur. Quand j'apprenais à me servir de ce couple, je ne comprenais pas pourquoi Nginx ne voulait pas correctement fonctionner. J'ai passé du temps à comprendre que le conteneur Nginx et le conteneur Nextcloud n'avaient pas le même docRoot :
  • Nginx : /srv/html
  • Nextcloud : /var/www/html
Comprenez que les requêtes Nginx allaient chercher des fichiers dans /srv/html/blabla.php quand Nextcloud annonçait la présence de ses sources dans /var/www/html/blabla.php. Le bordel.

C'est là que je n'ai trouvé pas idiot l'idée de créer le chemin manquant au démarrage du pod avec un postStart. Du coup, j'avais Nginx et Nextcloud au diapason. Il est sans doute possible de configurer Nginx pour surcharger son docRoot, mais c'était l'occasion de jouer avec des commandes en amont de la création d'un conteneur.

Les deux points de montage

On a donc un point de montage pour les sources de Nextcloud :
        - name: pv-nextcloud
          mountPath: /var/www/html
Et un point de montage pour la configuration de Nginx :
        - name: nginx-config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf

Là aussi, j'ai perdu un peu de temps avant de comprendre qu'il fallait balancer toute la configuration de Nginx et pas seulement ce que j'ai l'habitude de mettre dans les sites-enabled. C'est du moins à faire quand on écrase le nginx.conf du pod. En y réfléchissant, c'est sans doute plus simple de modifier le point montage pour n'ajouter qu'un fichier dans le fameux sites-enabled.

Pour gérer la configuration de Nginx, je passe par une ConfigMap :
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
data:
  nginx.conf: |
    worker_processes  1;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;

    events {
        worker_connections  1024;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;
        #tcp_nopush     on;

        keepalive_timeout  65;

        #gzip  on;

        server {
            listen 80;

            add_header X-Content-Type-Options nosniff;
            add_header X-XSS-Protection "1; mode=block";
            add_header X-Robots-Tag none;
            add_header X-Download-Options noopen;
            add_header X-Permitted-Cross-Domain-Policies none;
            add_header Referrer-Policy no-referrer;

            root /var/www/html;

            location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
            }

            location = /.well-known/carddav {
                return 301 $scheme://$host/remote.php/dav;
            }
            location = /.well-known/caldav {
                return 301 $scheme://$host/remote.php/dav;
            }

            # set max upload size
            client_max_body_size 10G;
            fastcgi_buffers 64 4K;

            # Enable gzip but do not remove ETag headers
            gzip on;
            gzip_vary on;
            gzip_comp_level 4;
            gzip_min_length 256;
            gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
            gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

            location / {
                rewrite ^ /index.php$request_uri;
            }

            location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
                deny all;
            }
            location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
                deny all;
            }

            location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
                fastcgi_split_path_info ^(.+\.php)(/.*)$;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
                # fastcgi_param HTTPS on;
                #Avoid sending the security headers twice
                fastcgi_param modHeadersAvailable true;
                fastcgi_param front_controller_active true;
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_intercept_errors on;
                fastcgi_request_buffering off;
            }

            location ~ ^/(?:updater|ocs-provider)(?:$|/) {
                try_files $uri/ =404;
                index index.php;
            }

            # Adding the cache control header for js and css files
            # Make sure it is BELOW the PHP block
            location ~ \.(?:css|js|woff|svg|gif)$ {
                try_files $uri /index.php$request_uri;
                add_header Cache-Control "public, max-age=15778463";
                add_header X-Content-Type-Options nosniff;
                add_header X-XSS-Protection "1; mode=block";
                add_header X-Robots-Tag none;
                add_header X-Download-Options noopen;
                add_header X-Permitted-Cross-Domain-Policies none;
                add_header Referrer-Policy no-referrer;

                # Optional: Don't log access to assets
                access_log off;
            }

            location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
                try_files $uri /index.php$request_uri;
                # Optional: Don't log access to other assets
                access_log off;
            }
        }

    }
Eh oui, il y a tout dedans. Ça déforme l'affichage de ce billet, m'enfin. C'est une configuration Nginx classique.

On peut quand même s'arrêter sur la configuration du fastcgi_pass : il tape sur le 127.0.0.1 et le port 9000 du conteneur Nextcloud. Je n'ai pas encore gratté pour comprendre le pourquoi du comment mais je suppose que les deux conteneurs tournant dans le réseau du pod, ils se comportent comme deux services dans une seule et même machine. À confirmer.

On apply tout ça

Attention ! Avant de balancer le Deployment, balancez le yaml de la ConfigMap. Sans ça, Nginx ne chargera pas votre configuration !
dada@k8smaster1:~$ kubectl apply -f configmap.yaml
dada@k8smaster1:~$ kubectl apply -f nextcloud.yaml
Si tout se passe bien, vous devriez pouvoir voir ça :
dada@k8smaster1:~$ kubectl get pods
nextcloud-deployment-d6cbb8446-87ckf   2/2     Running   0          15h
Remarquez que Kubernetes vous montre bien qu'il y a deux conteneurs dans ce pod : 2/2.

Pour aller plus loin

Je ne parle pas des vérifications de l'état des conteneurs. Il faudrait placer des sondes liveness et readness pour parfaitement vérifier l'état des conteneurs. Sans ça, si l'un des services tombe, Kubernetes ne sera pas forcément en mesure de le détecter et de relancer le pod.
Il est aussi possible, pour respecter le concept de micro-service, de ne pas concaténer deux conteneurs dans un seul pod mais de faire un pod par conteneur et des services associés. Ça demande plus de travail pour un résultat qui, dans mon cas, n'apporte pas grand chose.

Big Brother habite Place Beauvau ? Exégèse en libertés

Rédigé par dada / 04 avril 2018 / Aucun commentaire


Avec la sortie de Peertube , on commence à voir fleurir un peu partout du contenu qu'il fait bon voir en dehors de Youtube, et dans ce bon contenu, il y a la dernière vidéo de la chaîne Thinkerview : Big Brother habite Place Beauvau ? Exégèse en libertés.

Je vous la lâche ici pour vous inviter à la regarder :


Elle fait du bien au cerveau. C'est vraiment de la bonne bouffe, pour parler simple. On y entend parler de Facebook, d'économie du numérique, de droit, d'House of Cards, d'Europe, de Neutralité du Net, de bouquins, d'histoire, de droit, de vie privée, de bataille à la David contre Goliath, de mensonges et j'en passe. C'est presque 2h de plaisir.

Avec elle, un toot qui n'en résume pas son contenu mais qui reprend la dernière intervention de Benjamin Bayart :


Android, Nextcloud, son application Contacts, DAVdroid et l'erreur 15

Rédigé par dada / 07 septembre 2016 / 2 commentaires


Il y a des trucs qui m'ont gonflé ces derniers jours et cette erreur en fait partie :
java.lang.IllegalStateException: [Error 15] PREF parameter value is malformed 
Pas très claire, pas super bavarde, y'a pas pire comme type d'erreur, surtout quand on aime bien gérer son propre serveur pour pouvoir profiter de la synchronisation des contacts de son téléphone avec son instance Nextcloud. Bon, je triche un peu, c'est une erreur Java, c'est plus verbeux que ça, mais j'allais pas déformer ce billet avec son blabla.
J'ai commencé par faire les trucs de base : sauvegarder mes contacts sur le téléphone, vider le carnet d'adresses, vider l'application Contacts de son contenu et lancer une synchronisation après avoir fait ce grand ménage. Rien à faire, ça pétait toujours. #Tristitude

En traînant sur l'internet mondial, j'apprends qu'il y a plusieurs versions du protocole VCard, le format ouvert qui permet l’échange des cartes visites, ou dit plus clairement, l’échange de nos contacts du téléphone. C'est lui que CardDav manipule. On ne va pas rentrer les détails mais, comme tout machin avec une RFC, une ligne de conduite claire, faut filer droit. A priori, les applications qui se cognent la manipulation des VCard savent ce qu'elles font, ou pas.
Je ne sais pas vraiment depuis quand la valeur PREF traîne dans les informations de mes contacts, mais ce merdeux est presque partout et il est mal utilisé. Exemple :
BEGIN:VCARD
VERSION:2.1
N:Johansson;Scarlett;;;
FN:Scarlett Johansson
TEL;CELL;PREF:+42612345678
END:VCARD
Remarquez bien ce maudit PREF qui se balade entre CELL et le numéro de téléphone : il n'a rien à faire ! La ligne TEL doit contenir les informations relatives au 06 du contact, ce que le squatteur ne comprend pas.
Bref, pour corriger la synchro avec Contacts de Nextcloud via DAVdroid, il suffit de le faire sauter. C'est comme ça que j'ai fait, ce n'est sans doute pas la façon la plus propre de faire, mais ça m'a défrustré.

La solution la plus simple, si vous êtes sous GNU/Linux et que vous savez un tout petit peu vous servir d'un terminal, c'est de :
  • Extraire son carnet d'adresse au format VCF
  • Ouvrir un terminal
  • Exécuter la commande suivante :
 sed -i "s/TEL;CELL;PREF:/TEL;VOICE:/g" contacts.vcf 
Avec cette simple manipulation, vous venez de faire sauter la totalité des occurrences de PREF; de votre carnet d'adresse en la remplaçant par VOICE;, qui ne pose pas de souci. Notez qu'il doit existe d'autre formats corrects pour la ligne TEL, vous pouvez fouiller si l'envie vous prend.
Enfin, vous pouvez tranquillement réimporter ce fichier édité dans le carnet d'adresse de votre téléphone et dans Nextcloud, ça marchera tout seul, sans cette fichue error 15.

Nextcloud 9 disponible, voyons voir

Rédigé par dada / 16 juin 2016 / 14 commentaires




L'un des derniers grand chambardement du monde libre de ces derniers temps est la création de Nextcloud par les fondateurs d'ownCloud. Ce bouleversement n’était attendu par personne, sauf si on s’intéressait aux mouvements des développeurs historiques d'ownCloud qui ont presque décidé de quitter le navire au même moment.

Bref, ownCloud perd ses fondateurs, met en marche une fondation et communique tant bien que mal pendant que ses papas foutent le camp pour pondre Nextcloud. Je ne sais pas pour vous, mais moi, je migre vers Nextcloud.
Les promesses de ce dernier sont plutôt belles : fournir les fonctionnalités de la version professionnelle d'ownCloud nativement, sans devoir souscrire à une quelconque offre de support. Avec ça, comme ils le disent, on devrait avoir un cloud personnel plus efficace et, surtout, dépourvu des magouilles qui servaient à différencier la version communautaire de la version payante d'ownCloud.

Du coup, avec la sortie de leur première version, le moment est venu de passer le cap et d'y aller. Mais d'abord, un peu de méfiance et de bon sens : ce genre de manipulation peut ne pas se passer comme prévu surtout si vous trainez quelques applications farfelues avec vous. Personnellement, j'ai une application qui ne m'a pas permis de faire la migration. Comme je devais faire du ménage et nettoyer mon serveur, j'ai sauté sur l'occasion pour repartir sur une installation de mon cloud personnel bien plus propre que l'ancienne.

Pour celles et ceux qui voudraient se lancer dans la bascule, voici les manipulations à faire pour migrer d'OC à NC :
  • Faire des sauvegardes des fichiers (/data) et du config.php
  • Désactiver les applications tierces
  • Remplacer la totalité des fichiers d'ownCloud par ceux de Nextcloud
  • Mettre en place le config.php et le /data d'ownCloud dans Nextcloud
  • Lancer la procédure de mise à jour automatique
Et si tout va bien, après quelques minutes d'attente, le temps que la base de données soit mise à jour, Nextcloud apparait sous vos yeux. C'est bleu clair, un peu vif, mais on s'y fait.

Comme c'est encore une copie presque conforme, on ne s'y perd pas. J'y retrouve mes applications indispensables, c'est tout bon. Il ne reste plus qu'à rebalancer mes fichiers et tout sera de nouveau fonctionnel comme si de rien n’était.

Actuellement, seule l'application Android existe au nom de Nextcloud, pour le reste, comme le client de synchronisation du bureau, celui d'ownCloud est parfaitement fonctionnel.

Ce changement n'est pas encore très important d'un point de vue technique. C'est surtout un choix : celui de suivre les créateurs qui n'assument plus de passer par une division entre les utilisateurs commerciaux et les autres pour vivre de leur travail. Perso, j'y crois, j'aime ce genre d’idées.

Bon, maintenant, il faut que je dégage quelques stickers... /me soupire