Perte de données avec Nextcloud / OnlyOffice ⚠️

Dans le cadre d'une prestation avec Librezo, Tobias et moi avons fait face à un gros incident sur un OnlyOffice connecté à un Nextcloud : on a perdu une semaine d'éditions de documents.

Mise en situation🔗

Utilisatrice : Bonjour, des documents que j'ai édités ont disparu… Le fichier existe sur Nextcloud mais il est vide, et sa dernière modification correspond à sa création… Je l'ai pourtant édité depuis.

🧠 : Merde merde merde merde

🧠 : Ils sont où ces documents pourquoi ils sont nulle part dans les backups ? J'ai l'impression qu'ils ont jamais été sauvegardés 😱

Constat🔗

Ces documents n'ont jamais été sauvegardés sur Nextcloud.

Explication🔗

Par défaut, quand un document est édité avec OnlyOffice, il n'est enregistré dans Nextcloud qu'une fois que son édition est terminée, c'est à dire que tous les clients se sont déconnectés d'OnlyOffice.

Pour une raison inconnue, OnlyOffice ne détectait plus la déconnexion des clients. Donc les documents restaient gentiment dans le cache d'OnlyOffice. Quand un document précédemment édité était à nouveau ouvert dans OnlyOffice, il était correctement chargé, puisque stocké dans son cache.

On n'a jamais cherché à faire des sauvegardes d'un cache, parce que

vas-y c'est un cache

Un cache n'est pas censé conserver des données persistentes.

Un beau jour, on a fait une mise à jour des services, un joli docker compose down, qui a pour effet de supprimer les conteneurs, et avec tous les fichiers qui ne sont pas persistés dans des volumes Docker.

Donc le cash cache a disparu. 💸

Et les fichiers de nos utilisateurs et utilisatrices avec.

Issues reportées🔗

Sur la version d'OnlyOffice incluse dans une app Nextcloud, on trouve de nombreuses complaintes d'erreurs similaires : #12, #77, #78, #87, #100...

Solutions🔗

La première solution est de toute évidence suffisante, mais traumatisme est père de frilosité. Nous on a mis en place les deux 🌨

Garde-fou #1 : Paramétrage d'OnlyOffice🔗

*Interlude* : Vous savez ce qu'on dit sur les paramètres par défaut ?
*Divulgâchage* : il ne sont jamais changés par la plupart des ~~utilisateurices~~ admin sys. Surtout quand la doc est aussi monstrueuse que celle d'OnlyOffice.

Il existe une option forcesave, désactivée par défaut, qui permet de définir un intervalle de temps au bout duquel les éditions seront sauvegardées vers Nextcloud, que la session d'édition soit terminée ou pas.

Pour activer cette option, il faut ajouter ceci dans le fichier

/etc/onlyoffice/documentreader/local.json :

{
    "services": {
        "CoAuthoring": {
            "autoAssembly": {
                "enable": true,
                "interval": "5m"
            }
        }
    }
}

Mais ce fichier est édité par l'entrypoint (le script de démarrage) du conteneur officiel.

On a essayé de monter le fichier tel que présenté au-dessus ↑ avec cette entrée dans notre docker-compose.yml :

services:
  onlyoffice:
    volumes:
      - ./local.json:/etc/onlyoffice/documentserver/local.json

Mais le fichier est modifié par l'entrypoint, ce qui rend difficile son versionnage. Si on ajoute :ro à la fin de la ligne, pour le monter en read-only, le conteneur crash.

On a donc pris le parti d'améliorer l'entrypoint pour que ces valeurs puissent être commandées par des variables d'environnement.

Voilà le patch à appliquer (`git apply <` [`entrypoint.patch`](https://u.ppom.me/entrypoint.patch)) ```diff diff --git a/run-document-server.sh b/run-document-server.sh index fd183a3..400e9e2 100755 --- a/run-document-server.sh +++ b/run-document-server.sh @@ -75,6 +75,10 @@ NGINX_CONFIG_PATH="/etc/nginx/nginx.conf" NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-1} NGINX_WORKER_CONNECTIONS=${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)}

+FORCESAVE_ENABLE=${FORCESAVE_ENABLE:-false} +FORCESAVE_INTERVAL=${FORCESAVE_INTERVAL:-5m} +FORCESAVE_STEP=${FORCESAVE_STEP:-1m}

JWT_ENABLED=${JWT_ENABLED:-true}

validate user's vars before usinig in json🔗

@@ -328,6 +332,11 @@ update_ds_settings(){ ${JSON} -I -e "this.services.CoAuthoring.token.inbox.inBody = ${JWT_IN_BODY}" ${JSON} -I -e "this.services.CoAuthoring.token.outbox.inBody = ${JWT_IN_BODY}"

  • ${JSON} -I -e "if(this.services.CoAuthoring.autoAssembly===undefined)this.services.CoAuthoring.autoAssembly={};"
  • ${JSON} -I -e "this.services.CoAuthoring.autoAssembly.enable = ${FORCESAVE_ENABLE}"
  • ${JSON} -I -e "this.services.CoAuthoring.autoAssembly.interval = '${FORCESAVE_INTERVAL}'"
  • ${JSON} -I -e "this.services.CoAuthoring.autoAssembly.step = '${FORCESAVE_STEP}'"
  • if [ -f "${ONLYOFFICE_EXAMPLE_CONFIG}" ]; then ${JSON_EXAMPLE} -I -e "this.server.token.enable = ${JWT_ENABLED}" ${JSON_EXAMPLE} -I -e "this.server.token.secret = '${JWT_SECRET}'"
</details>

Ce patch doit être appliqué au [repo du conteneur Docker
d'OnlyOffice](https://github.com/ONLYOFFICE/Docker-DocumentServer).

Alternativement, le fichier d'entrypoint patché peut très sûrement être monté
dans le conteneur, permettant de s'éviter de reconstruire l'image manuellement.

Testé :
```yaml
services:
  onlyoffice:
    build: /chemin/vers/le/repo/git/patché

Non testé :

services:
  onlyoffice:
    volumes:
      - ./run-document-server.patché.sh:/app/ds/run-document-server.sh:ro

Une fois que vous avez reconstruit le conteneur avec ces valeurs ou monté la version patchée de l'entrypoint, voilà un exemple de configuration utilisant ces variables :

services:
  onlyoffice:
    environment:
      - FORCESAVE_ENABLE=true
      - FORCESAVE_INTERVAL=2m
      - FORCESAVE_STEP=5m

L'entrypoint fonctionne bizarrement, il n'édite local.json que s'il n'existe pas (… ou quelque chose comme ça. Si vous avez compris un comportement plus précis, n'hésitez pas à me le dire). Donc il est possible que vous ayez besoin de supprimer le conteneur d'OnlyOffice pour que l'entrypoint édite local.json. Vérifiez que vos documents ont bien été sauvegardés dans Nextcloud, pour ne pas perdre de données !

Une pull request est ouverte pour appliquer ce patch upstream.

Garde-fou #2 : Sauvegarde du cache d'OnlyOffice🔗

Afin de garder le cache d'OnlyOffice, même si on supprime son conteneur, on peut monter sauvegarder son cache et sa base de données.

Quoi, il y a une base de données dans le conteneur ?

Et oui, le conteneur OnlyOffice est un immense bordel dans lequel tournent

  • le serveur applicatif d'OnlyOffice
  • nginx
  • postgresql
  • rabbitmq
  • encore d'autres trucs.

Bref, pour sauvegarder vite fait le cache, on sauvegarde le cache du serveur applicatif et la base de données PostgreSQL. On a pas non plus fait un export SQL de la base de données comme on fait pour faire une vraie sauvegarde de base de données, mais vas-y c'est du cache, comme on dit.

services:
  onlyoffice:
    volumes:
      - onlyoffice-cache:/var/lib/onlyoffice/documentserver/App_Data
      - onlyoffice-db:/var/lib/postgresql

Too Long; Already Read?🔗

Si vous utilisez Nextcloud et OnlyOffice, je vous encourage à demander activer l'option forcesave, et vos documoutons seront bien gardés.

🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑