How to port a static Web App to Cozy Cloud

I wanted to try to install a static Web Application on my CozyBox. Unfortunately, Cozy is not able for now to serve static Web pages. So I wrote a tiny wrapper around my application. It proved to be very easy. Here’s the simple steps I took :

First, I created a npm package from my application, to reference it from the wrapper. It’s as easy as running npm init then npm publish inside your application repository. Then, the wrapper itself. Create a new directory, initialize the git repository and the package.json. Then dependencies to express.js and your application :

mkdir toto
cd toto
git init
npm init
npm install --save express
npm install --save myapp Your application should be in `node_modules/myapp`. All you have to do is use Express to serve this static directory :
var express = require('express');
var app  = express();
var port = process.env.PORT || 9250;
var host = process.env.HOST || "127.0.0.1";
// Serve static content
app.use(express.static(__dirname + '/node_modules/myapp'));
// Starts the server itself
http.createServer(app).listen(port, host, function() {
  console.log("Server listening to %s:%d within %s environment", host, port, app.get('env'));
});

Congrats, you’re done !

Now, publish the fruit of your efforts to Github, then go to the home of your CozyBox, and at the bottom the of application manager, just type the URL of the repository of your wrapper. Click install, wait a few seconds… Enjoy !

Bonus: Configure your application for Cozy

My application allows to synchronize data with a remoteStorage server. Good news, my CozyBox can host a remoteStorage server. So I’d like to let the application know the parameters to connect to this instance (in fact, all remoteStorage needs is a login).

So I hacked my application to use a default.js file with some default values. When building the application, I don’t concatenate it with others JavaScript files, so browser has to perform a specific query to fetch this file. Then, in the Express server, I just had to add a route to override this file with another one containing specific configuration values:

app.get('/js/default.js', function (req, res) {
  res.setHeader('Content-Type', 'text/javascript');
  res.sendFile('customConfig.js');
});

If you want to see the result of my week-end experiments, just take a look at the code of my Cozy Wrapper for Àlire, or try installing it inside your CozyBox

Bonus: Add an icon

In the package.json file of the wrapper, add the path of the icon of your application :

{
  "name": "cozy-myapp",
  "version": "0.0.1",
  "description": "CozyCloud wrapper for MyApp",
  "main": "server.js",
  "dependencies": {
    "myapp": ">= 0.0.1",
    "express": "^4.10.1"
  },
  "scripts": {
    "start": "node server.js"
  },
  "author": "Clochix",
  "license": "GPLv3",
  "icon-path": "myapp.png"
}

My (Cozy ?) Firefox Cloud OS

Il serait temps que je me souvienne que ce fatras est un carnet d’esquisse, et que je m’en serve pour esquisser des bribes d’inspirations pas finies, des fois que quelqu’un ait une idée pour faire avancer la réflexion.

Donc j’ai écrit une appli Web pour Firefox OS. Je dis « pour Firefox OS » car elle utilise un certain nombre de fonctionnalités qui n’existent pour l’instant que sur cette plateforme. Mais, comme je prêche que le Web est la plateforme universelle, je me suis senti obligé de faire en sorte qu’elle fonctionne également, en mode légèrement dégradé, dans tout navigateur moderne. J’ai utilisé pour cela divers types de rustines. Et je me dis que serait fort pratique un service fournissant des rustines à la demande, pour combler les manques actuels des agent utilisateurs Web.

Quelques exemples de telles rustines :

Disposer d’une meilleure connectivité réseau. Mon application intègre un lecteur de flux ATOM. Elle effectue donc des requêtes à destination de divers domaines. En Web classique, c’est interdit du fait de la politique d’origine identique. Dans Firefox OS, cette restriction peut être levée, en accordant explicitement à l’application le droit d’effectuer de telles requêtes. Pour les applications s’exécutant dans un autre environnement, lever la restriction est également faisable, en passant par un proxy CORS. Un tel proxy est l’exemple type de fonctionnalité qu’un service de rustines à la demande pourrait fournir.

Plus généralement, la plateforme Web n’a pas encore pour l’instant accès à de vrais sockets. C’est à dire qu’elle ne peut pas communiquer directement avec d’autres protocoles. Je travaille actuellement sur une application de messagerie, le client ne peut pas dialoguer directement avec des serveurs IMAP/SMTP, etc, et a donc besoin là encore d’un serveur intermédiaire. En attendant que l’API TCPSocket soit standardisée et implémentée, un service fournissant une rustine, par exemple au travers d’un pont Web Socket ↔ TCP Socket, serait le bienvenu.

La communication inter-applicative est aujourd’hui un des plus gros manques de la plateforme Web. Plusieurs propositions existent, Web Intents et Web Activities, mais ni la spécification ni les implémentations ne semblent promettre quelque chose d’utilisable dans un futur proche. En attendant, une solution utilisant un serveur et des Web Hooks me semble assez simple à mettre en œuvre et serait particulièrement utile. J’attend donc d’un service de rustines qu’il me propose une telle solution.

Parmi les fonctionnalités manquantes côté client, on peut encore par exemple citer un planificateur de tâches, capable de déclencher, à l’heure dite ou périodiquement, une fonction d’une application. Et bien évidemment, la synchronisation des données entre les instances d’une application installées sur plusieurs terminaux.

Je suis partisan d’un modèle où nos applications et nos données seraient au plus près de nous, idéalement directement dans nos terminaux. Hébergées sur chacun de nos périphériques disposant d’un navigateur. Malheureusement, une telle solution ne sera pas possible avant plusieurs années, le temps que les navigateurs implémentent les fonctionnalités qui leur manquent. En attendant, nos applications Web auront encore besoin de serveurs pour palier les manques des clients. Ces services, je ne les imagine évidemment qu’auto-hébergés, afin de pouvoir les modeler au plus proche de nos besoins et en garder le contrôle. J’imagine un monde où chaque navigateur aurait son serveur compagnon, les deux travaillant main dans la main.

Un tel projet existe, qui fournit aux applications Web les fonctionnalités aujourd’hui uniquement disponibles côté serveur : c’est Hoodie. Mais je me demande si à côté d’Hoodie, un autre service n’aurait pas sa place. Un service qui, outre ces rustines, hébergerait lui-même des applications Web statiques. Je me demande à quoi ressemblerait une version serveur de Firefox OS, si ce concept même de Firefox Server OS a un sens. Et je me demande si ce Firefox Cloud OS pourrait être un des usages de CozyCloud (le projet pour lequel je travaille). CozyCloud est un serveur hébergeant des applications Web et leur offrant des services transverses. On peut déjà installer un serveur remoteStorage dans sa CozyBox, pour synchroniser des données entre plusieurs instances d’une application. Porter sur Cozy un proxy CORS, Hoodie, ou des équivalents, ne devrait pas poser de problèmes. L’architecture actuelle utilise encore le paradigme d’applications mixtes, mi-client, mi serveur, mais rien n’interdit d’exposer les fonctionnalités spécifiques au serveur comme de réels services accessibles aux applications clientes. Cozy pourrait ainsi devenir le pendant « serveur » de Firefox OS : une plate-forme personnelle d’exécution d’applications Web offrant des fonctionnalités avancées.

Tout cela n’est qu’une intuition, et j’ai du mal à réaliser si je délire complètement ou si c’est une voie à creuser. Vos avis sont les bienvenus ☺

Message de service

J’ai la chance et la joie de rejoindre dans quelques heures la formidable équipe qui travaille sur le non moins formidable projet CozyCloud.

Jusqu’à présent, il est rare que j’ai pu être fier de mes réalisations professionnelles, et mon expression publique ne pouvait être confondue avec celle de mes employeurs. La situation change, car Cozy est un projet auquel je crois, dont la philosophie rencontre mes valeurs. Je vais essayer de rester relativement neutre dans mes billets et gazouillis, mais je ne crois guère en l’objectivité de la parole humaine, et préfère dire clairement d’où elle émane. Les opinions que j’exprimerai resteront les miennes, et ce carnet ne va pas se transformer en prospectus sponsorisé par Cozy. Il n’empêche, le projet est enthousiasmant, donc je ne m’interdirai pas non plus de dire régulièrement tout le bien que j’en pense.

Inutile de délayer davantage, vous voici prévenus, vous saurez faire la part des choses. Trinquons plutôt à ma nouvelle aventure au pays des nuages douillets ☺

Son bout de réseau

Ayant du mettre le nez hors de ma cave ces derniers jours, je me suis heurté douloureusement au principe de réalité, parfois appelé « état de la couverture 3G outre-périf », et ai eu la curiosité de jeter un œil à quelques spécimens de réseaux Wifi ouverts et gratuits découverts dans ces inhospitalières contrées. Je suis tombé sur moult formulaires où la gratuité se payait en informations personnelles, état civil, coordonnées électroniques et téléphoniques, etc. Au nom bien sûr de la « responsabilité », le gentil fournisseur du service ne voulant être tenu responsable de l’utilisation de son réseau pour consulter des sites pédo-djihadistes. Mécréant que je suis, je taxe évidemment cette aimable fable d’hypocrite camouflage à la volonté de collecter des informations pour des buts moins avouables, n’ayons pas peur des maux, marketings. Il n’empêche qu’avec l’amoncellement de règlements encadrant la ténue liberté de surfer, je pourrais entendre l’argument de la responsabilité. Des fournisseurs d’accès honnêtes et philanthropiques seraient sans doute tenus de demander de semblables renseignements. Et j’en suis venu à me demander si la meilleure solution pour tout le monde ne serait pas que ces réseaux en accès plus ou moins libres n’autorisent que la connexion à un VPN.

Demain, chacun disposera d’un serveur personnel. Serveur non au sens de machine physique mais de plate-forme simple à administrer et fournissant un certain nombre de services, comme le mail. Il me semblerait sain qu’un de ces services soit un VPN, c’est à dire qu’en plus d’un serveur, l’honnête internaute de demain possède également un bout de réseau. J’y vois plusieurs avantages :

  • en terme de responsabilité des intermédiaires techniques : ils fournissent juste une connexion physique entre un terminal et un réseau, ils ne peuvent être tenus responsable de l’usage de leur réseau. L’IP de leur point d’accès s’efface au profit de celle de l’internaute ;
  • en terme de neutralité : le fournisseur de la liaison physique entre mes terminaux et le cœur du réseau ne peut plus être tenté de contrôler ce que je fais, d’interdire par exemple le P2P ou la VOIP. Mes communications sont encapsulées dans le VPN, il ne peut à priori rien y voir. À chaque internaute de connecter son VPN à un fournisseur de transit conforme à ses attentes et valeurs ;
  • en terme évidemment de sécurité : il est facile de récupérer des identifiants de connexion à par exemple Free, et de profiter ainsi du réseau FreeWifi. En déplacement, c’est une solution très pratique. Mais créer un faux accès FreeWifi pour intercepter des identifiants, voire tout le trafic, était il y a quelques années à la porté de quiconque sait se servir d’un moteur de recherche. Plus généralement, les réseaux publics sont rarement sûrs, et à moins d’être compétent en informatique et sûr de la configuration de ses terminaux, je ne me risquerais pas à m’y connecter. Il est par contre assez simple de s’assurer que la connexion entre notre terminal et le VPN est raisonnablement sécurisée. On rendrait ainsi beaucoup plus sûr la connexion via des points d’accès publics et partagés ;
  • on peut imaginer une meilleure mutualisation des ressources. Privilégier les points d’accès publics plutôt que les boites individuelles, puisque l’intelligence n’est plus dans le points d’accès lui-même mais dans le VPN ;
  • la contrepartie est évidemment un risque accru de surveillance. En faisant passer toutes mes communications par un unique tuyau, je rend leur interception bien plus aisée.

Une telle architecture pose un risque évident en facilitant l’espionnage. Mais elle résout également un certain nombre de problèmes, et l’idée ne me parait pas complètement débile. Fournir les outils pour se connecter à un VPN devrait donc être, à mon humble avis, une priorité des développeurs de plateformes, tant côté client que serveur.

Enfumer Gmail

Vouloir se prémunir de l’espionnage par les agences gouvernementales est une chose, essayer de se protéger du profilage par les marchands du temple en est une autre qui n’a pas grand chose en commun. La première, pour être sérieuse, demande beaucoup de ressources et impose nombre de contraintes. Par exemple chiffrer systématiquement tous ses messages, et ne communiquer qu’avec des gens maitrisant eux aussi raisonnablement la cryptographie. Mais la plupart du temps, je voudrais juste éviter que Google ne connaisse tous mes sujets d’intérêt du moment, via l’analyse de mes échanges avec des correspondants dont la majorité utilise Gmail.

Ce matin, je voulais envoyer quelques nouvelles à un correspondant, utilisateur de Gmail, mais n’avais guère envie que Google apprenne avant l’officialisation ici la nature de mes prochaines aventures professionnelles. J’ai donc cherché à offusquer le contenu du message, pour le masquer aux trop curieux algorithmes de Google.

J’ai d’abord pensé à simplement encoder le contenu du message en ROT13 ou ROT47. De nombreux sites proposent des formulaires permettant d’encoder / décoder ce format. Mais il serait trop simple pour Google de détecter ce format et décoder de tels messages. J’ai donc décidé de passer par un algorithme de chiffrement symétrique utilisant une clé. Clé que j’envoie en clair avec le message, mais ce n’est pas un problème : le but n’est pas d’empêcher un humain qui intercepterait ma correspondance de la lire, mais de rendre moins probable la lecture du message par les algorithmes de Google, et donc l’exploitation des données qu’il contient pour accroitre les données qu’il possède sur moi.

J’ai fini avec deux petits bouts de code :

  • un formulaire HTML hébergé à une URL que je contrôle et qui permet de chiffrer / déchiffrer directement dans le navigateur grâce à la bibliothèque crypto-js ;
  • un script shell qui utilise openssl pour créer une clé et chiffrer avec elle les données en entrée, puis afficher la clé, le message chiffré et l’URL du formulaire ;

En pratique, pour envoyer mon message, je l’ai comme à l’accoutumé composé dans Vim, puis j’ai sélectionné le texte que je voulais chiffrer, appelé via un raccourci mon script, et ainsi obtenu un message qui ressemblait à :


Pour lire ce message, copiez son contenu dans le formulaire sur http://url.de/monformulaire#U2FsdGVkX1+cOIz7zzahV+WoB5VywEECppjXMsMo0OUOhTTdNWFCDxbs3sdo5rthB/Y0CEdZdSg9c3ziwMZxSewInrfrTYnzSTygelNltyDgxXNgm9geYimxH+W9zgDK
Mot de passe : coucou

Message :

U2FsdGVkX1+cOIz7zzahV+WoB5VywEECppjXMsMo0OUOhTTdNWFCDxbs3sdo5rthB/Y0CEdZdSg9c3ziwMZxSewInrfrTYnzSTygelNltyDgxXNgm9geYimxH+W9zgDK


En cliquant sur le lien, mon correspondant arrive sur le formulaire pré-rempli où il ne lui reste plus qu’à saisir le mot de passe pour déchiffrer le message. Le même formulaire lui permet également de créer un texte avec la même sémantique, qu’il n’aura pour me répondre qu’à coller dans le corps de son message.

Je conviens aisément que cela n’est pas du tout ergonomique, et aisé à contourner. Mais ça me semble simple d’utilisation, à la portée de n’importe qui, et évite que les algorithmes de Google ne lisent mes messages.

Peut-être, dans nos réflexions sur la sauvegarde d’un peu de mystère et d’intimité, devrions-nous aussi réfléchir au concept de niveau raisonnable de brouillard pour une situation donnée.

Fork me on GitHub