44 KiB
ObsiGate
Version française — ce document est le miroir synchronisé de README.md (référence complète). Dernière synchronisation : septembre 2026.
Porte d'entrée web ultra-léger pour vos vaults Obsidian — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
Interface web d'ObsiGate : sidebar multi-vault, recherche globale, statistiques et raccourcis.
📚 Guides
Les guides d'utilisation pas à pas se trouvent dans docs/GUIDES/ :
| Guide | Contenu |
|---|---|
| 🚀 Prise en main | Premier lancement, interface, navigation, vaults, raccourcis |
| 🔍 Recherche, PDF & Excalidraw | Syntaxe de requête, recherche sémantique, lecteur PDF, diagrammes |
| 🤖 Assistant IA & Forge | Fournisseurs, éditeur IA, BooksLM, Forge, commandes @ / / |
| 📝 Édition & collaboration | Édition simultanée, curseurs distants, persistance |
| 📱 PWA & hors-ligne | Installation, cache hors-ligne, file de synchro, notifications |
| 🔌 API REST | Authentification, clés API, endpoints, exemples curl, SSE |
| 🧩 Serveur MCP | Brancher Claude Desktop, Cursor, Cline… sur vos vaults |
| 🔒 Authentification & sécurité | Utilisateurs, MFA, permissions par vault, durcissement |
| 🐳 Déploiement Docker | docker-compose, volumes, reverse proxy, mises à jour |
| 🖥️ Desktop (Tauri) | Installation, premier lancement, build depuis les sources, dépannage |
Index complet :
docs/GUIDES/README.md.
📋 Table des matières
- ✨ Fonctionnalités
- 📚 Guides
- 🚀 Prérequis
- ⚡ Installation rapide
- ⚙️ Configuration détaillée
- 🌍 Variables d'environnement
- 🔒 Authentification
- ➕ Ajouter une nouvelle vault
- 🔨 Build & déploiement avec build.sh
- 🖼️ Rendu d'images Obsidian
- 🖥️ Desktop (Tauri) — Application native
- 📖 Utilisation
- 👥 Collaboration temps réel
- 🔌 API
- 🔍 Recherche avancée
- 🔧 Dépannage
- ⚡ Performance
- 🛡️ Sécurité
- 🏗️ Stack technique
- 🏠 Architecture
- 📝 Développement
- 📄 Licence
- 🤝 Support
- 📝 Changelog
✨ Fonctionnalités
- 🤖 AI Editor intégré — Éditeur CodeMirror 6 avec toolbar IA : amélioration, correction, traduction, génération, réécriture personnalisée, toolbox (liste, tableau, frontmatter, canvas) — multi-provider DeepSeek/OpenRouter/Gemini
- 🧩 Serveur MCP & agent IA — Serveur Model Context Protocol intégré (
/mcp) et assistant avec function calling : lisez, cherchez et modifiez vos vaults depuis Claude Desktop, Cursor… avec confirmations two-step, permissions par vault, rate limiting et redaction des secrets (guide) - 👥 Collaboration temps réel — Édition simultanée d'un même document (Yjs/CRDT) : curseurs distants colorés, indicateur de présence, fusion sans conflit, reconnexion automatique et persistance serveur (détail)
- 📖 Guide d'utilisation intégré — Aide complète en FR/EN accessible depuis le menu Options : interface, navigation, recherche, fichiers, IA, sécurité, API & intégrations (OpenAPI, MCP), hors-ligne, collaboration, desktop, plus une section Architecture avec diagramme Mermaid ; téléchargeable en Markdown et PDF dans la langue courante (détail)
- 📱 Éditeur mobile natif — Édition optimisée pour le tactile : barre d'outils Markdown flottante (gras/italique/code/liste/lien), bouton « Coller » persistant (contournement iOS), zoom par pincement et hauteur ajustable, raccourcis swipe (liens entrants / table des matières) et mode lecture plein écran avec navigation entre fichiers (détail)
- 🗺️ Vue graphe interactive — Canvas force-directed avec Barnes-Hut O(n log n), filtres (tag, type), profondeur, mode focus, historique de navigation ←→↑, export PNG, aperçu au survol (Ctrl+click)
- 🗂️ Multi-vault : Visualisez plusieurs vaults Obsidian simultanément
- 🌳 Navigation arborescente : Parcourez vos dossiers et fichiers dans la sidebar
- 🔍 Recherche avancée : Moteur TF-IDF avec stemming français, normalisation des accents, snippets surlignés, facettes, pagination et tri — plus une recherche sémantique optionnelle (embeddings
all-MiniLM-L6-v2, fusion hybride TF-IDF + RRF) activable via le toggle~(détail) - 💡 Autocomplétion intelligente : Suggestions de fichiers, tags et historique avec navigation clavier
- 🧩 Syntaxe de requête : Opérateurs
tag:,#,vault:,title:,path:,ext:avec chips visuels - 📜 Historique de recherche : Persisté en localStorage (max 50 entrées, LIFO, dédupliqué)
- 🏷️ Tag cloud : Filtrage par tags extraits des frontmatters YAML
- 🔗 Wikilinks : Les
[[liens internes]]Obsidian sont cliquables - 🖼️ Images Obsidian : Support complet des syntaxes d'images Obsidian avec résolution intelligente
- 🎬 Audio & vidéo : Lecteurs HTML5 intégrés (
.mp3 .wav .flac .mp4 .webm…) avec streaming HTTP Range (lecture, déplacement, plein écran) et lecture persistante (mini-lecteur flottant / mini-fenêtre vidéo, retour au média ou arrêt à tout moment, contrôles écran verrouillé via Media Session), repli téléchargement si le format n'est pas lisible par le navigateur - 🎨 Diagrammes Excalidraw : Visualiseur/éditeur natif des fichiers
.excalidrawet.excalidraw.md(iframe sandboxée, auto-save, thème clair/sombre, texte des diagrammes indexé pour la recherche) - 🎨 Syntax highlight : Coloration syntaxique des blocs de code
- 🌓 Thème clair/sombre : Toggle persisté en localStorage
- 📡 Synchronisation temps réel : Surveillance automatique des fichiers via watchdog avec mise à jour incrémentale de l'index
- 📡 Server-Sent Events : Notifications SSE pour les changements d'index avec reconnexion automatique
- ➕ Gestion dynamique des vaults : Ajout/suppression de vaults via API sans redémarrage
- 🖥️ Application desktop native : Tauri (Rust) + backend Python embarqué, sans Docker ni navigateur
- 🐳 Docker multi-platform : linux/amd64, linux/arm64, linux/arm/v7, linux/386
- 🔒 Authentification : JWT + Argon2id, sessions persistantes, contrôle d'accès par vault
- 🛡️ Sécurité : Rate limiting, audit log, backup automatique, redaction de secrets, headers CSP, protection path traversal, utilisateur non-root
- ⚡ Performance : Compression GZip, Cache-Control immutable, index inversé incrémental, search sans I/O disque
- ❤️ Healthcheck : Endpoint
/api/healthintégré pour Docker et monitoring
🚀 Prérequis
Système requis
- Docker >= 20.10
- docker-compose >= 2.0
- Espace disque : ~200MB pour l'image Docker
Systèmes supportés
- Linux (Ubuntu, Debian, CentOS, etc.)
- macOS (Intel et Apple Silicon)
- Windows (avec Docker Desktop)
- NAS compatibles Docker (Synology, QNAP, etc.)
⚡ Installation rapide
1. Cloner le dépôt
git clone https://git.dracodev.net/Projets/ObsiGate.git
cd ObsiGate
2. Configurer vos vaults et vos secrets
Éditez docker-compose.yml pour ajouter vos vaults Obsidian :
volumes:
- /chemin/absolu/vers/votre/vault:/vaults/NomDeVotreVault:ro
Important
: Le chemin doit être absolu et le volume en lecture seule (
:ro)
Créez votre fichier .env pour l'authentification et les secrets :
cp .env.example .env
# Éditez .env pour configurer vos mots de passe et options
Ne committez jamais
.env! Il est dans.gitignore. Utilisez.env.examplecomme référence.
3. Lancer l'application
chmod +x build.sh # une seule fois
./build.sh # build + déploiement en une commande
Options utiles :
./build.sh --help,./build.sh --cache(rebuild rapide),./build.sh --build-only(construire sans démarrer).
4. Accéder à l'interface
Ouvrez votre navigateur sur : http://localhost:2020
⚙️ Configuration détaillée
Étape 1 : Préparation des vaults
- Localisez vos vaults Obsidian sur votre système
- Notez les chemins absolus vers chaque dossier
- Vérifiez les permissions : Docker doit pouvoir lire ces dossiers
Étape 2 : Configuration docker-compose.yml
services:
obsigate:
build:
context: .
image: obsigate:latest
container_name: obsigate
restart: unless-stopped
ports:
- "2020:8080" # Port local 2020 → Port conteneur 8080
volumes:
- /home/user/Documents/Obsidian-Recettes:/vaults/Recettes:ro
- /home/user/Documents/Obsidian-IT:/vaults/IT:ro
- ./data:/app/data # Persistance des données d'auth
environment:
- VAULT_1_NAME=Recettes
- VAULT_1_PATH=/vaults/Recettes
- VAULT_2_NAME=IT
- VAULT_2_PATH=/vaults/IT
- OBSIGATE_AUTH_ENABLED=true
- OBSIGATE_ADMIN_USER=admin
env_file:
- .env # Contient OBSIGATE_ADMIN_PASSWORD et autres secrets
Étape 3 : Build & déploiement
chmod +x build.sh
./build.sh
Alternative manuelle :
docker compose build --no-cache
docker compose up -d
Compatibilité Docker : l'image utilise une variante minimale d'
uvicornetfastapi 0.110.3afin d'éviter les dépendances optionnelles natives (watchfiles,uvloop, …) qui peuvent échouer au build sur Alpine, ARM ou i386.
🌍 Variables d'environnement
Les vaults sont configurées par paires VAULT_N_NAME / VAULT_N_PATH (N = 1, 2, 3…) :
| Variable | Description | Exemple |
|---|---|---|
VAULT_1_NAME |
Nom affiché de la vault | Recettes |
VAULT_1_PATH |
Chemin dans le conteneur | /vaults/Obsidian-RECETTES |
VAULT_1_ATTACHMENTS_PATH |
Dossier d'attachements (optionnel) | 06_Boite_a_Outils/6.2_Attachments |
VAULT_1_SCAN_ATTACHMENTS |
Scan d'images au démarrage (défaut : true) | true |
Règles de nommage : lettres, chiffres et tirets uniquement ; pas d'espaces ; le nom doit correspondre au chemin dans le conteneur.
🔒 Authentification
Désactivée par défaut — Compatible avec toutes les installations existantes.
Système optionnel basé sur JWT + Argon2id avec contrôle d'accès par vault.
Activer l'authentification
cp .env.example .env- Éditez
.env:OBSIGATE_AUTH_ENABLED=true OBSIGATE_ADMIN_USER=admin OBSIGATE_ADMIN_PASSWORD=votre_mot_de_passe # Laissez vide = auto-généré (voir logs) # OBSIGATE_SECURE_COOKIES=false # true si derrière HTTPS - Dans
docker-compose.yml:env_file: - .env
Ne mettez jamais de mot de passe dans
docker-compose.yml! Utilisez toujours.env.
Premier démarrage
Si aucun utilisateur n'existe, ObsiGate crée automatiquement un compte admin et affiche le mot de passe une seule fois dans les logs :
docker-compose logs obsigate | grep -A4 "PREMIER"
Gestion des utilisateurs via CLI
# Créer un utilisateur
docker exec obsigate python backend/create_admin.py create alice MonMotDePasse --role user --vaults Recettes IT
# Créer un admin avec accès total
docker exec obsigate python backend/create_admin.py create bob SecretPass --role admin --vaults "*"
# Lister / supprimer
docker exec obsigate python backend/create_admin.py list
docker exec obsigate python backend/create_admin.py delete alice
Interface d'administration
Un compte admin connecté voit une icône 🛡️ dans le header : liste, création/édition/suppression d'utilisateurs, assignation des vaults, activation/désactivation de comptes.
Contrôle d'accès par vault
| Valeur vaults | Accès |
|---|---|
["*"] |
Toutes les vaults (y compris futures) — défaut admin |
["Recettes", "IT"] |
Uniquement ces vaults |
[] |
Aucun accès |
Variables d'environnement d'auth
| Variable | Description | Défaut |
|---|---|---|
OBSIGATE_AUTH_ENABLED |
Activer l'authentification | false |
OBSIGATE_ADMIN_USER |
Nom de l'admin auto-créé | admin |
OBSIGATE_ADMIN_PASSWORD |
Mot de passe admin (vide = auto-généré) | (auto) |
OBSIGATE_SECURE_COOKIES |
Cookie Secure (HTTPS uniquement) |
false |
OBSIGATE_ACCESS_TOKEN_TTL |
Durée de vie token JWT (secondes) | 3600 |
OBSIGATE_REFRESH_TOKEN_TTL |
Durée de vie refresh token (secondes) | 2592000 |
OBSIGATE_LOGIN_MAX_ATTEMPTS |
Tentatives de login max par IP | 10 |
OBSIGATE_ACCOUNT_MAX_ATTEMPTS |
Tentatives de login max par compte | 10 |
OBSIGATE_LOGIN_WINDOW_SECONDS |
Fenêtre de rate limiting (secondes) | 900 |
OBSIGATE_TRUST_PROXY |
Faire confiance à X-Forwarded-For pour l'IP client (reverse proxy) |
false |
OBSIGATE_WEBHOOK_ALLOW_HTTP |
Autoriser les webhooks non HTTPS | false |
OBSIGATE_WEBHOOK_ALLOW_PRIVATE |
Autoriser les webhooks vers des adresses privées/boucle | false |
OBSIGATE_PDF_MAX_SIZE_MB |
Taille max des PDF extraits (text indexation) | 50 |
OBSIGATE_MEDIA_MAX_INLINE_MB |
Taille max pour la lecture audio/vidéo intégrée (au-delà : téléchargement) | 500 |
OBSIGATE_PDF_EXTRACT_TIMEOUT |
Timeout extraction PDF (secondes) | 30 |
OBSIGATE_TAVILY_API_KEY / OBSIGATE_BRAVE_API_KEY / OBSIGATE_SERPAPI_API_KEY / OBSIGATE_EXA_API_KEY |
Fournisseurs de recherche web à clé (essayés avant SearXNG) | — |
OBSIGATE_WEB_PROVIDERS |
Ordre des fournisseurs de recherche (ex. brave,searxng) |
— |
OBSIGATE_WEB_RETRY |
Réessais réseau des outils web (backoff maison) | 1 |
OBSIGATE_WEB_CACHE_TTL |
Durée du cache SQLite des résultats web (secondes, 0 = off) |
900 |
OBSIGATE_GITEA_URL / OBSIGATE_GITEA_TOKEN |
Source connectée Gitea (outil git_list_repos…) |
— |
OBSIGATE_GITHUB_TOKEN |
Jeton GitHub (outil git_list_repos…) |
— |
Ces clés peuvent aussi être saisies depuis l'interface (menu → Configurations → « Sources connectées & recherche ») : la valeur saisie est stockée dans
data/api_keys.jsonet prime sur la variable d'environnement.
Volume pour la persistance
Les données d'auth (users.json, secret.key) sont stockées dans /app/data :
volumes:
- ./data:/app/data # Persistance des utilisateurs et clé JWT
➕ Ajouter une nouvelle vault
Méthode 1 : Édition directe
docker-compose down- Ajoutez le volume :
- /nouveau/chemin/vault:/vaults/NouvelleVault:ro - Ajoutez les variables :
VAULT_4_NAME=NouvelleVault+VAULT_4_PATH=/vaults/NouvelleVault - Redémarrez :
./build.sh
Méthode 2 : Hot-reload (recommandé)
- Ajoutez volume + variables comme ci-dessus
./build.shcurl http://localhost:2020/api/index/reload
Méthode 3 : API dynamique (sans redémarrage)
curl -X POST http://localhost:2020/api/vaults/add \
-H "Content-Type: application/json" \
-d '{"name": "NouvelleVault", "path": "/vaults/NouvelleVault"}'
curl -X DELETE http://localhost:2020/api/vaults/NouvelleVault
🔨 Build & déploiement avec build.sh
Utilisation de base
chmod +x build.sh # une seule fois
./build.sh # build from scratch + démarrage
Options disponibles
| Option | Description |
|---|---|
--help, -h |
Affiche l'aide complète |
--build-only |
Construit l'image sans démarrer le conteneur |
--no-cache |
Rebuild complet sans cache Docker (défaut) |
--cache |
Utilise le cache Docker (plus rapide si peu de changements) |
--progress=plain |
Sortie verbeuse (recommandé pour le debug) |
--progress=tty |
Sortie interactive avec barres de progression |
Ce que fait le script
- Vérifie Docker et Docker Compose (versions)
- Valide
docker-compose.yml(présence + syntaxe) - Vérifie chaque volume monté (avertit si la source n'existe pas)
- Construit l'image Docker (multi-stage, ~180MB)
- Démarre le conteneur (
docker compose up -d) - Affiche statut + logs en temps réel
Arrêter / redémarrer
docker compose down # Arrêter
docker compose up -d # Redémarrer sans rebuild
docker compose logs -f # Voir les logs
🖼️ Rendu d'images Obsidian
ObsiGate supporte toutes les syntaxes d'images Obsidian avec résolution intelligente multi-stratégies.
Syntaxes supportées
- Markdown standard avec attributs HTML :
[<img width="180" src="path/to/image.svg"/>](https://example.com) - Wiki-link embed chemin complet :
![[06_Boite_a_Outils/6.2_Attachments/image.svg]] - Wiki-link embed nom de fichier :
![[image.svg]] - Markdown standard :

Résolution intelligente (7 stratégies, par priorité)
- Chemin absolu
- Dossier d'attachements configuré (
VAULT_N_ATTACHMENTS_PATH) - Index de démarrage (match unique)
- Même répertoire que le fichier markdown
- Racine du vault
- Index de démarrage (match le plus proche)
- Fallback : placeholder stylisé
[image not found: filename.ext]
Visionneuse & arborescence
Les images sont de plein droit des fichiers du vault : elles apparaissent dans
l'arborescence, sont indexées (nom + métadonnées, jamais les octets) et
s'ouvrent dans une visionneuse dédiée — zoom molette 0,1×–8×, pan au
glisser, double-clic pour réinitialiser, navigation ←/→ entre les images du
dossier (avec pellicule de miniatures WebP), panneau de métadonnées, lightbox
plein écran, ouverture de l'original et téléchargement. Le filtre de recherche
ext:png/ext:jpg est disponible. Formats décodables : PNG, JPEG, GIF, WebP,
BMP, ICO, SVG (SVG servi avec une politique CSP sandbox). HEIC/HEIF
(iPhone) n'est pas décodable par les navigateurs et n'est pas pris en charge.
Configuration
environment:
- VAULT_1_NAME=MonVault
- VAULT_1_PATH=/vaults/MonVault
- VAULT_1_ATTACHMENTS_PATH=Assets/Images # Chemin relatif
- VAULT_1_SCAN_ATTACHMENTS=true # Activer le scan (défaut)
Rescan manuel
curl -X POST http://localhost:2020/api/attachments/rescan/MonVault
🖥️ Desktop (Tauri) — Application native
📖 Guide complet : Desktop (Tauri)
ObsiGate Desktop est une application native construite avec Tauri (Rust + webview système). Elle embarque le backend Python et le frontend dans un exécutable standalone — zéro Docker, zéro ligne de commande.
🚧 Version 2.0.0 — binaires en cours de stabilisation. Pour l'instant, le build depuis les sources est recommandé.
Fonctionnalités desktop natives
| Fonctionnalité | Web | Desktop |
|---|---|---|
| Accès fichiers local | Via upload | Natif (sélecteur dossier) |
| Thème système | Manuel | Auto (suit OS dark/light) |
| Notifications | Service Worker | Natif OS |
Associations .md |
❌ | ✅ « Ouvrir avec ObsiGate » |
| Tray icon | ❌ | ✅ Barre des tâches |
| Auto-update | ❌ | ✅ Vérifie les releases Gitea |
| Mode hors-ligne | Limité | Complet (backend local) |
Téléchargement (binaires pré-buildés)
Les releases sont publiées sur Gitea :
| Plateforme | Format |
|---|---|
| Linux | .deb + .AppImage |
| Windows | .msi + .exe (NSIS) |
# Linux — .deb (Debian/Ubuntu/Deepin)
sudo dpkg -i obsigate_2.0.0_amd64.deb
# Linux — .AppImage (toute distrib)
chmod +x ObsiGate_2.0.0_amd64.AppImage && ./ObsiGate_2.0.0_amd64.AppImage
REM Windows : double-cliquer sur ObsiGate_2.0.0_x64.msi (ou le setup NSIS)
Démarrage
- Lancez l'application depuis le menu ou la ligne de commande
- Le backend Python démarre automatiquement sur
127.0.0.1:17890(splash « Démarrage… » pendant le boot) - La fenêtre s'ouvre et charge l'interface ObsiGate
- Premier lancement : sélectionnez le dossier de vos vaults Obsidian via le sélecteur natif
- Pour fermer : icône tray → Quitter (arrêt propre du backend)
Build depuis les sources
Guide détaillé : desktop/README.md.
Prérequis communs
| Outil | Version | Installation |
|---|---|---|
| Rust (cargo) | ≥ 1.75 | rustup |
| Tauri CLI | ≥ 2.0 | cargo install tauri-cli |
| Git | — | — |
| Dépendances système Linux | — | sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev |
Important — staging :
tauri.conf.jsonembarquebackend/**etfrontend/**depuis le dossierdesktop/. Les scripts de build copient automatiquement../backendet../frontenddansdesktop/avantcargo tauri build. Sans ce staging, le build échoue avec « glob pattern backend/**/* path not found ».
🪟 Windows — build-windows.bat
REM Prérequis (via Scoop) : rustup, curl, git
scoop install rustup curl git
rustup default stable
cargo install tauri-cli
cd desktop
build-windows.bat
Étapes du script :
- Tue les processus Python résiduels (
taskkill /F /IM python.exe) - Télécharge Python 3.11 embed (python.org) →
desktop\python-embed\+ activation de pip (python311._pth) pip install -r ..\backend\requirements.txtdans l'embed- Staging : copie
..\backendet..\frontenddansdesktop\ cargo tauri build --target x86_64-pc-windows-msvc --bundles nsis- Copie
python-embedà côté de l'exécutable (target\x86_64-pc-windows-msvc\release\) pour le mode dev local - Nettoie les dossiers stagés
→ Artefact : desktop\target\x86_64-pc-windows-msvc\release\bundle\nsis\ObsiGate_2.0.0_x64-setup.exe
🐧 Linux — build-linux.sh
cd desktop
chmod +x build-linux.sh
./build-linux.sh
Étapes du script :
- Vérifie Rust + Tauri CLI, installe les dépendances système (apt)
- Crée un venv Python
desktop/python-embed/venv+pip install -r ../backend/requirements.txt - Staging : copie
../backendet../frontenddansdesktop/ cargo tauri build --target x86_64-unknown-linux-gnu --bundles deb,appimage- Copie le runtime (
python-embed/,backend/,frontend/) à côté de l'exécutable
→ Artefacts :
desktop/target/x86_64-unknown-linux-gnu/release/bundle/deb/obsigate_2.0.0_amd64.debdesktop/target/x86_64-unknown-linux-gnu/release/bundle/appimage/ObsiGate_2.0.0_amd64.AppImage
🤖 Builds CI/CD — artefacts automatiques
Oui — le workflow .gitea/workflows/desktop-build.yml construit les binaires desktop à chaque push sur main touchant desktop/**, frontend/** ou backend/** (et manuellement via workflow_dispatch), sur des runners self-hosted :
| Job | Runner | Artefacts (conservés 30 jours) |
|---|---|---|
build-windows |
[self-hosted, windows, desktop] |
desktop/target/release/bundle/msi/*.msi |
build-linux |
[self-hosted, linux, desktop] |
*.AppImage + *.deb |
- Les artefacts sont téléchargeables depuis la page Actions du run Gitea.
- La publication en Gitea Release est prévue sur les tags
v*(étapePublish to Gitea Release). - Le workflow web
.gitea/workflows/ci.ymlgère de son côté lint → tests → sécurité → build Docker → e2e Playwright.
Architecture Desktop
┌────────────────────────────────────────────┐
│ Tauri (Rust) │
│ ├─ Webview (webview système) │
│ │ └─ Frontend (HTML/JS/CSS) │
│ └─ Sidecar Python │
│ └─ uvicorn backend.main:app │
│ └─ port 127.0.0.1:17890 │
└────────────────────────────────────────────┘
Cycle de vie : Tauri spawn le backend Python → health check → splash de démarrage → redirection vers la webview. À la fermeture : kill propre du backend.
📖 Utilisation
Interface web
- Navigation : Cliquez sur les vaults dans la sidebar pour les développer
- Recherche : Utilisez la barre de recherche pour chercher dans toutes les vaults
- Tags : Cliquez sur les tags pour filtrer les contenus
- Wikilinks : Les liens
[[page]]sont cliquables et navigables - Images : Toutes les syntaxes d'images Obsidian sont rendues automatiquement
- Thème : Basculez entre thème clair/sombre avec l'icône 🌙/☀️
Raccourcis clavier
| Action | Raccourci |
|---|---|
| Recherche | Ctrl + K ou / |
| Toggle thème | Ctrl + T |
| Focus recherche | Esc |
👥 Collaboration temps réel
📖 Guide complet : Édition & collaboration
Plusieurs utilisateurs peuvent éditer le même document markdown simultanément (façon Google Docs) :
- Fusion sans conflit grâce à Yjs (CRDT) : deux personnes peuvent taper au même endroit, aucune modification n'est perdue.
- Curseurs distants colorés et sélections visibles dans CodeMirror, avec le nom de chaque utilisateur.
- Indicateur de présence dans l'en-tête de l'éditeur (avatars + statut de connexion).
- Reconnexion automatique (backoff exponentiel) : l'état est fusionné au retour.
- Persistance serveur : le document est écrit sur disque 2 s après la dernière modification.
- Transport : WebSocket
ws(s)://<hôte>/ws/collab/{vault}/{chemin}, authentifié par cookieaccess_token(ou?token=) et soumis au contrôle d'accès par vault.
Aucune configuration n'est nécessaire : ouvrez le même fichier dans deux navigateurs (ou deux fenêtres) pour voir la collaboration en action.
🔌 API
📖 Guide complet : API REST · Serveur MCP
ObsiGate expose une API REST complète :
| Endpoint | Description | Méthode | Auth |
|---|---|---|---|
/api/health |
Health check (status, version, stats) | GET | Non |
/api/auth/status |
Statut auth (activé, utilisateurs présents) | GET | Non |
/api/auth/login |
Connexion (access token + cookie refresh) | POST | Non |
/api/auth/refresh |
Renouveler l'access token via cookie refresh | POST | Cookie |
/api/auth/logout |
Déconnexion + révocation refresh token | POST | Oui |
/api/auth/me |
Infos utilisateur courant | GET | Oui |
/api/auth/change-password |
Changer son mot de passe | POST | Oui |
/api/auth/admin/users |
Lister / créer des utilisateurs | GET/POST | Admin |
/api/auth/admin/users/{u} |
Modifier / supprimer un utilisateur | PATCH/DELETE | Admin |
/api/vaults |
Liste des vaults (filtrée par permissions) | GET | Oui |
/api/browse/{vault}?path= |
Navigation dans les dossiers | GET | Oui |
/api/file/{vault}?path= |
Contenu rendu d'un fichier | GET | Oui |
/api/file/{vault}/raw?path= |
Contenu brut d'un fichier | GET | Oui |
/api/file/{vault}/download?path= |
Téléchargement d'un fichier | GET | Oui |
/api/file/{vault}/save?path= |
Sauvegarder un fichier | PUT | Oui |
/api/file/{vault}?path= |
Supprimer un fichier | DELETE | Oui |
/api/search/advanced |
Recherche avancée TF-IDF (+ semantic=true pour l'hybride) |
GET | Oui |
/api/suggest / /api/tags/suggest |
Autocomplétion | GET | Oui |
/api/tags?vault= |
Tags uniques avec compteurs | GET | Oui |
/api/index/reload |
Force un re-scan des vaults | GET | Admin |
/api/events |
Flux SSE temps réel | GET | Oui |
/api/vaults/add / /api/vaults/{name} |
Gestion dynamique des vaults | POST/DELETE | Admin |
/api/image/{vault}?path= |
Servir une image | GET | Oui |
/api/media/{vault}/thumb?path=&size= |
Miniature WebP (cache disque) | GET | Oui |
/api/config |
Lire / écrire la configuration | GET/POST | Oui/Admin |
/api/diagnostics |
Statistiques index et mémoire | GET | Admin |
Quand
OBSIGATE_AUTH_ENABLED=false, tous les endpoints sont accessibles sans token. Tous les endpoints exposent des schémas Pydantic documentés ; doc interactive sur/docs(Swagger UI).
Exemples :
curl http://localhost:2020/api/health
curl http://localhost:2020/api/vaults
curl "http://localhost:2020/api/search/advanced?q=recette%20tag:cuisine&vault=all&limit=20&offset=0&sort=relevance"
curl "http://localhost:2020/api/suggest?q=piz&vault=all"
curl "http://localhost:2020/api/file/Recettes?path=pizza.md"
🔍 Recherche avancée
📖 Guide complet : Recherche, PDF & Excalidraw
Syntaxe de requête
| Opérateur | Description | Exemple |
|---|---|---|
tag:<nom> |
Filtrer par tag | tag:recette docker |
#<nom> |
Raccourci tag | #linux serveur |
vault:<nom> |
Filtrer par vault | vault:IT kubernetes |
title:<texte> |
Filtrer par titre | title:pizza |
path:<texte> |
Filtrer par chemin | path:recettes/soupes |
ext:<type> |
Filtrer par type de fichier | ext:md kubernetes |
"phrase exacte" |
Recherche de phrase | tag:"multi mots" |
Les opérateurs sont combinables : tag:linux vault:IT ext:md serveur web.
Support PDF
Les fichiers PDF de vos vaults s'affichent en ligne dans le navigateur via le visualiseur PDF natif (iframe + <embed>).
Le visualiseur streame le fichier via HTTP Range (206 Partial Content) — les gros PDF se chargent progressivement.
Le texte est extrait à l'indexation (pypdf / pymupdf) — le contenu PDF est donc recherchable via la recherche full-text.
Filtrez avec ext:pdf pour restreindre les résultats aux PDF.
Les métadonnées (pages, titre, auteur) sont disponibles via GET /api/file/{vault}/pdf/info sans transférer le document.
Limitations : pas d'OCR (les PDF scannés ne sont pas recherchables), pas d'annotation, pas d'édition du PDF lui-même.
Diagrammes Excalidraw
Les fichiers .excalidraw et .excalidraw.md s'ouvrent dans un éditeur visuel Excalidraw complet, intégré dans une iframe sandboxée — dessinez, modifiez et sauvegardez sans quitter ObsiGate.
Les modifications sont sauvegardées automatiquement (2 s) ou avec Ctrl+S ; l'éditeur suit le thème clair/sombre.
Le texte des éléments du diagramme est extrait à l'indexation : il est donc recherchable via la recherche full-text (ext:excalidraw).
Les fichiers créés avec le plugin Obsidian Excalidraw (y compris le format .excalidraw.md compressé) sont compatibles.
Raccourcis clavier
| Raccourci | Action |
|---|---|
Ctrl+K / Cmd+K |
Focaliser la barre de recherche |
/ |
Focaliser la recherche (hors champ texte) |
↑ / ↓ |
Naviguer dans les suggestions |
Enter |
Sélectionner la suggestion active ou lancer la recherche |
Escape |
Fermer les suggestions / quitter la recherche |
Fonctionnalités
- TF-IDF : scoring par fréquence pondérée des termes
- Boost titre : correspondances dans le titre ×3
- Normalisation des accents :
resumetrouverésumé - Snippets surlignés (
<mark>), facettes (compteurs par vault/tag), pagination (50/page), tri pertinence/date, chips de filtres, historique (50 recherches) - Recherche sémantique (optionnelle) : le toggle
~(ouAlt+S) fusionne le classement TF-IDF avec un classement par embeddings (RRF). Fonctionne sans dépendance avec un provider de hachage ; installezbackend/requirements-semantic.txtet/ou renseignezOBSIGATE_EMBEDDING_*pour de vrais embeddingsall-MiniLM-L6-v2. Voir docs/features/semantic-search.md.
🔧 Dépannage
Port déjà utilisé :
sudo netstat -tulpn | grep 2020
# Changer le port dans docker-compose.yml : ports: - "2021:8080"
Vault non trouvée : chemins absolus, permissions de lecture, redémarrer le conteneur après modification.
Build échoue :
docker system prune -f
docker compose down
./build.sh --progress=plain
# Si l'échec persiste :
./build.sh --progress=plain 2>&1 | tee build.log
Logs pour debugging :
docker compose logs -f obsigate
docker compose logs --tail=100 obsigate
Desktop : les logs du backend sont dans %APPDATA%\ObsiGate\logs\backend.log (Windows) / ~/.config/obsigate/logs/backend.log (Linux).
⚡ Performance
| Métrique | Estimation |
|---|---|
| Indexation | ~1–2s pour 1 000 fichiers markdown |
| Recherche avancée | < 10ms pour la plupart des requêtes (index inversé + TF-IDF) |
| Résolution wikilinks | O(1) via table de lookup |
| Mémoire | ~80–150MB par 1 000 fichiers (contenu capé à 100 KB/fichier) |
| Image Docker | ~180MB (multi-stage) |
| CPU | Non-bloquant ; recherche offloadée sur thread pool dédié |
Paramètres recommandés par taille de vault
| Taille | Fichiers | search_workers |
prefix_max_expansions |
max_content_size |
|---|---|---|---|---|
| Petit | < 500 | 1 | 50 | 100 000 |
| Moyen | 500–5 000 | 2 | 50 | 100 000 |
| Grand | 5 000+ | 4 | 30 | 50 000 |
Configurables via l'interface (Settings) ou l'API /api/config.
Optimisations clés
- Index inversé avec set-intersection + prefix matching par recherche binaire
- ThreadPoolExecutor : recherche CPU-bound hors de l'event loop asyncio
- InvertedIndex incrémental : hooks
add_document/remove_document, plus de rebuild O(N) - Compression GZip (~70% de bande passante économisée) + Cache-Control immutable (1 an)
- Race condition guard (
currentSearchId+ AbortController), progress bar, timeout 30s - Rendu Markdown singleton, debounced icon rendering, recherche sans I/O disque
🛡️ Sécurité
📖 Guide complet : Authentification & sécurité
- Path traversal : tous les endpoints fichier valident que le chemin résolu reste dans la vault
- Rate limiting : 10 tentatives de login max par IP sur 15 minutes + lockout par compte (5 tentatives)
- Audit log : écritures/suppressions/config journalisées dans
data/audit.log(JSON lines, rotation 10 MB) - Backup automatique : chaque modification/suppression sauvegardée dans
.obsigate-backup/avec timestamp - Secret redaction : masquage automatique des JWT, clés API, tokens dans les aperçus
- Utilisateur non-root : conteneur Docker sous
obsigate(UID 1000) - Volumes read-only : vaults montées en
:ropar défaut - Secrets dans
.env: jamais dansdocker-compose.yml - Atomic writes : tmp+replace pour users.json, shares.json, webhooks.json
🏗️ Stack technique
- Backend : Python 3.11 + FastAPI 0.110 + Uvicorn
- Auth : python-jose (JWT HS256) + argon2-cffi (Argon2id)
- File Watcher : watchdog 4.x (inotify natif + fallback polling)
- Frontend : Vanilla JS + HTML + CSS (zéro framework, zéro build)
- Rendu Markdown : mistune 3.x
- PDF Export : WeasyPrint 60+
- Desktop : Tauri v2 (Rust) + Python embarqué
- Image Docker : python:3.11-slim (multi-stage)
- Stockage utilisateurs : JSON local (
data/users.json) — aucune base de données - Architecture : SPA + API REST + SSE
🏠 Architecture
┌─────────────────┐ ┌─────────────────────────────────────────┐
│ Navigateur │◄───►│ FastAPI (backend/main.py) │
│ (SPA) │ REST │ ┌──────────────┐ ┌──────────────┐ │
│ │ │ │ indexer.py │ │ search.py │ │
│ app.js │ │ │ (scan+cache) │ │ (in-memory) │ │
│ style.css │ │ └───────┬────── └──────┬───────┘ │
│ index.html │ │ │ │ │
└─────────────────┘ │ ┌───┴──────────────┴───┐ │
│ │ Index en mémoire │ │
│ │ (fichiers, tags, │ │
│ │ contenu, lookup) │ │
│ └───────────────────────┘ │
└─────────────────────────────────────────┘
Flux de données :
- Au démarrage,
indexer.pyscanne tous les vaults en parallèle (thread pool, non-bloquant) - Contenu, tags (YAML + inline) et métadonnées mis en cache en mémoire
- Table de lookup O(1) pour la résolution des wikilinks
watcher.pysurveille les fichiers (watchdog natif ou polling)- Modifications → mise à jour incrémentale de l'index
- Changements notifiés au frontend via SSE
- Recherche sur l'index mémoire (zéro I/O disque)
- Le frontend SPA communique via REST + SSE
📝 Développement
🧪 Tests et CI — règles obligatoires (avant chaque push)
⚠️ Règle absolue — contributeurs humains et agents IA : ne jamais faire de
git pushsans avoir exécuté localement la séquence complète ci-dessous avec 100 % de succès. Le push ne sert pas à découvrir les échecs : la CI est un filet de sécurité, pas un outil de diagnostic.
Vérifications locales avant commit
| Étape | Commande | Job CI équivalent |
|---|---|---|
| Lint backend | ruff check backend/ |
lint |
| Validation des imports frontend | node tests/frontend/validate-imports.mjs |
lint |
| Tests unitaires frontend | node tests/frontend/unit.test.mjs |
lint |
| Tests backend | pytest tests/ -q |
test |
| E2E Playwright | npm run test:e2e (~10 min) |
e2e |
Tests E2E locaux (npm run test:e2e)
Le script scripts/run-e2e-local.sh reproduit fidèlement les conditions du
job CI e2e (.gitea/workflows/ci.yml) :
- backend démarré nativement (venv
.venv-e2e, Python 3.11 viauv) ; - authentification désactivée (
OBSIGATE_AUTH_ENABLED=false) ; - fixtures
test_vault(TestVault) ettest_dir(TestDir) ; - port
2029(baseURL deplaywright.config.ts) ; - projet Playwright
chromium-desktopuniquement (comme la CI).
Prérequis : uv, Node.js ≥ 20, navigateurs Playwright
(npx playwright install chromium). Le venv est créé automatiquement au
premier lancement. Docker n'est pas nécessaire.
npm run test:e2e # suite complète
bash scripts/run-e2e-local.sh --headed # navigateur visible
bash scripts/run-e2e-local.sh -g "reset panes" # filtre sur un test
Sous Windows, si bash n'est pas exploitable (WSL indisponible, git-bash
bloqué par une politique de contrôle d'application), utiliser le lanceur
PowerShell équivalent :
npm run test:e2e:ps
pwsh -File scripts/run-e2e-local.ps1 -PlaywrightArgs @('-g','reset panes')
La suite doit se terminer sur tous les tests passant (60 actuellement), sans échec ni dépendance aux retries. En cas d'échec : corriger et relancer localement jusqu'à 100 %, puis seulement commiter.
Règles d'écriture des tests (leçon apprise)
- Vérifier chaque sélecteur dans le DOM réel avant de l'utiliser dans un
test. Bug réel rencontré : un test ciblait
#cp-inputalors que l'input de la palette porte uniquement la classe.cp-input(aucun id) — le test ne pouvait passer dans aucun environnement. - Tout test nouveau ou modifié doit être exécuté localement (au minimum
avec
-g "nom du test") avant le push. - Pas de contournements qui masquent une instabilité (
waitForTimeoutarbitraires, fallback silencieux) : traiter la cause racine.
Commits et push
- Message de commit : sujet à l'impératif ≤ 50 caractères ; corps (72 col.) uniquement s'il apporte une information utile.
- Un commit = un changement logique (ne pas mêler fix et refactoring).
- Push uniquement quand les 5 étapes locales sont vertes. Pipeline CI :
lint → test → security → build → e2e.
Structure du projet
ObsiGate/
├── backend/ # API FastAPI
│ ├── main.py # Endpoints, Pydantic models, rendu markdown
│ ├── indexer.py # Scan des vaults, index en mémoire, lookup table
│ ├── search.py # Moteur de recherche fulltext avec scoring
│ ├── watcher.py # Surveillance fichiers (watchdog + debounce)
│ ├── auth/ # Module d'authentification (JWT + Argon2id)
│ └── create_admin.py # CLI gestion utilisateurs
├── frontend/ # Interface web (Vanilla JS, zéro framework)
│ ├── index.html # Page SPA + écran de login + splash de boot
│ ├── js/ # Modules ES (app, viewer, editor, graph, …)
│ └── style.css # Styles (CSS variables, thèmes, responsive)
├── desktop/ # Application native Tauri (Rust + Python embarqué)
│ ├── src/main.rs # Shell natif : cycle de vie backend, tray, menus
│ ├── build-windows.bat
│ └── build-linux.sh
├── data/ # Données persistantes (créé au démarrage)
├── Dockerfile # Multi-stage, healthcheck, non-root
├── docker-compose.yml # Déploiement avec healthcheck et auth env vars
├── build.sh # Build & déploiement automatisé
└── docs/ # ROADMAP, guides, audits
Contribuer
Voir docs/CONTRIBUTING.md pour les standards de code et docs/DELIVERY_WORKFLOW.md pour la méthode de livraison obligatoire.
📄 Licence
Ce projet est sous licence MIT — voir le fichier LICENSE pour les détails.
🤝 Support
- Issues : git.dracodev.net/Projets/ObsiGate/issues
- Documentation : git.dracodev.net/Projets/ObsiGate/wiki
📝 Changelog
Consultez le CHANGELOG.md pour l'historique complet de toutes les versions (v1.0.0 → v2.25.1).
Projet : ObsiGate | Version : 2.25.1 | Dernière mise à jour : Septembre 2026
