Files
local_machine/docs/connectivity/apps/joplin/RUNBOOK.md
ahauimix 0238aa7c02 Add Object B and self-growth canons with Cursor ledger rules; refresh connectivity and VPN runbooks.
Track day metrics/anamnesis HARD rules under .cursor/rules and personal docs so each screening updates days/{KIN}, dynamics, and big-data ledger.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 10:22:56 +08:00

385 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runbook: Joplin — синк Mac ↔ телефон (WebDAV / Android-хотспот)
Симптом: **синхронизация перестала работать** между Joplin на Mac и на телефоне.
Стек: **rclone serve webdav** на Mac → `~/JoplinSync` → Joplin (Mac + Android) по HTTP. Облако Joplin не используется.
**Рабочая схема (2026-0607):** Mac на **хотспоте**, primary IP **`*.100`** через `networksetup -setmanual`, телефон → `http://<подсеть>.100:8080`. Подробно: [STABLE_SETUP.md](./STABLE_SETUP.md).
**Последняя проверка: 2026-07-04** — синк работает на подсети `10.121.169.x` (см. ниже).
---
## Проверенный рабочий сетап (зафиксировано 2026-07-04)
### Условия (все обязательны)
| # | Условие | Как проверить |
|---|---------|---------------|
| 1 | Mac — **клиент WiFi хотспота Android** (не домашний WiFi) | `joplin-hotspot-alias.sh status``network: похоже на Android-хотспот` |
| 2 | **rclone** слушает `:8080` | `joplin-webdav-status.sh` → процесс / порт |
| 3 | Mac primary IP = **`<подсеть>.100`** (setmanual) | `static IP: OK`, `ipconfig getifaddr en0``*.100` |
| 4 | Шлюз WiFi = **телефон** (Android) | gateway `10.x.x.x` / `192.168.43.x` — не `192.168.1.1` роутера |
| 5 | **Mac Joplin**`http://127.0.0.1:8080` | `settings.json``sync.6.path` |
| 6 | **Телефон Joplin**`http://<подсеть>.100:8080` | URL из `status`, **без** `/` и пробелов в конце |
| 7 | Учётка WebDAV: логин `joplin`, пароль из env | после смены пароля — `joplin-webdav-reload.sh` |
| 8 | В rclone.log — запросы **не только** с `127.0.0.1` | `GET`/`PUT from 10.x.x.x` (часто IP **шлюза**, не Mac) |
### Пример сессии, когда синк **работал** (2026-07-04)
```
Подсеть: 10.121.169.x
Gateway: 10.121.169.246 ← телефон (виден в rclone.log)
Mac primary: 10.121.169.100 ← networksetup -setmanual
URL Mac: http://127.0.0.1:8080
URL телефон: http://10.121.169.100:8080
rclone.log: GET from 10.121.169.246:59442 …
alias.log: networksetup -setmanual 10.121.169.100 gw 10.121.169.246
```
### Одна команда перед синком
```bash
./docs/apps/joplin/scripts/joplin-ensure-sync.sh
```
Один раз (LaunchAgent без пароля):
```bash
./docs/apps/joplin/scripts/joplin-hotspot-alias-install-sudo.sh
./docs/apps/joplin/scripts/joplin-hotspot-alias-install.sh
```
Перед возвратом на домашний WiFi:
```bash
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh dhcp
```
---
## Что НЕ работает (не пробовать)
| Подход | Почему не работает | Что делать вместо |
|--------|-------------------|-------------------|
| **Tailscale / VPN mesh** | На Mac нет App Store; brew tailscale без GUI/daemon — не подняли стабильно; пользователь отказался | Хотспот + LAN WebDAV (эта схема) |
| **`ifconfig alias *.100`** | Mac видит alias (`curl` с Mac OK), **Android не маршрутизирует** к alias — в rclone.log **нет** `from 10.x` | **`networksetup -setmanual`** → primary `*.100` |
| **`http://*.local:8080`** (mDNS) | Android-хотспот **не резолвит** `.local` клиентов WiFi | IP: `http://<подсеть>.100:8080` |
| **URL = DHCP primary Mac** (`10.x.x.84`) | IP **меняется** при каждом reconnect хотспота | Фиксированный хвост **`.100`** |
| **Старый URL после смены подсети** (`10.74.21.100` при Mac в `10.121.169.x`) | ETIMEDOUT; телефон стучится не туда | `./joplin-hotspot-alias.sh status`**один раз** новый URL |
| **Stale Manual WiFi** (старый шлюз в prefs) | `No Router MAC`, нет интернета, ping gateway fail | `macos-hotspot-network-recover.sh recover` → DHCP → `repair` |
| **Mac дома (`192.168.1.x`), телефон на LTE** | Разные сети — маршрута нет | Mac к **хотспоту** телефона **или** телефон в ту же WiFi |
| **Смотреть только UI Joplin на Mac** | Mac синкается на `127.0.0.1`**OK даже когда телефон молчит** | `tail -f ~/Library/Logs/joplin-webdav/rclone.log \| grep -v 127.0.0.1` |
| **WebDAV URL в разделе «Прокси»** | Прокси — для HTTP/SOCKS, не адрес синка | **Синхронизация → Self-hosting → WebDAV** |
| **Пробел / `/` в конце URL** | `Not a valid URL: …8080 /info.json` | Переписать URL без пробела и без trailing `/` |
| **Joplin Cloud / Docker Server** | Не выбрано: нужен **локальный** WebDAV без облака | rclone на Mac (`~/JoplinSync`) |
| **Обновлять URL на Mac при смене хотспота** | Mac всегда на localhost | Mac: **только** `127.0.0.1:8080`; менять URL **на телефоне** |
### Быстрая отличительная диагностика
| Симптом | Вероятная причина из таблицы выше |
|---------|-----------------------------------|
| rclone только `from 127.0.0.1` | alias вместо setmanual, разные сети, или неверный URL на телефоне |
| `curl` с Mac на `*.100` OK, телефон — timeout | **alias** (типичный кейс 2026-07-04) → `repair` |
| Mac «Completed», заметок нет | Mac не на WebDAV / пробел в URL |
| `401 Unauthorized` | пароль env ≠ Joplin или старый rclone → `reload` |
| Интернет на Mac мёртв после reconnect | stale Manual → `recover` |
---
## Архитектура
```
Телефон (Joplin) ──HTTP──► Mac en0 primary *.100:8080 ──► rclone ──► ~/JoplinSync/
Mac (Joplin) ──HTTP──► 127.0.0.1:8080 (тот же rclone)
```
| Компонент | Путь / имя |
|-----------|------------|
| Данные | `~/JoplinSync` |
| Учётка | `~/.config/joplin-webdav/env` (`600`, не в git) |
| WebDAV | LaunchAgent `com.eternal.joplin-webdav` |
| Static `*.100` | LaunchAgent `com.eternal.joplin-hotspot-alias` (setmanual; опционально + sudoers) |
| Лог rclone | `~/Library/Logs/joplin-webdav/rclone.log` |
| Лог static IP | `~/Library/Logs/joplin-webdav/alias.log` |
| Лог Joplin Mac | `~/.config/joplin-desktop/log.txt` |
| Настройки Mac | `~/.config/joplin-desktop/settings.json``sync.6.path` |
Скрипты: `docs/apps/joplin/scripts/`.
---
## Шаг 0: диагностика
```bash
./docs/apps/joplin/scripts/joplin-webdav-status.sh
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh status
```
| Что смотреть | OK | Проблема |
|--------------|-----|----------|
| rclone / `:8080` | процесс слушает | `joplin-webdav-serve.sh` или `joplin-webdav-install.sh` |
| `static IP: OK` | primary `*.100` | `joplin-hotspot-alias.sh repair` (sudo) |
| rclone.log | `from 10.` или `from 192.` | только `127.0.0.1` — телефон не достучался |
| Mac URL | `127.0.0.1:8080` | настроить WebDAV на Mac |
---
## Правильные URL
### Android раздаёт хотспот, Mac — клиент WiFi (основной сценарий)
| Устройство | WebDAV URL |
|------------|------------|
| **Mac** | `http://127.0.0.1:8080` |
| **Телефон** | `http://<подсеть>.100:8080` — актуально: `http://10.121.169.100:8080` (2026-07-04) |
Узнать актуальный URL:
```bash
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh status
# или
grep JOPLIN_PHONE_URL ~/.config/joplin-webdav/env
```
**Не использовать на телефоне** (подробнее — раздел «Что НЕ работает» выше):
| URL / подход | Почему |
|-----|--------|
| `http://eternals.local:8080` | Android-хотспот **не резолвит** `.local` |
| `http://10.219.227.100:8080` | старая подсеть (пример) |
| `http://10.74.21.100:8080` | старая подсеть (пример) |
| `http://10.x.x.84:8080` (DHCP primary Mac) | IP меняется при reconnect |
| alias `*.100` без setmanual | телефон не достучится (2026-07-04) |
### Общее для Joplin
- Логин: `joplin`
- Пароль: `JOPLIN_WEBDAV_PASS` из env
- **Без** `/` в конце URL
- **Без пробела** в конце
- `http://`, не `https://`
- **Настройки → Синхронизация → Self-hosting → WebDAV** (не «Прокси»)
После смены URL на Mac: **Quit Joplin** → открыть снова → **Синхронизировать**.
---
## Симптом → причина → действие
### 1. «Синк OK, заметок нет на Mac»
Mac Joplin не на WebDAV — в `~/JoplinSync` только данные с телефона.
→ URL `http://127.0.0.1:8080`, проверить конфигурацию, синк.
---
### 2. `ETIMEDOUT` / `connect ETIMEDOUT 10.x.x.x:8080`
**Причина:** на телефоне **устаревший IP** (другая подсеть или primary `.100` не выставлен).
**Признаки:** Joplin `ETIMEDOUT`; rclone — нет свежих `GET`/`PUT` с `10.`.
**Действие:**
```bash
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh ensure # sudo
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh status # новый URL
```
→ Обновить URL на телефоне **только если сменилась подсеть** (`10.219``10.74`).
---
### 3. `401 Unauthorized`
Пароль в Joplin ≠ env, или rclone не перезапущен.
```bash
grep JOPLIN_WEBDAV_PASS ~/.config/joplin-webdav/env
./docs/apps/joplin/scripts/joplin-webdav-reload.sh
```
---
### 4. `Not a valid URL: …/info.json`
Пробел в конце URL в настройках Joplin → переписать URL.
---
### 5. Порт 8080 не слушает
```bash
./docs/apps/joplin/scripts/joplin-webdav-status.sh
./docs/apps/joplin/scripts/joplin-webdav-serve.sh
```
Лог: `~/Library/Logs/joplin-webdav/launchd.err.log`.
---
### 6. Mac «синкается», телефон — нет (2026-07-04)
**Самый частый кейс.** Mac → `127.0.0.1:8080` OK. Телефон молчит.
**Три причины (часто вместе):**
1. **Подсеть сменилась** — на телефоне старый URL (`10.74.21.100`), Mac уже в `10.121.169.x`
2. **Primary `.100` не выставлен** — LaunchAgent не смог `sudo networksetup` (sudoers + `repair`)
3. **Разные сети** — Mac на домашнем WiFi (`192.168.1.x`), телефон на мобильном
**Диагностика:**
```bash
./docs/apps/joplin/scripts/joplin-webdav-status.sh
grep JOPLIN_PHONE_URL ~/.config/joplin-webdav/env
tail -5 ~/Library/Logs/joplin-webdav/rclone.log | grep -v 127.0.0.1
```
| Признак | Значение |
|---------|----------|
| rclone только `from 127.0.0.1` | телефон **не достучался** |
| `static IP: MISSING` | `./joplin-hotspot-alias.sh repair` |
| `stale ifconfig: …` | старый alias → `repair` (скрипт снимет alias, выставит setmanual) |
| `JOPLIN_PHONE_URL` ≠ URL из status | обновить URL **на телефоне** |
| gateway `192.168.1.1` | домашний WiFi — телефон должен быть **в той же сети** |
**Фикс:**
```bash
./docs/apps/joplin/scripts/joplin-hotspot-alias-install-sudo.sh # если sudo просит пароль
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh repair
./docs/apps/joplin/scripts/joplin-webdav-status.sh # URL для телефона
```
→ Обновить URL в Joplin на телефоне → **Синхронизировать**
---
### 7. `ECONNREFUSED` / телефон «не достаёт», Mac — да
**Причина:** primary **`*.100` отсутствует** на `en0` (слетел после reconnect или DHCP вместо setmanual).
```bash
ifconfig en0 | grep inet
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh status
curl -s -o /dev/null -w '%{http_code}\n' http://10.74.21.100:8080/ # подставьте *.100 из status
```
`joplin-hotspot-alias.sh ensure`
В браузере **на телефоне**: `http://<subnet>.100:8080` — запрос логина
→ Нет интернета на Mac: [HOTSPOT_NETWORK_EMERGENCY.md](../../HOTSPOT_NETWORK_EMERGENCY.md)
---
### 8. `eternals.local` / `*.local` не работает с телефона
**Ожидаемо.** mDNS на Mac резолвится, Android-хотспот — нет. Использовать **`http://<subnet>.100:8080`**, не `.local`.
---
## Процедура: переподключили хотспот / сменили WiFi
### 1. Интернет на Mac
Если `curl` / браузер мёртвы:
```bash
bash /Users/eternal/code/local_machine/docs/connectivity/scripts/macos-hotspot-network-recover.sh recover
```
WiFi на хотспоте: **Manual `*.100`** через `joplin-hotspot-alias` (шлюз = текущий gateway). Перед домашним WiFi: `joplin-hotspot-alias.sh dhcp`. См. [HOTSPOT_NETWORK_EMERGENCY.md](../../HOTSPOT_NETWORK_EMERGENCY.md).
### 2. Joplin
```bash
./docs/apps/joplin/scripts/joplin-webdav-status.sh
./docs/apps/joplin/scripts/joplin-hotspot-alias.sh ensure # если static IP MISSING
```
Чеклист:
- [ ] rclone слушает `:8080`
- [ ] `static IP: OK` (или `repair` выполнен)
- [ ] **Mac:** `http://127.0.0.1:8080` — без изменений
- [ ] **Телефон:** URL из `status`**не менять**, если подсеть та же (`10.74.21.x`)
- [ ] Подсеть **сменилась** → один раз новый `http://<new-subnet>.100:8080`
- [ ] В rclone.log появились `from 10.` после синка на телефоне
### 3. Авто `*.100` (рекомендуется один раз)
```bash
bash ./docs/apps/joplin/scripts/joplin-android-hotspot-setup.sh install
bash ./docs/apps/joplin/scripts/joplin-hotspot-alias-install-sudo.sh
```
LaunchAgent выставляет primary `*.100` каждые 60 с после reconnect.
---
## Скрипты
| Скрипт | Когда |
|--------|--------|
| `joplin-webdav-status.sh` | Первая диагностика |
| `joplin-hotspot-alias.sh status\|ensure\|repair\|dhcp` | URL телефона, primary `*.100`, вернуть DHCP |
| `joplin-android-hotspot-setup.sh install` | Полная настройка хотспота |
| `joplin-hotspot-alias-install-sudo.sh` | setmanual/dhcp без пароля (LaunchAgent) |
| `joplin-webdav-install.sh` | Первая установка rclone + launchd |
| `joplin-webdav-reload.sh` | После смены пароля в env |
| `joplin-mdns-setup.sh` | Справочно; **не для URL на телефоне-хотспоте** |
Путь: `docs/apps/joplin/scripts/`.
---
## Логи
**rclone.log** — успех: `PROPFIND`, `GET`, `PUT from <IP>`. Телефон часто виден как IP **шлюза** (`10.74.21.61`), не IP Mac — нормально для Android.
**log.txt Mac:**
```bash
grep -E 'Synchronizer: \[error\]|ETIMEDOUT|ECONNREFUSED|Unauthorized|Not a valid URL' \
~/.config/joplin-desktop/log.txt | tail -20
```
---
## Безопасность
- WebDAV только в LAN (`0.0.0.0:8080` пока rclone работает); не пробрасывать в интернет.
- env и пароль — не в git.
---
## Связанные документы
| Документ | Зачем |
|----------|--------|
| [STABLE_SETUP.md](./STABLE_SETUP.md) | Primary `*.100`, установка |
| [README.md](./README.md) | Оглавление |
| [docs/apps/joplin/README.md](../../../apps/joplin/README.md) | Установка с нуля |
| [HOTSPOT_NETWORK_EMERGENCY.md](../../HOTSPOT_NETWORK_EMERGENCY.md) | Сеть macOS после reconnect |
---
## История инцидентов
| Дата | Симптом | Корень | Фикс |
|------|---------|--------|------|
| 2026-06-02 | 401 | Пароль env ≠ Joplin | `joplin-webdav-reload.sh` |
| 2026-06-08 | ETIMEDOUT | Старый IP на телефоне | Обновить URL |
| 2026-06-09 | Телефон не достаёт `.100` | Mac без primary `.100` | `setmanual` / `joplin-hotspot-alias repair` |
| 2026-06-15 | Нет интернета после reconnect | Stale Manual + битые маршруты | `macos-hotspot-network-recover.sh recover` |
| 2026-06-19 | `eternals.local` не работает | Android-хотспот не резолвит mDNS | URL `http://10.74.21.100:8080` + setmanual |
| 2026-06-19 | Синк OK | primary `.100` + LaunchAgent | [STABLE_SETUP.md](./STABLE_SETUP.md) |
| 2026-07-04 | Mac OK, телефон нет | alias `.100`; подсеть `10.74``10.121` | setmanual + URL `10.121.169.100` |
| 2026-07-04 | **Синк OK** | setmanual `10.121.169.100`, gateway `.246` | [рабочий сетап](#проверенный-рабочий-сетап-зафиксировано-2026-07-04) |
---
*Актуальный URL телефона: `./docs/apps/joplin/scripts/joplin-hotspot-alias.sh status`.*