Свой сервер синхронизации Obsidian: LiveSync, CouchDB и ИИ через MCP - со всеми граблями
Часть 2 из 2Устройства: ПК и iPhone
Первое устройство: ПК
Кто первый, тот заливает хранилище на сервер. В базе ещё ничего нет, поэтому первым беру устройство, где удобнее вводить данные, то есть ПК. Сначала пробовал iPhone: ввод сложных паролей на телефоне и падающая проверка сервера заставили переключиться.
Хранилище создаётся обычное, в обычной папке, не в OneDrive, Dropbox или iCloud Drive: одно хранилище синхронизируется одним способом. Дальше шестерёнка слева внизу, "Сторонние плагины", включить их, "Обзор", Self-hosted LiveSync, "Установить" и "Включить".
Мастер настройки
Плагин переведён на русский частично. На первом экране выбираю "Я настраиваю это впервые", второй вариант про добавление устройства пригодится позже для телефона.
Экран "Сквозное шифрование": ставлю галочку, в появившемся поле "Парольная фраза" вставляю COUCHDB_PASSPHRASE, только значение, без имени и =, и сверяю края через кнопку показа пароля. Пункт Obfuscate Properties выключен, с ним MCP не найдёт заметки. Advanced не трогаю, алгоритм по умолчанию и E2EE v2 с MCP работают. Плагин честно предупреждает, что passphrase не проверяется до начала синхронизации и ошибка всплывёт только потом, поэтому её надо вставлять, а не набирать.
В способе подключения выбираю "Configure a remote manually" и CouchDB: Setup URI ещё нет, его создаст первое устройство.
На экране CouchDB Configuration: URL https://obsidian.example.com без слеша в конце, имя пользователя livesync (не admin), пароль LIVESYNC_PASSWORD, имя базы obsidian, Use Internal API выключено, CORS на сервере уже настроен. Кнопка Check server requirements скажет "Проверка конфигурации не удалась", и это нормально: проверка читает /_node/_local/_config, а nginx его закрывает, в логе видно 403. Кнопку Fix жать не нужно, реальная проверка это следующая кнопка, Create or connect to database and continue.
Последний экран, "Final Confirmation: Overwrite Server Data with This Device's Files": три галочки, включая "I have created a backup of my Vault", и кнопка I Understand, Overwrite Server.
Ловушка 1: Overwrite Server требует прав администратора CouchDB
Симптом: мастер прошёл, внизу синхронизация стоит на нуле и значок перечёркнут красным, заметки на сервер не уходят. Сохранения не помогают.
Причина видна по логу nginx: "Overwrite Server" сначала удаляет базу (DELETE /obsidian/), а потом создаёт заново. У livesync прав на это нет, отсюда 401. Плагин остаётся в состоянии "первая загрузка не завершена" и ставит себя на паузу.
Лечение такое, что пароль админа на ПК не попадает, а окно риска измеряется минутами. Сначала бэкап и копия каталога couchdb-local.d/. Потом временно делаю livesync администратором сервера:
set -a; . ./.env; set +a
jq -n --arg p "$LIVESYNC_PASSWORD" '$p' | docker exec -i obsidian-couchdb sh -c 'cat > /tmp/p.json'
printf 'user = "%s:%s"\n' "$COUCHDB_USER" "$COUCHDB_PASSWORD" \
| docker exec -i obsidian-couchdb curl -fsS -K - -X PUT --data-binary @/tmp/p.json \
"http://127.0.0.1:5984/_node/_local/_config/admins/${LIVESYNC_USER}"
docker exec obsidian-couchdb rm -f /tmp/p.json
Выдать роль _admin через документ пользователя в _users нельзя, CouchDB отвечает 403. Изменение применяется через пару секунд, проверить можно запросом GET /_session, там должно появиться "roles":["_admin"].
Дальше на ПК: "Настройки", "Self-hosted LiveSync", "Перезапустить мастер настройки" и всё заново. Теперь в логе DELETE /obsidian/ 200, PUT /obsidian/ 201, _bulk_docs 201. Окно "All optional features are disabled" про выключенные Customisation Sync и Hidden File Sync закрываю кнопкой OK: для заметок они не нужны, наборы плагинов на ПК и телефоне всё равно разные.
И сразу снимаю права (префикс с printf и docker exec тот же, что выше):
... curl -K - -X DELETE "http://127.0.0.1:5984/_node/_local/_config/admins/${LIVESYNC_USER}"
Как сделать проще: выдать livesync права администратора до мастера и снять после. Это экономит час.
Ловушка 2: пересозданная база теряет права доступа
После удаления и создания база получает _security по умолчанию, где в members.roles стоит ["_admin"]. Как только livesync перестаёт быть админом, он получает 401 на свою же базу.
Лечение: вернуть _security из бэкапа, вот зачем скрипт сохраняет его отдельно.
docker exec -i obsidian-couchdb sh -c 'cat > /tmp/sec.json' < /var/backups/obsidian/security-YYYY-MM-DD.json
... curl -K - -X PUT -H 'Content-Type: application/json' --data-binary @/tmp/sec.json \
"http://127.0.0.1:5984/obsidian/_security"
Проверка: у livesync своя база отвечает 200, _all_dbs даёт 401, в _session нет _admin.
Ловушка 3: MCP перестал расшифровывать заметки
Симптом: list_notes показывает заметки, read_note отвечает "Note not found", в логах MCP Decryption with HKDF failed.
Причина: у новой базы новая соль шифрования, она лежит в _local/obsidian_livesync_sync_parameters, поле pbkdf2salt. Запущенный MCP помнит старую.
Лечение: пересоздать контейнер MCP командой docker compose up -d --force-recreate mcp. Заодно я поменял VAULT_NAME на реальное имя хранилища. После старта в логах появляется Synchronisation parameters fetched successfully и число проиндексированных заметок.
Ловушка 4: Synchronisation paused for compatibility review
Окно появляется после пересоздания базы: плагин просит обновить плагин на всех устройствах и держит синхронизацию на паузе. На единственном устройстве безопасно нажать Resume synchronisation. Крестик и фиолетовая кнопка Keep synchronisation paused оставляют паузу. Вернуться к окну можно командой Review why synchronisation is paused, но она видна, только пока пауза активна: если в палитре "Команда не найдена", значит паузы уже нет.
Ловушка 5: "Диагностика настроек" ломает синхронизацию
Симптом: режим LiveSync выбран, пауза снята, но заметки не уходят. В логе nginx при каждом сохранении только GET/PUT _local/obsydian_livesync_milestone, без _bulk_docs и _changes. В журнале плагина сначала "Some mismatches have been detected in the configuration between devices. Running a manual replication will attempt to resolve this issue.", а затем "Не удалось подключиться к серверу". Это сообщение ложное, подключение в порядке.
Причина: в Hatch была нажата "Диагностика настроек", и она "исправила" customChunkSize с 0 на 60. В базе записано 0. Автосинхронизация при расхождении молча отказывается работать.
Лечение: палитра команд, Self-hosted LiveSync: Sync now, то есть ручная синхронизация. Плагин сам включает "Automatic alignment of compatible chunk settings", обновляет настройки в базе и запускает LiveSync. Окна с таблицей может и не быть. Не принимай предложения "Диагностики" менять customChunkSize на уже работающей базе.
Ловушка 6: после Fetch и Overwrite автосинхронизация выключена
Перед загрузкой плагин вызывает suspendAllSync() и выключает LiveSync, периодическую синхронизацию, sync on save и sync on start. После загрузки он их не включает обратно, в исходниках CLI-версии плагина так и написано: "suspendAllSync() clobbers them". Итог: синхронизация только по ручной команде.
Лечение: после мастера на каждом устройстве зайти в "Настройки синхронизации" и заново выбрать режим. Похожие жалобы есть в issue плагина.
Как диагностировать
Источника правды два, и это главный навык во всей истории.
Первый, лог nginx /var/log/nginx/obsidian.access.log. По нему видно, есть ли запросы от устройства вообще: User-Agent у ПК выглядит как obsidian/1.13.7 ... Electron, у телефона как iPhone ... obsidian. Дальше по запросам: _bulk_docs с кодом 201 означает, что данные ушли, _changes означает обмен, одни только milestone говорят, что плагин проверил базу и сам остановился, 401 это права, 403 на /_node это закрытая админка.
Второй, журнал самого плагина: палитра команд (Ctrl+P, на iPhone свайп вниз по заметке) и Self-hosted LiveSync: Show log. Названия команд плагина не переводятся, искать надо по-английски: Show log, Sync now.
В строке состояния внизу перечёркнутый красный значок и нули у счётчиков означают, что синхронизация стоит.
Второе устройство: iPhone
Если от неудачной первой попытки осталось хранилище, удали его в "Управлении хранилищами". Новое создаётся с тем же именем, что на ПК, тогда ссылки obsidian:// от ИИ открываются и на телефоне. Пункт "Хранить в iCloud" выключить: iCloud вместе с LiveSync дают дубликаты и конфликты. Плагин ставится так же, как на ПК.
Настройки передаются с ПК из раздела "Для настройки других устройств". Кнопка "Показать QR код" в русском интерфейсе показывает окно "Мы сгенерировали QR-код... Отсканируйте QR-код телефоном" без самого QR-кода, а OK просто закрывает окно. Причина в том, что в русском переводе строки Setup.QRCode потерян плейсхолдер ${qr_image}, в английском он есть. Обход: "Внешний вид", язык плагина English, показать QR, вернуть язык. Важно, что этот QR не зашифрован, в нём все настройки включая пароли, поэтому только со своего экрана, не фотографировать и не пересылать.
Альтернатива это "Копировать текущие настройки в Setup URI". Строка зашифрована паролем, который ты придумываешь сам, её можно переслать себе, например в "Избранное" мессенджера. Setup URI и пароль к нему стоит сохранить в менеджер паролей, пригодятся для следующих устройств.
В мастере на телефоне: "Я добавляю устройство к существующей настройке синхронизации", дальше QR или Setup URI и пароль. На экране "Mostly Complete: Decision Required" нужен вариант "My remote server is already set up. I want to join this device." Не первый, потому что "I am setting up a new server... / reset" перезапишет сервер пустым телефоном, и не третий, плагин сам называет его опасным.
Дальше "Data retrieval scheduled" и Overwrite all with remote files. Overwrite здесь про файлы на iPhone, сервер не трогается. Вариант "Compare time and take newer" не подходит: Obsidian кладёт в каждое новое хранилище заметку "Добро пожаловать", на iPhone она новее серверной и победила бы. Если появится окно про compatibility review, жми Resume.
После Fetch iPhone один раз синхронизировался и замолчал: правка с телефона на ПК не пришла. По логу nginx после Fetch от iPhone не было ни одного запроса. Ручной Sync now отправлял правку, а следующую уже нет. Причина та же, что и на ПК, шестая ловушка: Fetch выключил автосинхронизацию.
Правильные режимы синхронизации
Идти надо в "Настройки", "Self-hosted LiveSync", "Настройки синхронизации", "Режим синхронизации".
| Устройство | Режим | Дополнительно |
|---|---|---|
| ПК | LiveSync (непрерывно) | Keep replication active in the background включить |
| iPhone | LiveSync | Sync on Startup, Sync on File Open, Sync on Save включить |
Даже если в поле уже стоит LiveSync, после мастера выбери его заново, чтобы он применился.
Свёрнутый Obsidian на телефоне замораживается через несколько секунд, это ограничение iOS, а не плагина. Правка, сделанная прямо перед сворачиванием, уйдёт при следующем открытии, через Sync on Startup. В итоге пишешь заметку, и через секунду-две она на сервере и на другом устройстве, без нажатий.
Мелочи, которые стоит знать
Пустые папки не синхронизируются, LiveSync передаёт файлы. Новая папка появится на других устройствах и в MCP, когда в ней будет хоть одна заметка.
Переменная VAULT_NAME должна точно совпадать с именем хранилища в Obsidian, иначе ссылки obsidian://open?vault=... не открываются. Смена имени даёт новый подкаталог в томе MCP: поисковый индекс пересоберётся, а OAuth-клиентов придётся переподключить.
Команда docker compose restart не перечитывает .env, нужен docker compose up -d.
Удаление заметки через MCP уходит в базу, и LiveSync удаляет её на всех устройствах.
Лимиты: документ CouchDB 50 МБ, client_max_body_size 128M. Большие вложения раздувают базу.
Инструкции для ИИ можно держать на сервере (MCP_INSTRUCTIONS_FILE), а запись ограничить папкой (WRITE_FOLDERS), это пригодится при открытии MCP наружу.
Что даёт E2E-шифрование, а что нет
Защищено содержимое заметок: утечка логина с телефона даёт только шифротекст, дамп без passphrase бесполезен.
Не защищены пути и имена файлов, они лежат в базе открытым текстом, вида "path":"папка/заметка.md". Скрыть их можно через Path Obfuscation, но тогда не работает MCP, выбирать приходится. И root на сервере: passphrase лежит в .env для MCP, значит, это уже шифрование при хранении, а не строго end-to-end.
Итоговая проверка
Заметка, созданная на ПК, через 1-2 секунды читается через MCP с сервера, и раз она расшифровывается, то passphrase и Path Obfuscation в порядке. Правка на iPhone приходит на ПК без ручных команд. Пользователь livesync не админ, _all_dbs для него 401, админка снаружи 403. Бэкап по расписанию работает, восстановление проверено.
Что дальше
Открыть MCP наружу через nginx с OAuth (MCP_AUTH_TOKEN, BASE_URL), чтобы Claude в браузере, десктопе и на телефоне мог записывать мысли в Inbox-папку, а запись ограничить через WRITE_FOLDERS. Защиты от перебора пароля на форме входа MCP нет, понадобится limit_req в nginx, при этом fail2ban не должен забанить адреса Claude.
Копия бэкапа за пределы сервера через rsync или rclone. Fail2ban на 401 для CouchDB и ротация логов nginx для этого сайта.
Комментарии
Пока никто не написал. Будьте первым.