Etherpad Lite

Introduction

Vous souvenez-vous de Google Wave ? Mais si, ce truc la :

Ce service, sorte de mix entre mail, chat et réseaux sociaux qui avait fait beaucoup de bruit à sa sortie (et qui est depuis mort et enterré) introduisait une fonction qui faisait rêver à l'époque : la possibilité d'écrire des messages de manière collaborative, en voyant chaque caractère tapé par votre collaborateur en direct.

En fait, Google n'a pas été le premier à proposer une telle fonctionnalité : EtherPad, sorti un an auparavant, le proposait déjà. Il n'a pas eu le temps de se faire beaucoup connaitre du public car il fut très vite racheté par Google, en vue d'implémenter certaines de ses technos dans Google Wave et Google Docs.

Ce rachat a entraîné la libération du code source d'Etherpad. Depuis quelques années maintenant, de nombreux services proposent d'ouvrir des "Pads" et d'y écrire du contenu en collaborant. Je pense notamment à l'excellent Framapad, maintenu par Framasoft, mais il y en a bien d'autres.

Framapad

Quelle est l'utilité ?

Une question qui revient souvent : à quoi sert Etherpad ? Je vois ça comme un mix du défunt Google Wave et Pastebin. La différence est qu'il est possible, en l'installant sur votre serveur personnel, de garder la main sur vos données.

Voici à quoi ressemble l'interface :

Création ou ouverture d'un Pad

Édition d'un Pad

Import/Export du Pad

Changement de nom et de couleur d'utilisateur + le chat du Pad

Etherpad vs Etherpad Lite

Etherpad Lite, c'est Etherpad sans sucre ? Non, mais il est vrai qu'Etherpad est plutôt gourmand en ressources, à priori à cause du fait qu'il repose entre autre sur Scala et Java. Etherpad Lite est une réécriture quasi-complète d'Etherpad, en utilisant des technologies bien plus légères que son prédécesseur, notamment Node.js. Par conséquent, là où Etherpad occupait 257 Mo de RAM à froid, Etherpad Lite ne consomme que 16 Mo.

Etherpad vs Etherpad Lite

Installation d'Etherpad Lite

Nous allons installer Etherpad Lite sur une Debian Squeeze, avec Apache en tant que reverse proxy (via le mod_proxy).

Avant tout, installons des dépendances :

# aptitude install gzip git-core curl python libssl-dev pkg-config build-essential

On installe node.js :

$ wget http://nodejs.org/dist/v0.6.15/node-v0.6.15.tar.gz
$ tar xvf node-v0.6.15.tar.gz
$ cd node-v0.6.15/
$ ./configure
$ make
# make install

On installe etherpad-lite et ses dépedances.

$ git clone 'git://github.com/Pita/etherpad-lite.git'
$ cd etherpad-lite/bin/
$ ./installDeps.sh

Enfin, on lance Etherpad Lite.

./run.sh

Etherpad lite se lance sur votre serveur, par défaut sur le port 9001. Depuis votre serveur, vous pouvez y accéder via l'adresse http://localhost:9001.

Configurer le reverse-proxy Apache

Pour accéder à votre instance d'Etherpad Lite à travers le port 80, nous pouvons faire du reverse-proxy avec Apache. Dans /etc/apache2/sites-available/, créer un fichier etherpad et le comme configurer comme ceci :

Update: Visiblement cette configuration n'est plus fonctionnelle avec les dernières versions d'etherpad, comme le signale quenneni dans son commentaire.

<VirtualHost *:80>
        ServerAdmin support@example.org
        ServerName etherpad.example.com
        CustomLog /var/log/apache2/etherpad_access.log combined
        ErrorLog /var/log/apache2/etherpad_error.log
        ErrorLog syslog:local2

        <IfModule mod_proxy.c>
           
            # The following allows "nice" urls such as https://etherpad.example.org/padname
            RewriteEngine On
            RewriteRule /p/*$ http://etherpad.example.com/ [NC,L]
            RewriteCond %{REQUEST_URI} !^/p/
            RewriteCond %{REQUEST_URI} !^/static/
            RewriteCond %{REQUEST_URI} !^/socket.io/
            RewriteCond %{REQUEST_URI} !^/ep/
            RewriteCond %{REQUEST_URI} !^/minified/
            RewriteCond %{REQUEST_URI} !^/api/
            RewriteCond %{REQUEST_URI} !^/ro/
            RewriteCond %{REQUEST_URI} !^/error/
            RewriteCond %{REQUEST_URI} !^/jserror
            RewriteCond %{REQUEST_URI} !/favicon.ico
            RewriteCond %{REQUEST_URI} !/robots.txt
            RewriteRule ^/+(.+)$ http://etherpad.example.com/p/$1 [L]

            ProxyVia On
            ProxyRequests Off
            ProxyPass / http://127.0.0.1:9001/
            ProxyPassReverse / http://127.0.0.1:9001/
            ProxyPreserveHost on
            <Proxy *>
                Options FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
            </Proxy>
        </IfModule>
</VirtualHost>

La même configuration, avec SSL :

<IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerAdmin support@example.org
        ServerName pad.jeyg.info
        CustomLog /var/log/apache2/etherpad_access.log combined
        ErrorLog /var/log/apache2/etherpad_error.log
        ErrorLog syslog:local2

        SSLEngine on

        SSLCertificateFile    /etc/ssl/certs/webserver.crt
        SSLCertificateKeyFile /etc/ssl/private/webserver.key

        <IfModule mod_proxy.c>
           
            # the following allows "nice" urls such as https://etherpad.example.org/padname
            RewriteEngine On
            RewriteRule /p/*$ https://etherpad.example.com/ [NC,L]
            RewriteCond %{REQUEST_URI} !^/p/
            RewriteCond %{REQUEST_URI} !^/static/
            RewriteCond %{REQUEST_URI} !^/socket.io/
            RewriteCond %{REQUEST_URI} !^/ep/
            RewriteCond %{REQUEST_URI} !^/minified/
            RewriteCond %{REQUEST_URI} !^/api/
            RewriteCond %{REQUEST_URI} !^/ro/
            RewriteCond %{REQUEST_URI} !^/error/
            RewriteCond %{REQUEST_URI} !^/jserror
            RewriteCond %{REQUEST_URI} !/favicon.ico
            RewriteCond %{REQUEST_URI} !/robots.txt
            RewriteRule ^/+(.+)$ https://etherpad.example.com/p/$1 [L]

            ProxyVia On
            ProxyRequests Off
            ProxyPass / http://127.0.0.1:9001/
            ProxyPassReverse / http://127.0.0.1:9001/
            ProxyPreserveHost on
            <Proxy *>
                Options FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
            </Proxy>
        </IfModule>
    </VirtualHost>
</IfModule>

Il ne reste plus qu'à activer les modules mod_proxy et proxy_http (ainsi que mod_rewrite et mod_ssl si ce n'est pas déjà fait) puis activer le virtualhost.

# a2enmod mod_proxy proxy_http
# a2ensite etherpad
# /etc/init.d/apache2 reload

Après configuration de votre zone DNS, vous pouvez accéder à Etherpad Lite via l'adresse que vous avez spécifié à Apache. Ici, http(s)://etherpad.example.org.

Script Init

Vous préférez certainement qu'Etherpad Lite puisse être géré comme un service, ce qui est beaucoup plus viable pour une mise en production. Voici un exemple de script init (sysvinit), à personnaliser, à placer dans /etc/init.d/etherpad-lite.

#!/bin/sh

### BEGIN INIT INFO
# Provides:          etherpad-lite
# 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
# Short-Description: starts etherpad lite
# Description:       starts etherpad lite using start-stop-daemon
### END INIT INFO

PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin"
LOGFILE="/var/log/etherpad-lite/etherpad-lite.log"
EPLITE_DIR="/usr/share/etherpad-lite"
EPLITE_BIN="bin/safeRun.sh"
USER="your-user"
GROUP="your-user"
DESC="Etherpad Lite"
NAME="etherpad-lite"

set -e

. /lib/lsb/init-functions

start() {
  echo "Starting $DESC... "
 
    start-stop-daemon --start --chuid "$USER:$GROUP" --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $EPLITE_DIR/$EPLITE_BIN -- $LOGFILE || true
  echo "done"
}

#We need this function to ensure the whole process tree will be killed
killtree() {
    local _pid=$1
    local _sig=${2-TERM}
    for _child in $(ps -o pid --no-headers --ppid $pid); do
        killtree $child $sig
    done
    kill -$sig $pid
}

stop() {
  echo "Stopping $DESC... "
   while test -d /proc/$(cat /var/run/$NAME.pid); do
    killtree $(cat /var/run/$NAME.pid) 15
    sleep 0.5
  done
  rm /var/run/$NAME.pid
  echo "done"
}

status() {
  status_of_proc -p /var/run/$NAME.pid "" "etherpad-lite" && exit 0 || exit $?
}

case "$1" in
  start)
      start
      ;;
  stop)
    stop
      ;;
  restart)
      stop
      start
      ;;
  status)
      status
      ;;
  *)
      echo "Usage: $NAME {start|stop|restart|status}" >&2
      exit 1
      ;;
esac

exit 0

Assurez vous que le fichier est bien executable par root, puis activez le lancement du service lors du boot de la machine :

# update-rc.d etherpad-lite defaults

Changer le type de base de données

C'est primordial pour tout passage en production, car la base de données utilisée par défaut est très sale. La preuve.

~/etherpad-lite/var$ file dirty.db
dirty.db: UTF-8 Unicode English text, with very long lines

Pas très optimisé tout ça. En fait si on l'ouvre, on s'aperçoit qu'il s'agit simplement d'un fichier JSON. Ce n'est pas si mauvais que ça, mais si la base s'alourdit les performances vont vite être catastrophiques.

Modifions donc la base, dans le fichier settings.json.

[...]

//The Type of the database. You can choose between dirty, sqlite and mysql
  //You should use mysql or sqlite for anything else than testing or development
  "dbType" : "dirty",
  //the database specific settings
  "dbSettings" : {
                   "filename" : "../var/dirty.db"
                 },
                 
  /* An Example of MySQL Configuration
   "dbType" : "mysql",
   "dbSettings" : {
                    "user"    : "root",
                    "host"    : "localhost",
                    "password": "",
                    "database": "store"
                  },
  */

[...]

Sqlite


Commande à lancer depuis la racine d'etherpad-lite :

$ npm install sqlite3

La commande peut être longue, patientez.

info done ok
sqlite3@2.1.3 ./node_modules/sqlite3

Puis dans le fichier settings.json :

"dbType" : "sqlite",
  //the database specific settings
  "dbSettings" : {
                   "filename" : "../var/sqlite.db"
                 },

MySQL


On crée le compte, et la base mysql.

# mysql -u root -p
mysql> CREATE DATABASE 'etherpad-lite';
mysql> CREATE USER 'etherpad-lite-user'@'%' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON `etherpad-lite`.* TO 'etherpad-lite-user'@'localhost' IDENTIFIED BY '<password>';
mysql> FLUSH PRIVILEGES;

Puis dans le fichier settings.json :

"dbType" : "mysql",
"dbSettings" : {
                    "user"    : "etherpad-lite-user",
                    "host"    : "localhost",
                    "password": "password",
                    "database": "etherpad-lite"
                  },

Enfin, de nouveau dans mysql :

$ mysql -u -root -p
mysql> ALTER DATABASE `etherpad-lite` CHARACTER SET utf8 COLLATE utf8_bin;
mysql> USE `etherpad-lite`;
mysql> ALTER TABLE `store` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

Conclusion

Et voilà !
Je vous recommande dans le cas d'une installation sur un serveur donannt sur le net d'ajouter de l'authentification au niveau d'Apache. Autrement, les risques d'utilisations abusives du service ou d'attaques du serveur sont assez élevés.

Enjoy !

Vus : 2686
Publié par Jeyg : 33