Файловый слой для AI-ботов: синхронизируем Telegram, VPS и Obsidian через Git
Файловый слой позволяет AI-боту сохранять результат не только в чате, но и в виде управляемого Markdown-файла. Бот пишет заметку в Obsidian vault на VPS, cron отправляет изменения в Gitea, а Obsidian Git синхронизирует их с Mac; общие папки подключаются через обратные симлинки.
Коротко
| Компонент | Роль |
|---|---|
| Telegram-бот | Принимает голос, текст и ссылки |
| VPS | Создаёт Markdown-файлы в локальном vault |
| Gitea | Хранит историю и передаёт изменения через Git |
| Obsidian Git | Подтягивает заметки на Mac |
| iCloud и симлинки | Дают совместный доступ к выбранным папкам |
| AGENTS.md | Задаёт ботам правила именования, тегов и размещения файлов |
Недавно мы собрали схему, в которой телеграм-боты сохраняют голосовые заметки, ссылки, задачи и черновики прямо в Obsidian vault. Бот пишет markdown-файл на VPS, Git отправляет изменения в Gitea, а Obsidian Git подтягивает их на Mac. Идея простая: AI-бот должен оставлять после себя не только ответ в чате, а управляемый артефакт — файл с понятным именем, тегами и местом в vault. Тогда Obsidian становится не просто заметочником, а файловым слоем для персональных агентов. Расскажем, как мы это сделали.
Если коротко, то схема работает так: бот на VPS создает markdown-файл в локальном Obsidian vault, cron пушит изменения в Gitea, а Obsidian Git на Mac каждые несколько минут делает pull. Общие iCloud-папки подключаются обратными симлинками: реальные файлы лежат в vault, а iCloud ссылается на них.
В AGIMA мы часто смотрим на AI не как на отдельную игрушку, а как на слой, который должен встраиваться в процессы и оставлять проверяемый результат. Этот личный проект — маленький пример такого подхода.
В статье покажем свою схему: Gitea на VPS, Caddy для HTTPS, cron для синхронизации, Obsidian Git на Mac и обратные симлинки для iCloud-папок. Отдельно разберу ограничения: конфликты Git, права контейнеров, Docker-порты и backup перед переносом папок.
Задача: боты должны оставлять markdown-файлы в Obsidian
У меня есть телеграм-боты, которые записывают заметки, задачи и мысли. Один работает с голосовым диктантом, другой сохраняет ссылки и выжимки из статей, третий просто логирует короткие идеи. Все они генерируют markdown-файлы.
Vault — это папка, в которой Obsidian хранит заметки как обычные markdown-файлы. Поэтому ботам не нужен отдельный API Obsidian: достаточно создать файл в правильной папке и дождаться синхронизации.
Я рассматривал три варианта:
копировать файлы вручную (быстро надоест);
хранить vault в стороннем облаке (не подходит для личных данных и ботов на VPS);
синхронизировать через Git (дает историю изменений и хорошо встраивается в файловую схему).
Плюс у нас есть папки, которые живут в iCloud: общие списки и заметки. Их тоже нужно было присоединить к vault так, чтобы Git видел содержимое, а не ссылку.
Архитектура
Итоговая схема решения выглядит так:
Телефон: голос, текст, ссылки
↓
Telegram-бот на VPS
↓ пишет markdown-файл
/opt/obsidian-vault/ ← Git-репозиторий на VPS
↓ cron каждые 2 минуты
Gitea на VPS
↓ git pull каждые 5 минут
Obsidian на Mac через плагин Obsidian Git
↕ обратные симлинки
iCloud-папки для общих заметок
Каждый блок можно заменить: Gitea — на GitHub или GitLab, Telegram — на Matrix, cron — на systemd timer, Docker — на обычный сервис. Принцип остаётся один: файловая система плюс Git дают синхронизацию, историю изменений и понятную точку входа для ботов.
Компоненты в схеме:
| Компонент | Роль | Почему выбран |
|---|---|---|
| Telegram-бот | Создаёт Markdown-файлы | Удобный вход с телефона |
| VPS | Запускает ботов и cron | Всегда онлайн |
| Gitea | Центральный Git-репозиторий | Self-hosted и история изменений |
| Caddy | Обеспечивает HTTPS и reverse proxy | Автоматически выпускает сертификат в типовом сценарии |
| Obsidian Git | Выполняет pull, commit и push на Mac | Работает внутри Obsidian |
| iCloud | Даёт доступ к общим папкам | Нужен для семейных и общих заметок |
| AGENTS.md | Задаёт правила для файлов | Не даёт ботам засорить vault |
Почему не Obsidian Sync, Syncthing или WebDAV
Obsidian Sync хорош для обычной синхронизации между устройствами, но в моей схеме ботам на VPS нужно писать файлы в тот же контур. Мы хотели, чтобы бот создавал markdown-файл на сервере, а дальше он попадал в Obsidian обычным Git-процессом.
Syncthing тоже подходит для файлов, но мне важна история изменений и возможность разрулить конфликт через Git. WebDAV или S3 можно использовать, но тогда придется отдельно решать, как Obsidian на Mac будет стабильно подтягивать изменения.
Git + Gitea оказался самым понятным вариантом: боты пишут в папку, cron коммитит изменения, Obsidian Git подтягивает их на Mac.
| Подход | Плюсы | Минусы |
|---|---|---|
| Obsidian Sync | Официальный sync, минимум администрирования | Подписка, сложнее встроить ботов на VPS |
| Syncthing | Хорош для файловой синхронизации | Меньше контроля через историю Git |
| Git + Gitea | История изменений, self-hosted, удобно для ботов | Конфликты, нужен сервер и дисциплина |
| WebDAV/S3 | Удобно для backend-сценариев | Нужен отдельный слой для Obsidian |
Шаг 1. Переносим iCloud-папки внутрь Obsidian vault
Начнем с iCloud-папок: если сделать симлинк в неправильную сторону, Git увидит только ссылку, а не файлы.
Задача такая: физические файлы должны лежать в vault, чтобы Git видел содержимое. А папка в iCloud должна ссылаться на папку внутри vault, чтобы общий доступ через iCloud продолжал работать.
Важно: сначала сделайте копию папки и проверьте схему на тестовой директории. iCloud не всегда одинаково работает с симлинками на разных версиях macOS, поэтому переносить боевые заметки без проверки нельзя.
Пример безопасной процедуры:
bash # 1. Делаем резервную копию cp -a "iCloud/Main/AI Mindset" "iCloud/Main/AI Mindset.backup" # 2. Копируем папку в vault cp -a "iCloud/Main/AI Mindset" "Vault/AI Mindset" # 3. Проверяем, что файлы на месте ls "Vault/AI Mindset" # 4. Только после проверки заменяем папку в iCloud на симлинк mv"iCloud/Main/AI Mindset" "iCloud/Main/AI Mindset.old" ln -s "$HOME/Vault/AI Mindset""$HOME/iCloud/Main/AI Mindset"
Обратный симлинк — это когда физические файлы лежат в vault, а папка в iCloud указывает на них ссылкой. Так Git видит содержимое, а iCloud остается точкой доступа для общих папок.
После проверки можно удалить .old, но я бы не делал это сразу. Сначала откройте Obsidian, проверьте Git-статус, убедитесь, что iCloud видит папку, и только потом переносите боевые данные.
Шаг 2. Поднимаем Gitea на VPS и закрываем порт
Для личных заметок мы не хотели использовать GitHub: даже приватный репозиторий остается сторонним сервисом. Поэтому выбрали Gitea на своем VPS.
Gitea — self-hosted Git-сервер. В этой схеме он нужен как центральное место, куда VPS пушит изменения и откуда Mac их забирает.
Минимальный контейнер Gitea можно запустить одной командой:
bash docker run -d --name gitea -p 127.0.0.1:3000:3000 gitea/gitea:latest
Обратите внимание на 127.0.0.1:3000:3000. Так контейнер слушает только localhost. Если опубликовать порт как -p 3000:3000, Docker сам добавит правила в iptables, и ufw может не защитить сервис так, как вы ожидаете. Для таких случаев в Docker есть отдельная цепочка DOCKER-USER, но в моей схеме проще не открывать Gitea наружу напрямую.
Публичный HTTPS-трафик идет через Caddy:
caddyfile git.example.com { reverse_proxy 127.0.0.1:3000 }
В типовом сценарии Caddy сам выпустит Let's Encrypt-сертификат, если DNS уже указывает на VPS и порты 80/443 открыты.
Дальше инициализируем репозиторий в vault и пушим:
bash cd ~/obsidian-vault git init cat > .gitignore <<'EOF' .obsidian/workspace.json obsidian/workspace.DS_Store .env .env*.local EOF git add -A git commit -m "init" git remote add origin https://git.example.com/user/vault.git git push -u origin master
Шаг 3. Настраиваем Git-синхронизацию между VPS и Mac
У синхронизации две стороны: Mac с Obsidian и VPS с контейнерами ботов.
Mac: Obsidian Git
На Mac мы используем плагин Obsidian Git. Настройки:
— Auto pull: каждые 5 минут;
— Auto commit: каждые 5 минут;
— Auto push: после commit.
В этой схеме Obsidian остается обычной папкой с markdown-файлами. Это удобно для ботов: им не нужен API Obsidian, достаточно создать файл по правилам и дождаться Git-синхронизации.
VPS: cron-скрипт
На VPS клонируем vault один раз. Контейнеры с ботами монтируют его через bind mount:
bash docker run -v /opt/obsidian-vault:/home/node/vault your-bot-image
Для Docker Compose это может выглядеть так:
yaml services: bot: image: your-bot-image volumes: - /opt/obsidian-vault:/home/node/vault env_file: -.env
Простой sync-скрипт:
bash #!/bin/bash # /opt/vault-sync.sh set -e cd /opt/obsidian-vault || exit 1 git pull --rebase if [ -n "$(git status --porcelain)" ]; then git add -A git commit -m "auto-sync $(date '+%Y-%m-%d %H:%M')"git push fi # Права для контейнеров: uid 1000 = node user chown -R 1000:1000 /opt/obsidian-vault
В crontab:
cron */2 * * * * /opt/vault-sync.sh >> /var/log/vault-sync.log 2>&1
Бот записал файл, через пару минут он попал в Git, еще через несколько минут Obsidian подтянул его на Mac.
Для личного vault нам хватило простого cron-скрипта. В более серьезной схеме я бы добавил lock-файл, обработку конфликтов, отдельного пользователя для sync и уведомление в Telegram при ошибке.
Шаг 4. Описываем правила для ботов в AGENTS.md
Синхронизация доставляет файлы, но не поддерживает порядок. Порядок держит AGENTS.md: он задает правила именования, frontmatter, папки и поведение по умолчанию. Без него бот технически работает, но через неделю vault превращается в свалку.
Минимальный набор:
Добавить в чат: # AGENTS.md ## Naming — Формат: `{project} {type} описание — YYYY-MM-DD.md` — Максимум 80 символов ## Frontmatter --- tags: [тег1, тег2] date: YYYY-MM-DD source: telegram --- ## Куда класть — Если не уверены в папке — `_inbox/` — Не класть файлы в корень vault — Боты создают новые файлы и не редактируют существующие заметки
Пример структуры vault:
Добавить в чат: obsidian-vault/ _inbox/ articles/ shopping/ tasks/ AGENTS.md .gitignore
Пример файла, который создает бот:
Добавить в чат: --- tags: [inbox, voice] date: 2026-03-27 source: telegram --- # Идея для статьи про Obsidian Короткая мысль, надиктованная голосом.
Главное правило: боты создают новые заметки, обычно в _inbox/, и не редактируют файлы, которые человек правит руками. Так меньше Git-конфликтов.
Шаг 5. Закрываем основные риски безопасности
Главный риск self-hosted-схемы — случайно открыть наружу сервис, который должен быть доступен только локально. Поэтому Gitea слушает 127.0.0.1, а публичный HTTPS-трафик проходит через Caddy.
Мой базовый чек-лист:
— Gitea слушает только 127.0.0.1, а не все интерфейсы.
— Caddy отдает Gitea через HTTPS.
— Docker-порты публикуются как 127.0.0.1:X:X, если сервис не должен быть доступен напрямую.
— SSH-доступ на VPS только по ключу, парольный вход выключен.
— В Gitea включена 2FA.
— Пароль Gitea сгенерированный, не password123.
— Токены Telegram-ботов лежат в .env, а в репозиторий попадает только .env.example.
— .env, .env*.local и временные файлы добавлены в .gitignore.
— Cron пишет лог, а ошибки не остаются незамеченными.
— Vault регулярно бэкапится отдельно от Git.
Git не заменяет backup. Он хранит историю изменений, но не защищает от потери сервера, ошибки в командах, повреждения репозитория или удаления remote. Для боевого vault нужен отдельный backup: например, снапшот VPS и периодическая копия vault на внешний диск или в отдельное хранилище.
Где схема ломается
Эта схема лучше всего работает для append-only сценариев: бот создает новые заметки, а человек позже разбирает их в Obsidian. Для совместного редактирования одних и тех же файлов Git-конфликты придется обрабатывать вручную.
Что может пойти не так:
— Бот и человек одновременно изменили один файл. Git получит конфликт, синхронизация остановится до ручного разбора.
— iCloud не подхватил обратный симлинк. Поэтому сначала нужна тестовая папка.
— Cron упал после git pull --rebase. Нужны лог и уведомление об ошибке.
— Контейнер пишет файлы от другого пользователя. Тогда появляются проблемы с правами.
— Бот положил заметку в корень vault. Это лечится правилами в AGENTS.md.
— Gitea недоступна во время push. Нужно повторить синхронизацию или разбирать состояние вручную.
Правило, которое снимает половину проблем: боты создают новые файлы в _inbox/ и не редактируют существующие заметки.
Грабли, на которые я наступил
Docker-порты. Если пробросить порт как -p 3000:3000, сервис может оказаться доступен извне. Для Gitea я использую -p 127.0.0.1:3000:3000, а наружу отдаю только Caddy.
SSH падает после запуска контейнера. Контейнер на host-сети может занять порт 22. Не используйте --network host без необходимости.
Git: dubious ownership. Cron работает от root, а файлы принадлежат uid 1000. Git ругается. Для личной схемы можно добавить safe directory:
bash git config --global --add safe.directory /opt/obsidian-vault
Права на файлы. Контейнер работает как node:1000, а git clone создает файлы от root. Бот не может записать файл. В простом варианте помогает:
bash chown -R 1000:1000 /opt/obsidian-vault
В более аккуратной схеме лучше настроить пользователя и права так, чтобы не делать chown -R каждые две минуты.
iCloud не видит симлинк. Такое возможно. Перед миграцией боевых данных сделайте тестовую папку, проверьте синхронизацию на всех устройствах и оставьте backup.
Чек-лист перед боевым запуском
— Gitea доступна только через Caddy, контейнер слушает 127.0.0.1.
— Vault пушится и пуллится вручную без конфликтов.
— Бот создает новый файл в _inbox/.
— Obsidian Git подтягивает файл на Mac.
— iCloud-папка проверена на тестовой директории.
— Есть backup до переноса боевых заметок.
— Ошибки cron попадают в лог или уведомление.
— Токены ботов не лежат в vault.
Кому подходит такая схема
Подойдет, если:
— боты в основном создают новые заметки;
— вы хотите хранить заметки в markdown и Git;
— у вас уже есть VPS или вы готовы его поддерживать;
— вам важна история изменений и self-hosted-контур;
— вы готовы иногда разбирать Git-конфликты.
Не подойдет, если:
— несколько человек одновременно редактируют одни и те же файлы;
— нужен официальный sync без администрирования;
— вы не хотите поддерживать VPS;
— заметки содержат данные, для которых нужен полноценный security/compliance-процесс.
Итого
В нашем случае схема заработала за вечер: боты пишут markdown-файлы в один vault, Git синхронизирует их между VPS и Mac, а Obsidian Git подтягивает изменения. Но это не замена backup и не универсальная синхронизация для командной работы.
Схема лучше всего подходит, когда боты создают новые заметки: голосовые мысли, ссылки, задачи, черновики, логи. Человек потом разбирает их в Obsidian, переносит по папкам и редактирует.
Если повторяете такую схему, начните с тестового vault: проверьте iCloud-симлинки, права контейнеров, поведение cron при конфликте и восстановление из backup. После этого можно расширять систему: добавлять ботов для диктовки, парсинга статей и логирования задач.


