Миграция с Outline на Docmost: неделя работы и один неприятный сюрприз
Мы разворачивали Outline по стандартной инструкции почти два года назад, и всё это время он в целом устраивал — быстрый, с приятным Markdown-редактором, но упирался в два ограничения, которые со временем стали раздражать сильнее: вход только через OAuth-провайдера (без варианта «просто логин и пароль» для двух подрядчиков без корпоративной почты) и жёсткое требование S3-совместимого хранилища под любые вложения, даже на маленьком инстансе. Docmost выглядел логичным следующим шагом — тоже self-hosted, тоже открытый исходный код, но с локальным хранением файлов из коробки и собственной формой входа. Ниже — что реально происходило при переезде: что пошло не так при экспорте и импорте, где было больнее всего с правами доступа и какой сюрприз всплыл уже после того, как все решили, что миграция закончена.
Содержание
- Почему вообще уходили с Outline
- Подготовка: что сделали до первого экспорта
- Экспорт из Outline и импорт в Docmost: что автоматика не смогла
- Вложения и файлы — самая долгая часть переезда
- Права доступа и пространства: пришлось передумать структуру
- Что стало лучше после переезда
- Неприятный сюрприз, который вылез через две недели
Почему вообще уходили с Outline
Формальный повод обновиться был, но решающими стали три практических неудобства, накопившихся за время эксплуатации.
Первое — авторизация. Outline из коробки не имеет собственной формы «email + пароль», только вход через сторонний OAuth-провайдер (Google, Slack, Microsoft или generic OIDC). Для команды из сотрудников с рабочей почтой это не проблема, но у нас регулярно появляются внешние подрядчики на короткие проекты, которым не хочется заводить учётку в корпоративном Google Workspace ради доступа к паре страниц документации. Пришлось либо заводить их в OIDC-провайдере вручную, либо давать временный доступ через общий аккаунт — оба варианта неудобные и с точки зрения безопасности сомнительные (сама по себе настройка OAuth у Outline не самая простая — типовые проблемы вроде redirect_uri_mismatch разобраны отдельно в статье про частые ошибки Outline на сервере).
Второе — обязательное S3-хранилище. С определённого момента разработчики Outline убрали из официальной сборки локальную файловую систему как backend для вложений — без S3-совместимого хранилища (MinIO, Cloudflare R2, любой другой совместимый провайдер) картинки и файлы вставить в документ нельзя. Для вики с парой сотен страниц заводить отдельный MinIO-контейнер только ради вложений — лишняя часть инфраструктуры, которую тоже нужно бэкапить и мониторить, особенно если сам сервер под вики брался с расчётом на скромные требования по памяти (сколько реально нужно ресурсов под Outline, мы прикидывали ещё при первой установке).
Третье — субъективное, но реальное: интерфейс Outline заточен под «документ как файл в папке», а часть команды последние пару лет привыкла работать в блочных редакторах вроде Notion — с вложенными блоками, таблицами прямо внутри страницы, простым drag-and-drop структуры. Docmost по интерфейсу и модели документа заметно ближе именно к этому паттерну, плюс поддерживает вход по email и паролю параллельно с SSO и хранит вложения на локальном диске без обязательного S3 — это и решило вопрос в его пользу.
Отдельно: мы не рассматривали это как переход на «более мощный» инструмент. MediaWiki или Confluence решают похожую задачу тяжеловесной, классической wiki-моделью с ревизиями и сложной разметкой — с другой философией и порогом входа для нетехнических сотрудников. Нам нужен был инструмент того же класса, что и Outline, просто без двух конкретных ограничений.
Подготовка: что сделали до первого экспорта
Прежде чем трогать боевую вики, подняли тестовый Docmost на отдельном VPS — минимальная конфигурация через docker-compose.yml с Postgres, Redis и самим приложением. Ключевые переменные окружения (сверяйтесь с актуальным .env.example в репозитории Docmost — имена и набор параметров между релизами могут отличаться):
services:
docmost:
image: docmost/docmost:latest
depends_on:
- db
- redis
environment:
APP_URL: "https://wiki-test.example.com"
APP_SECRET: "сгенерированный-случайный-ключ"
DATABASE_URL: "postgresql://docmost:pass@db:5432/docmost?schema=public"
REDIS_URL: "redis://redis:6379"
STORAGE_DRIVER: "local"
ports:
- "3010:3000"
volumes:
- docmost_data:/app/data/storage
db:
image: postgres:16
environment:
POSTGRES_DB: docmost
POSTGRES_USER: docmost
POSTGRES_PASSWORD: pass
volumes:
- db_data:/var/lib/postgresql/data
redis:
image: redis:7
volumes:
docmost_data:
db_data:
На тестовом инстансе сделали три вещи до того, как трогать реальные данные: прогнали пробный экспорт из Outline на десятке документов, чтобы увидеть, что вообще происходит при импорте; составили список всех коллекций (collections) в Outline и владельцев каждой — пригодилось на этапе прав доступа; сняли полный бэкап продовой базы Outline (pg_dump) и отдельно скачали содержимое S3-бакета с вложениями — на случай отката или сверки с оригиналом задним числом. Последний пункт оказался не формальностью — сверяться с оригиналом пришлось не один раз, особенно на этапе вложений.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSЭкспорт из Outline и импорт в Docmost: что автоматика не смогла
У Outline есть встроенный экспорт коллекций в Markdown-архив (ZIP с файлами .md и вложенной структурой папок по вложенности документов). Готового «мигратора Outline → Docmost» на момент переезда не было — Docmost поддерживал импорт в основном из Notion-подобных экспортов и обобщённого Markdown, так что пришлось работать через промежуточный формат и руками разбирать, что не легло ровно. Docmost по структуре папок сам восстанавливает иерархию страниц внутри пространства (space) — вложенная папка становится вложенной страницей, это работает предсказуемо.
Часть контента перенеслась без потерь: заголовки, абзацы, списки, таблицы средней сложности, код в тройных бэктиках. Проблемы начались там, где Outline хранит внутри документа не чистый Markdown, а собственные ProseMirror-структуры, которые при экспорте теряют часть смысла:
- Вложенные чек-листы. Плоские чек-листы (
- [ ] задача) экспортировались нормально, а дочерние пункты внутри одного чек-листа иногда теряли вложенность и превращались в плоский список того же уровня. - Упоминания пользователей (
@Имя). При экспорте превращались в обычный текст без ссылки на профиль — ожидаемое поведение, но проверять пришлось документ за документом там, где упоминание было значимо по контексту («ответственный: @Имя»). - Встроенные комментарии. Не переносятся вообще — Markdown-экспорт содержит только тело документа, ветки обсуждений остаются только в оригинальной базе Outline. Для документов с активной историей это значило потерю контекста решений («почему написано именно так»).
- Таблицы с объединёнными ячейками разворачивались в обычную сетку без объединения — два-три документа со сравнительными матрицами пришлось переверстать вручную.
Уже на этапе импорта в Docmost добавились ещё две проблемы. Изображения, вставленные в Markdown как ссылки на прежний S3-бакет Outline (!alt), не скачиваются и не перезаливаются в хранилище Docmost автоматически — остаются внешними ссылками, пока жив старый бакет (подробнее — в разделе про вложения ниже). А внутренние ссылки между документами Outline (вида см. договор) после импорта остаются текстом со старым путём и никуда не ведут — пришлось прогонять контент через скрипт, который искал такой паттерн по всем документам и подсказывал, где именно чинить ссылку руками на актуальный адрес в Docmost.
Практический вывод: прежде чем считать импорт готовым, стоит выборочно открыть 15–20 документов из разных коллекций и разного возраста (старые страницы форматированы иначе, чем недавние) и свериться с оригиналом визуально — раз файл импортировался без ошибок, это ещё не значит, что содержимое перенеслось верно.
Вложения и файлы — самая долгая часть переезда
Это оказался самый трудоёмкий этап миграции, и именно здесь стоит закладывать больше времени, чем кажется на первый взгляд.
Готового инструмента «перелить вложения из S3-бакета Outline в локальное хранилище Docmost с автоматической подменой ссылок в тексте» не было, поэтому процесс собрали из нескольких шагов: скачали всё содержимое S3-бакета через aws s3 sync (или аналогичный клиент для совместимого хранилища) в локальную папку с сохранением путей; прогнали по импортированным Markdown-файлам скрипт, который находил ссылки на старый бакет и сопоставлял их со скачанными файлами по пути в URL; загружали файлы в Docmost через интерфейс редактора (массовой загрузки вложений через API/CLI без открытия каждого документа на тот момент не было) и заменяли ссылку в тексте на новую, уже локальную; по каждому документу проверяли, что картинка реально отображается, а не просто ссылка выглядит правдоподобно.
Больнее всего было с документами, где на одной странице было 15–20 картинок (в основном скриншоты для внутренних инструкций) — такие страницы обрабатывали вручную дольше остальных вместе взятых. Отдельная проблема — файлы, у которых в Outline уже на момент экспорта была битая ссылка (сотрудник удалил файл из S3 напрямую, не через интерфейс Outline, и вики об этом не знала) — таких оказалось немного, но искать их пришлось тем же способом, вручную открывая документ за документом.
Практический совет, если планируете похожий переезд: не пытайтесь автоматизировать перенос вложений «на всякий случай под все форматы сразу» — проще сначала прогнать выборку из 20–30 документов руками, посчитать, сколько времени уходит на один документ в среднем по вашему контенту, и уже от этого числа планировать, сколько календарных дней закладывать на весь объём.
Права доступа и пространства: пришлось передумать структуру
Модели доступа у Outline и Docmost разные, и прямого сопоставления «один в один» не получилось.
| Outline | Docmost | |
|---|---|---|
| Верхний уровень | Коллекции (collections) | Пространства (spaces) |
| Права на коллекцию/пространство | Публичная / приватная / вручную по группам | Роли участников пространства (admin/member/viewer и приглашение по email) |
| Права на отдельный документ | Наследуются от коллекции, точечно переопределяются | Наследуются от пространства, есть отдельные права на страницу |
| Гостевой доступ | Через share-ссылку с токеном | Публичная ссылка на страницу с отдельным переключателем |
В Outline у нас было около десятка коллекций с точечными исключениями по документам — например, коллекция «Финансы» была закрыта для всех, кроме нескольких человек, но один отчёт внутри неё намеренно был открыт для всей команды. При переезде в Docmost такую структуру пришлось не копировать, а пересобирать: развели по разным пространствам то, что в Outline держалось в одной коллекции с точечными исключениями, а общедоступный отчёт вынесли в отдельное пространство с более широким доступом. Дословный перенос привёл бы либо к слишком открытому доступу там, где не надо, либо к раздаче прав документ за документом вручную — оба варианта хуже, чем один раз передумать иерархию под новую модель.
Заодно проверили, кто состоит в каждой группе доступа — за два года в правах Outline накопились «хвосты»: люди, уволившиеся полгода назад, но не выведенные из закрытых коллекций. Миграция — удобный повод почистить такие вещи, а не переносить старые ошибки в новую систему один в один.
Что стало лучше после переезда
После того как контент, вложения и права были выверены, стали заметны практические плюсы, ради которых всё затевалось:
- Локальный вход по email и паролю — подрядчикам больше не нужно заводить учётку в корпоративном OAuth-провайдере ради доступа к паре страниц. Для сотрудников с рабочей почтой SSO через тот же OIDC-провайдер остался доступен параллельно.
- Вложения без обязательного S3. Локальное хранение на диске убрало из инфраструктуры отдельный MinIO-контейнер, который раньше нужно было бэкапить и мониторить отдельно от самой вики.
- Более комфортный редактор для нетехнических сотрудников — блочная модель с простым drag-and-drop оказалась ближе к тому, к чему люди привыкли в Notion, и жалоб «не понимаю, как переместить раздел» стало заметно меньше. При этом мы по-прежнему платим только за сервер, а не за место в команде — если раньше сравнивали, во что обходится документ в Notion против своей вики, то с блочным self-hosted редактором это сравнение стало ещё нагляднее.
- Совместное редактирование в реальном времени ощущается стабильнее, чем в Outline, — на практике реже видели рассинхрон курсоров при одновременной правке одного раздела.
Ничего из этого не заработало само по себе без донастройки — SSO пришлось перенастраивать заново под Docmost, а не копировать конфиг из Outline, потому что структура OIDC-переменных у приложений отличается.
Неприятный сюрприз, который вылез через две недели
Сама активная фаза переезда — экспорт, импорт, разбор форматирования, перенос вложений, настройка прав — заняла примерно рабочую неделю, растянутую на чуть больший календарный срок, потому что часть правок делали в фоне между другими задачами. По завершении неделю продержали старый Outline в режиме «только для чтения» на случай, если кто-то найдёт документ, который не перенёсся, — ничего критичного не всплыло, и через две недели после переключения основную инстанцию остановили и вывели домен из DNS.
Именно тогда обнаружился сюрприз. Скрипт для поиска битых внутренних ссылок написали не сразу — документы из самой ранней пробной партии экспорта проверяли визуально выборочно, а не построчным поиском по паттерну, и несколько ссылок в старых, редко открываемых документах остались в исходном виде, указывая на домен Outline. Пока старый сервер отвечал, ссылки формально работали, хотя вели уже не туда, — и это маскировало проблему все две недели, пока домен не выключили. Как только DNS-запись убрали, ссылки начали возвращать ошибку, и заметили это не сразу, а когда сотрудник пожаловался, что не может открыть архивный регламент из старой инструкции по онбордингу.
Урок простой: тестовый период с параллельно работающим старым сервисом ловит скрытые проблемы только пока внимание к деталям высокое, в первые дни. Чем позже старую систему выключают, тем меньше у людей в памяти контекст, что и где могло сломаться. Правильный процесс — не полагаться на визуальную выборочную проверку, а сразу прогонять автоматический поиск по всем документам на паттерн ссылок на старый домен и повторить его ещё раз непосредственно перед отключением старого сервера, а не только один раз на этапе импорта.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько реально заняла вся миграция от начала до конца?
Активная работа уложилась примерно в рабочую неделю, растянутую на больший календарный срок из-за фоновых задач. Плюс ещё две недели старый Outline держали доступным «только для чтения», прежде чем окончательно его выключить.
Есть ли готовый скрипт-мигратор Outline → Docmost?
На момент этой миграции прямого мигратора не было — использовали промежуточный Markdown-экспорт из Outline и обобщённый импорт Markdown в Docmost, с ручной доработкой форматирования, вложений и внутренних ссылок. Проверьте актуальную документацию Docmost перед своим переездом — за это время могли появиться дополнительные импортёры.
Что теряется безвозвратно при переезде через Markdown-экспорт?
Комментарии и ветки обсуждений — Markdown-экспорт Outline содержит только тело документа. Если история обсуждений важна, сохраните бэкап базы Outline отдельно, а не рассчитывайте, что всё перенесётся вместе с текстом.
Стоит ли отключать старую систему сразу после переезда?
Нет — держите её доступной хотя бы в режиме чтения пару недель, но не полагайтесь на то, что «раз никто не пожаловался — всё ок». Прогоните автоматическую проверку ссылок и вложений на паттерн старого домена ещё раз непосредственно перед отключением.
Нужен ли S3 для Docmost, если он не обязателен?
Нет, если объём вложений умеренный и сервер не в кластере из нескольких инстансов — локальное хранение на диске работает штатно. S3 имеет смысл добавить при отказоустойчивости на несколько серверов приложения или когда вложения уже не помещаются на диск одной машины.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →