Nextcloud : synchronisation bloquée & fichiers verrouillés

Un des problèmes récurrents de Nextcloud est de parfois verrouiller certains fichiers suite à une opération réalisée sur eux (typiquement un déplacement, un renommage ou une suppression). Il en résulte alors une erreur de synchronisation (« server replied: Locked ») pour tous les appareils connectés. Le seul remède efficace que j’ai trouvé jusqu’ici est de faire un déverrouillage en masse de tous les fichiers sur la base de données.

  1. Passer Nextcloud en mode « maintenance » :
    • sudo docker exec -it -u www-data NextCloud bash -c './occ maintenance:mode --on'
  2. Modifier la base de données (en mode console sur le conteneur Docker) :
    • mysql -u root -p
    • USE nextcloud_db;
    • DELETE FROM oc_file_locks WHERE 1;
    • EXIT
  3. Sortir Nextcloud du mode « maintenance » :
    • sudo docker exec -it -u www-data NextCloud bash -c './occ maintenance:mode --on'

Nextcloud : sortir du mode maintenance

Parfois, Nextcloud bascule en mode maintenance, que ce soit suite à une manipulation voulue ou non. Normalement, sortir de ce mode passe par l’édition du fichier config.php, mais ceci est difficile – et déconseillé – lorsqu’on utilise cette application via Docker.

Dans notre cas, nous utilisons donc plutôt la commande suivante :

  • sudo docker exec -it -u www-data NextCloud bash -c './occ maintenance:mode --off'

macOS : downgrader tout en conservant ses données

Depuis longtemps, Apple pousse ses utilisateurs à mettre à jour ses logiciels (OS et applications) sans possibilité de retour en arrière. Pourtant, il est des situations où on peut avoir besoin d’un « downgrade », et si possible tout en conservant ses données.

Sur Mac, la restauration des données passe principalement par l’Assistant Migration, qui peut transférer ses données depuis un disque externe, un volume partagé en réseau, un autre Mac (via un câble firewire/thunderbolt/USB, ou depuis un PC via une connexion réeau. Problème : si les données à récupérer sont situées sur un disque dont la version de l’OS est supérieure à celle qu’on vient d’installer, l’outil refuse d’aller plus loin.

Pour y parvenir malgré tout, l’astuce consiste à faire en sorte que le volume contenant les données à récupérer ne contiennent pas de système d’exploitation. Et pour cela, il suffit d’utiliser un logiciel de sauvegarde pour copier l’intégralité du volume vers un disque externe, à l’exception du dossier « System » qui se trouve à la racine.

J’ai pu tester l’astuce avec Time Machine, dont les options permettent d’exclure certains dossiers, mais je pense que ça doit aussi fonctionner avec Carbon Copy Cloner.

SSH et authentification RSA

Jusqu’à présent, j’ai toujours utilisé le couple login/password pour me connecter sur mes machines via SSH, mais en voyant mon Syno commencer récemment à se faire spammer (probablement par des bots) j’ai commencé à m’intéresser à l’authentification par clés RSA.

L’idée est la suivante : le client et le serveur ont tous les deux une clé publique et une clé privée, et le serveur connaît la clé publique du client correspondant à un certain login. Au momment de la connexion

  • Le client et le serveur établissent un lien SSH sécurisé
  • Le client envoit une première requête d’authentification non-chiffrée, contenant notamment le login qu’il souhaite utiliser
  • Si le serveur confirme connaître ce login, le client envoit alors une seconde requête, cette fois chiffrée grâce à sa clé privée (qui n’est pas transmise telle quelle et ne doit être distribuée)
  • Si le serveur parvient à déchiffrer cette requête au moyen de la clé publique correspondante au login, l’authentification est validée

La seule manipulation technique repose dans le prérequis de copie initiale de la clé publique du client, laquelle doit être générée (si elle n’existe pas déjà). Voici les étapes à suivre sur la machine côté client :

  1. Utiliser la commande « ssh-keygen -t rsa » pour générer à la fois les clés publique et privée
  2. Choisir une passphrase si on souhaite ajouter un niveau de sécurité supplémentaire à chaque connexion via ces clés – utile sur un ordinateur portable qui pourrait être perdu, par exemple, ou sur une machine directement accessible via internet
  3. Utiliser la commande « ssh-copy-id [-p (port)] login@serveur » qui va s’occuper de copier la clé et la stocker au bon endroit sur le serveur

Normalement, c’est tout. On peut alors tester la connexion en tapant « ssh login@serveur [-p xxxxx] » .

À noter que la commande « ssh-copy-id » implique de pouvoir ouvrir un lien SSH au préalable depuis le client vers le serveur, ce qui est souvent bloqué par défaut dans la configuration d’OpenSSH : il faut alors s’y connecter via le réseau local et remplacer temporairement « PasswordAuthentication no » par « PasswordAuthentication yes », le temps de copier ses clés sur le serveur. Il faudra ensuite redémarrer le serveur SSH (commande pour un Syno sous DSM6 : sudo synoservicectl --reload sshd / et sous DSM7 : sudo synosystemctl restart sshd.service)

Synology : certificat wildcard (suite)

Comme vu dans une note précédente, l’implémentation de Let’s Encrypt par Synology permet d’utiliser les certificats « wildcard » moyennant un challenge basé sur le DNS. En gros, afin de valider la création du certificat, Let’s Encrypt demande d’ajouter une entrée TXT aléatoire dans le domaine concerné.

Le script « acme.sh » présenté dans la dernière note est automatisable via des API de fournisseurs de services, et il se trouve qu’OVH est inclus. J’ai donc utilisé cette implémentation, qui consiste à récupérer des identifiants chez OVH, à savoir une application key et une application secret :

On commence par se connecter en tant que root :

  • sudo -i

On indique alors au script :

  • export OVH_AK="JiEDi7S6u0hgnCOk"
  • export OVH_AS="ZMMqYNN4j5FI8gS2hgRuDkhW9hqsxDaG"

Une fois que c’est fait, il suffit alors de lancer le script en tenant compte de l’API et de ces identifiants :

  • ./acme.sh --issue --keylength 2048 -d celeri.net -d '*.celeri.net' --dns dns_ovh

On obtient alors les fichiers habituels :

Your cert is in  /usr/local/share/acme.sh/celeri.net/celeri.net.cer
Your cert key is in  /usr/local/share/acme.sh/celeri.net/celeri.net.key
The intermediate CA cert is in  /usr/local/share/acme.sh/celeri.net/ca.cer
And the full chain certs is there:  /usr/local/share/acme.sh/celeri.net/fullchain.cer

Une dernière commande pour récupérer les fichiers nécessaires dans une archive zip :

  • rm /volume1/homes/admin/certs/celeri.net/*
  • cp /usr/local/share/acme.sh/celeri.net/celeri.net.cer /usr/local/share/acme.sh/celeri.net/celeri.net.key /usr/local/share/acme.sh/celeri.net/ca.cer /volume1/homes/admin/certs/celeri.net/

Attention : le DSM de Synology ne supporte pas les certificats ECC, donc l’option « –keylength ecXXX » ne doit pas être utilisée !

Pour la suite, on reprend l’article précédent à l’étape 10 !

Source :
https://mondedie.fr/d/10315-tuto-certificat-wildcard-lets-encrypt-sur-un-domaine-heberge-par-ovh

Raspbian et ses clés Apt

Le Raspberry Pi 4 récemment acquis, et à l’OS par conséquent encore assez peu modifié, m’a affiché une erreur bizarre lors de ma dernière commande « apt update » :

pi@clr-pi4:~ $ sudo apt update
Atteint :1 http://raspbian.raspberrypi.org/raspbian buster InRelease
Atteint :2 http://raspbian.raspberrypi.org/raspbian bullseye InRelease
Réception de :3 http://deb.debian.org/debian stable InRelease [122 kB]
Err :3 http://deb.debian.org/debian stable InRelease
Les signatures suivantes n'ont pas pu être vérifiées car la clé publique n'est pas disponible : NO_PUBKEY 04EE7237B7D453EC NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY EF0F382A1A7B6500 NO_PUBKEY DCC9EFBF77E11517
Atteint :4 http://archive.raspberrypi.org/debian buster InRelease
Lecture des listes de paquets… Fait
W: Erreur de GPG : http://deb.debian.org/debian stable InRelease : Les signatures suivantes n'ont pas pu être vérifiées car la clé publique n'est pas disponible : NO_PUBKEY 04EE7237B7D453EC NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY EF0F382A1A7B6500 NO_PUBKEY DCC9EFBF77E11517
E: Le dépôt http://deb.debian.org/debian stable InRelease n'est pas signé.
N: Les mises à jour depuis un tel dépôt ne peuvent s'effectuer de manière sécurisée, et sont donc désactivées par défaut.
N: Voir les pages de manuel d'apt-secure(8) pour la création des dépôts et les détails de configuration d'un utilisateur.

Après quelques recherches, il s’avère que cela signifie que les clés publiques des serveurs de mise à jour du service Apt n’étaient plus répertoriées dans le trousseau d’accès de l’OS. J’ai pu régler le problème en saisissant la même séquence de deux commande pour chacune des 4 clés manquante :

  • gpg --keyserver keyserver.ubuntu.com --recv-key 04EE7237B7D453EC
  • gpg -a --export 04EE7237B7D453EC | sudo apt-key add -
  • gpg --keyserver keyserver.ubuntu.com --recv-key 648ACFD622F3D138
  • gpg -a --export 648ACFD622F3D138 | sudo apt-key add -
  • gpg --keyserver keyserver.ubuntu.com --recv-key EF0F382A1A7B6500
  • gpg -a --export EF0F382A1A7B6500 | sudo apt-key add -
  • gpg --keyserver keyserver.ubuntu.com --recv-key DCC9EFBF77E11517
  • gpg -a --export DCC9EFBF77E11517 | sudo apt-key add -

Je profite de cet article pour mentionner les services que je fais tourner sur cette machine à ce jour :

  • Pi-hole (test & backup)
  • PiVPN / Wireguard (test & backup)

Synology, Docker et Réseaux

Les conteneurs (ou containers en anglais), c’est vraiment très pratique. Virtualiser un package applicatif de façon à ce qu’il tourne de manière autonome mais avec des interfaces basiques (fichiers et réseaux) permet de se passer de VM complètes avec ce qu’elles supposent d’installation d’OS gourmands et potentiellement onéreux en termes de licences.

J’ai récemment pu déployer trois solutions open source sur mon Syno via conteneurs. Pour conserver les données générées par ces conteneurs, le principe est toujours le même : un volume (autrement dit un dossier partagé entre Docker et ses conteneurs) : ce n’est pas obligatoire, mais extrêmement conseillé, notamment pour ne pas tout perdre au moment de mettre à jour les conteneurs.

En revanche, pour ce qui est de l’interfaçage réseau croissant en termes de complexité : Bitwarden, Nextcloud et Pi-hole.

Level 1 : Bitwarden

Bitwarden est un gestionnaire de mots de passe simple et efficace dont la version gratuite fait déjà une large partie de ce qu’on peut en attendre, mais s’il y a une chose à héberger chez soi si on le peut, c’est bien ses identifiants web et autre numéros de carte bancaire.

Bitwarden n’a fondamentalement que deux besoins : un port d’accès en entrée pour l’interface web et un accès internet en sortie pour la synchronisation.

Pour couvrir ce besoin, le mode default bridge de Docker est suffisant : la sortie sur internet est directement active, et le bridge agit comme une sorte de NAT permettant d’attribuer un port de l’hôte (à définir soi-même) avec le port 80 de l’interface de Bitwarden. Seule difficulté rencontrée : le serveur DNS utilisé par l’application est le même que celui fourni par le DHCP du réseau, et ceci ne permet pas d’adresser l’IP de l’hôte lui-même.

Level 2 : Nextcloud

Nextcloud est une solution complète de stockage de données de type cloud. Il dispose de nombreux modules d’extensions et connecteurs divers permettant d’en faire une véritable suite collaborative professionnelle. Personnellement, mon cahier des charges était simple : synchronisation de fichiers, de contacts et d’agendas.

Par défaut, Nextcloud fonctionne avec une base de données SQLite intégrée au package, mais les développeurs recommandent fortement d’en limiter l’usage à des tests préliminaires et de passer à une base plus « pro » (MySQL/MariaDB ou PostGreSQL) avant toute mise en production. Et c’est là que ça se complique : dès que l’on choisit de suivre cette recommandation, cela signifie qu’il faut créer une interface réseau avec une DB, qui peut être la machine hôte (ici le Syno) ou bien un autre conteneur.

C’est cette seconde possibilité que j’ai choisie, car je préfère que la base de données intégrée du Syno soit réservé aux applicatifs du DSM. J’ai donc installé en parallèle un conteneur MariaDB. En théorie, l’interfaçage entre les deux packages peut se faire en mode default bridge, mais je suis tombé sur un piège : ce mode ne permet pas de forcer une IP fixe aux conteneurs, ni de leur affecter de hostname. Et comme Docker (en tout cas dans sa version DSM) semble aimer à faire changer les IP attribuées aux conteneurs, ce lien peut sauter à tout moment, rendant Nextcloud inopérant.

La solution que j’ai identifiée est d’utiliser un user-defined bridge, le default bridge étant naturellement trop limité – et avec le recul, je pense que c’est voulu, afin de pousser les admins à utiliser d’autres modes plus sécurisés. Globalement, un user-defined bridge fonctionne de la même façon que le default bridge, mais on lui associe un réseau de son choix : j’ai opté pour 10.10.10.0/24, avec une passerelle en 10.10.10.1.

Au moment de (re)déployer un conteneur, on peut alors choisir de le connecter à ce bridge et ainsi de lui affecter une IP fixe et même un hostname qui sera reconnu via requête DNS.

Attention : afin que le reverse-proxy du Syno soit bien supporté, il est nécessaire d’ajouter une instruction au fichier config.php :

docker exec -it -u www-data NextCloud bash -c './occ config:system:set overwriteprotocol --value="https"'

Level 3 : Pi-hole

Pi-hole est un astucieux bloqueur de publicités et de traqueurs utilisant le principe du « DNS menteur », c’est à dire qu’il se place en intermédiaire au serveur DNS pour filtrer les requêtes correspondant à des serveurs connus pour distribuer ce type de contenus. Au passage, c’est ce même système qu’utilise la fonction « bloquer les publicités » des Freebox.

Pi-hole existe en version conteneur, mais l’interfaçage réseau est plus complexe, et ce pour la raison suivante : une requête DNS utilise toujours un port standard (53 en UDP ou TCP), ce qui implique que ces ports doivent être libres sur l’hôte si l’on souhaite utiliser un mode bridge. Or, dans mon cas, j’utilise le Syno comme résolveur DNS, ce qui impose donc de trouver autre chose.

Docker intègre un autre mode d’interconnexion réseau, un driver appelé macvlan : en pratique, il s’agit plus ou moins d’un virtual switch qu’on trouve sur les principales solutions de VM : on crée des réseaux virtuels adossés à une interface physique, et les machines associées disposent alors d’une stack IP complète. Attention, cependant : le nom macvlan semble impliquer qu’on crée un VLAN entier (donc avec subnet et passerelle associées), mais c’est faux. En réalité, il s’agit plus d’un sous-réseau du LAN physique qui vient se greffer à ce dernier. Ici, on crée donc un subnet à host unique 10.1.1.52/32, qui sera également l’adresse IP du conteneur Pi-hole.

La création d’un tel réseau n’est pas chose aisée : après avoir suivi plusieurs tutoriels, j’ai noté 4 étapes principales.

  1. Créer une configuration du réseau : c’est là qu’on définit à la fois l’adressage du réseau et l’interface parent (ici : « ovs_eth0 ») :
  2. Créer une instance du réseau : pas de paramètre particulier ici, il suffit de choisir la configuration précédemment créée dans le menu (attention : bien cocher l’option Enable manual container attachment) :
  3. Associer le nouveau réseau avec l’interface physique et l’activer, grâe aux commandes suivantes (attention : ces commandes sont peut-être inutiles – à vérifier) :
    • ip link add mac0 link ovs_eth0 type macvlan mode bridge
    • ip addr add 10.9.9.1/24 dev mac0
    • ifconfig mac0 up
  4. Définir une route statique sur le routeur du LAN désignant l’hôte (i.e. le NAS) comme le next-hop pour le réseau 10.9.9.0/24

Une fois ceci fait, on (re)déploie le conteneur en lui affectant l’adresse IP prévue dans le nouveau subnet, ainsi que la passerelle et les serveurs DNS standards, et il se comporte alors comme une véritable machine dans le LAN. Il ne reste plus qu’à définir cette IP comme résolveur DNS dans le serveur DHCP, et Pi-hole peut alors remplir sa fonction.

macOS : reconstruire l’index de Spotlight

Dans certains cas (notamment des applications dont la fonction de recherche ne fonctionne plus correctemment), il peut être utile de reconstruire entièrement l’index de Spotlight.

Pour cela, on peut soit utiliser deux méthodes :

  • Dans les Préférences Système (en ajoutant puis retirant le disque/dossier concerné dans la rubrique « Spotlight », onglet « Confidentialité »)
  • Dans le terminal, avec la commande suivante :
    # sudo mdutil -E /

Synology : upgrade d’un container Docker

L’approche de Synology en matière de maintenance des conteneurs Docker n’est pas particulièrement intuitive. Voici donc les quelques étapes à suivre pour upgrader une appliance sur DSM 6 :

  1. Dans l’appli Docker, choisir le Registre pour localiser l’image de l’appliance, puis cliquer sur le bouton « Télécharger » :
  2. Une fois le téléchargement de l’image terminée (DSM envoie normalement une notification), afficher la liste des conteneurs et arrêter l’appliance à mettre à jour via le bouton on/off à sa droite
  3. Choisir ensuite « effacer » (ou « réinitialiser » dans les versions plus récentes)
    comme action : ceci a pour effet de détruire l’instance existante de l’ancienne image, tout en conservant les réglages effectués :
  4. Relancer ensuite l’appliance via son bouton on/off : un nouveau conteneur est alors créé avec l’image fraîchement téléchargée

Synology : Certificat Wildcard via Let’s Encrypt

Dans mon premier article sur ce blog, j’ai mentionné avoir installé un certificat wildcard (*.celeri.net) sur mon NAS Synology. Les avantages sont nombreux, à commencer par celui de ne pas avoir à remplacer celui en place (ou en ajouter un nouveau) à chaque fois que je décide d’utilier un nouveau sous-domaine. Synology ne permet pas (pour le moment ?) d’installer des  certificats wildcard sur ses NAS, mais on peut néanmoins utiliser les lignes de commande.

  1. On ouvre une connexion SSH sur le NAS avec « admin » comme login
  2. On commence par télécharger le script de création du certificat :
    • wget https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh
    • chmod a+x acme.sh
  3. On lance la requête permettant de créer le certificat :
    • ./acme.sh --issue -d *.celeri.net --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please [--force]
  4. En résultat, on obtient notamment les lignes suivantes :
    • Domain: ‘_acme-challenge.celeri.net’
    • TXT value: ‘qtlbfy4_7PYLwcQl1ya63tqYDw1SF2fKdx4OMJk6yaU’
  5. Dans le Manager d’OVH, dans la zone DNS de mon domaine « celeri.net », on crée une entrée de type TXT avec ces éléments pour permettre au challenge d’être réalisé sur le nom de domaine :
  6. Retour au Syno, on lance la validation du nom de domaine chez Let’s Encrypt :
    • ./acme.sh --renew -d *.celeri.net --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please [--force]
  7. En résultat, on obtient la création des fichiers nécessaires, comme annoncé en fin d’output :
    • Your cert is in /var/services/homes/admin/.acme.sh/.celeri.net/.celeri.net.cer
    • Your cert key is in /var/services/homes/admin/.acme.sh/.celeri.net/.celeri.net.key
    • The intermediate CA cert is in /var/services/homes/admin/.acme.sh/*.celeri.net/ca.cer
    • And the full chain certs is there: /var/services/homes/admin/.acme.sh/*.celeri.net/fullchain.cer
  8. Ces fichiers sont précieux, et méritent donc d’être enregistrés dans un dossier à part :
    • rm ~/Certs/celeri.net/* ; cp /var/services/homes/admin/.acme.sh/celeri.net/{celeri.net.cer,celeri.net.key,ca.cer} ~/Certs/celeri.net/
  9. On récupère alors ces fichiers via l’interface web du Syno (ou via SFTP)
  10. On crée un nouveau certificat en choississant l’option « Remplacer un certificat existant » (puisqu’il existe déjà; sinon choisir « Ajouter un nouveau certificat ») :
  11. Puis on choisit la fonction d’importation en pensant bien à indiquer que ce sera le certificat par défaut :
  12. Puis on choisit les bons fichiers :

Après un certain temps de traitement et un redémarrage du serveur web, normalement le nouveau certificat est fonctionnel !

À noter que cette méthode, puisqu’elle repose sur Let’s Encrypt par souci d’économie, ne permet de disposer que de certificats valables 3 mois, et qu’elle doit être reproduite à chaque fois manuellement car nécessite à la fois des manipulations sur le NAS et sur le serveur DNS. Le coût de la gratuité, en somme…

[MàJ – 25/05/2020] : Afin de permettre de renouveler plus facilement le certificat, j’ai mis à jour le script ACME.sh et ai implémenté l’API DNS d’OVH, ce qui fait que l’entrée TXT se met à jour automatiquement. Normalement, il n’y a donc plus qu’une seule commande à saisir sur le NAS avant de retourner à l’étape 7 :

cd acme.sh

./acme.sh --issue -d celeri.net -d '*.celeri.net' --dns dns_ovh

https://www.nas-forum.com/forum/topic/59379-lets-encrypt-certificats-wildcard/