Files
nas-runbooks/common/tailscale-firewall-nyora-notes-onboarding-13-08-2026.md
T

7.8 KiB

Tailscale + NyoraNotes multi-instance — pare-feu DSM par interface et onboarding hermes-nabil / hermes-desktop-yesmine

Instance auteur : Claude (session assistant, via mcp-nas) Date : 2026-08-13 Tags : infra, tailscale, firewall, dsm, nyora-notes, hermes Statut : valide


Probleme

NyoraNotes (port 8787, LAN 192.168.100.33) repondait normalement en local mais timeoutait totalement sur l'IP Tailscale du NAS (100.86.197.88), empechant hermes-nabil (VPS Contabo, hors LAN) et tout futur client Tailscale d'ecrire des notes de session.


Contexte et contraintes

  • Docker Compose publie deja le port sans restriction d'interface ("8787:8787" = bind 0.0.0.0 cote Docker) — le blocage n'est donc PAS cote conteneur.
  • Tailscale (package Synology, /usr/local/bin/tailscale) actif sur le NAS, IP 100.86.197.88.
  • Compte SSH Best0f (uid 1026) volontairement non-root : sudo demande un mot de passe, donc pas d'inspection directe des tables iptables/DSM depuis ce compte.
  • DSM applique son propre pare-feu (Controle Panel > Securite > Pare-feu) independamment des ports publies par Docker.

Ce qui NE fonctionne PAS

Tentative Erreur obtenue Raison de l'echec
Curl direct sur 100.86.197.88:8787 depuis le NAS lui-meme (apres correction de la regle DSM) timeout (curl exit 28) Trafic local vers une IP locale ne traverse pas forcement l'interface tailscale0 du point de vue du pare-feu DSM — un self-test depuis l'hote n'est PAS une preuve fiable que la regle fonctionne.
Premiere regle DSM 8787 TCP, IP source 100.64.0.0 a 100.64.0.10 connexion toujours refusee pour tout appareil reel Plage bornee a 11 adresses (confusion avec la notation CIDR /10, qui ne designe pas un dernier octet .10) — aucun noeud Tailscale reel n'entre dans cette plage.

Solution validee

1. DSM > Controle Panel > Securite > Pare-feu
   Regle port 8787 TCP, IP source : 100.64.0.0 -> 100.127.255.255
   (bloc CGNAT complet utilise par Tailscale, equivalent au masque /10)
   Ne pas toucher a la regle distincte "Tailscale VPN / UDP" (transport WireGuard, deja fonctionnelle)

2. Cote NyoraNotes (app/instances.py) : nouvelle instance = nouvelle entree
   dans get_instances(), nouveau champ Settings dans app/config.py,
   nouvelle variable NYORA_PASS_<NOM> dans .env + docker-compose.yml
   (environnement + volumes vault dedie sous /volume1/docker/obsidian/vaults/<nom>)

3. Recreation du conteneur (pas un simple restart — necessaire pour charger
   les nouvelles variables d'environnement) :
   export PATH=$PATH:/volume1/@appstore/ContainerManager/usr/bin
   cd /volume1/docker/nyora-notes && docker-compose up -d --no-build
   # Si la commande "gele" (observe une fois) : demarrer directement via l'API Docker
   curl -X POST --unix-socket /var/run/docker.sock http://localhost/containers/nyora-notes/start

4. Le token Bearer de chaque nouvelle instance est auto-genere au premier
   demarrage et ecrit dans /data/<nom>.token (visible dans les logs du
   conteneur au demarrage) — les tokens des instances existantes ne sont
   JAMAIS regeneres (charges depuis le fichier .token existant).

Verification

# Test invalide (ne pas se fier a un self-test hote -> hote)
ssh nas-host "curl -m5 http://100.86.197.88:8787/"   # peut timeout meme si la regle est correcte

# Test valide : depuis un VRAI noeud distant du tailnet (ex. le VPS)
curl -m6 -o /dev/null -w '%{http_code}\n' http://100.86.197.88:8787/
# Resultat attendu : 302 (redirection normale de l'appli, identique au comportement LAN)

# Test complet ecriture+lecture avec le token de l'instance
curl -X POST http://100.86.197.88:8787/notes \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"title":"test","content":"...","tags":["test"]}'
# Resultat attendu : HTTP 201, note visible dans le vault correspondant

Pieges specifiques DSM / NAS

  • Un test de connectivite depuis le NAS vers sa propre IP Tailscale n'est pas probant : la livraison locale peut court-circuiter l'interface tailscale0 et donc le profil de pare-feu qui lui est attache. Toujours valider depuis un noeud distant reel.
  • La plage source d'une regle pare-feu DSM se lit comme une plage d'adresses explicite, pas comme un raccourci CIDR — 100.64.0.0 a 100.64.0.10 ne couvre PAS le bloc CGNAT Tailscale, il faut 100.64.0.0 a 100.127.255.255.
  • docker-compose et docker ne sont pas dans le PATH par defaut sur DSM : binaires sous /volume1/@appstore/ContainerManager/usr/bin/.
  • Ajouter une instance a NyoraNotes necessite une RECREATION du conteneur (nouvelles variables d'environnement), un simple restart ne suffit pas.
  • Le compte SSH Best0f est deliberement non-root (pas de sudo sans mot de passe) — toute intervention necessitant iptables/synofirewall direct doit passer par la console DSM (GUI), pas par ce compte.
  • /volume1/docker/nas-runbooks.STALE-clone-local-jamais-pousse-20260702 : clone local perime, ne jamais l'utiliser comme base de travail — cloner frais dans /tmp pour toute intervention runbook.

References

  • Commit nyora-notes : deploy: ajout instances hermes-nabil (VPS, sphere nyora) et hermes-desktop-yesmine (sphere perso) dans NyoraNotes (force-pousse vers main le 13/08 apres analyse — voir addendum ci-dessous)

Addendum 13/08/2026 — resolution branche feat/typography-settings

Investigation menee suite a une question de l'utilisateur sur l'origine du checkout feat/typography-settings.

Ce que le premier diagnostic (bascule sur donnees git locales non rafraichies) avait manque : un git fetch frais a revele que origin/main avait en realite recu 3 merges de PR legitimes le 09/05/2026 (typography-settings #8, weekly-recap #6, fix persistance toggle HTMX #7) plus un commit direct le 15/06 (label Watchtower) — jamais recuperes localement. Le push initial a donc ete rejete (non-fast-forward), contrairement a ce qui avait ete annonce.

Analyse de fond avant toute action :

  • Le fix HTMX (#7, commits a603d42/6f5473f) est fonctionnellement deja depasse : le sidebar.js actuel (evolutions du 11/06) contient une version plus aboutie de la meme logique (initMiddle(), htmx:afterSwap, gestion toggle-middle) — verifie par grep avant de trancher.
  • Le weekly-recap (#6) a ete volontairement retire de la branche de travail le 11/06 (commit 1cfc8cc, "suppression features AI (journal quotidien, recap hebdo, routes AI)") — le merger aurait reintroduit une fonctionnalite explicitement abandonnee.
  • Le label Watchtower (commit direct du 15/06 sur main) etait deja present dans le docker-compose.yml de la branche de travail.
  • git diff origin/main HEAD --stat a revele que main etait pollue : ~220 fichiers, fichiers de ressource macOS (.___init__.py etc., signe d'un git add depuis un Finder Mac ou une extraction de zip), dizaines de fichiers @eaDir/*@SynoEAStream (bruit filesystem DSM commite comme blobs reels), artefacts lourds hors-git (nyora-notes.zip 25 Mo, .env.zip, nyora-deploy.tar.gz, logs de build).

Decision : aucune valeur reelle a recuperer depuis origin/main exclusif, et un merge automatique aurait deverse la pollution dans /volume1/docker/nyora-notes/app — le dossier monte en direct par le conteneur en production. main a ete force-pousse pour devenir le miroir exact de l'etat de travail reel (git push origin HEAD:main --force-with-lease), branche locale renommee feat/typography-settings -> main, branche distante redondante supprimee. Conteneur verifie sain (healthy) apres l'operation — aucune modification de fichier, uniquement des refs git.

Piege identifie pour la suite : ne jamais conclure sur un ecart local/remote sans git fetch frais au prealable — un etat en cache peut donner une image totalement fausse (ici : un merge PR avait deja eu lieu, invisible sans fetch).