Как установить и настроить AFFiNE на VPS
Notion удобен, пока не упираешься в цену подписки за команду, лимиты блоков на бесплатном плане и мысль о том, что все заметки и документы лежат на чужих серверах в другой юрисдикции. AFFiNE — открытый инструмент, который пытается закрыть ту же нишу: документы, канбан-доски и базы данных в одном рабочем пространстве, но развёрнутом на вашем VPS, где данные принадлежат только вам. Разберём, как поставить его через Docker Compose, настроить домен с HTTPS и не потерять данные при первом обновлении.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое AFFiNE и когда он оправдан вместо Notion
AFFiNE — open-source редактор рабочего пространства, который объединяет три инструмента сразу: блочный документ-редактор (как в Notion), канбан-доски для задач и bidirectional-ссылки между страницами (как в Obsidian). Один и тот же контент можно переключать между режимом документа и режимом визуального холста — это фирменная фишка проекта, которой нет ни у Notion, ни у Outline.
Из практических отличий, которые важны при выборе self-host варианта:
- вход по обычному email и паролю работает из коробки — не нужен внешний OAuth-провайдер, как в Outline, первый зарегистрированный пользователь становится администратором рабочего пространства;
- есть локальный режим без сервера вовсе (данные в браузере/десктоп-приложении) и облачный self-host режим с синхронизацией между устройствами — статья про второй, он и даёт смысл держать VPS;
- редактор написан на CRDT (Yjs) — это тот же класс технологий, что у Google Docs для совместного редактирования, конфликтов при одновременной правке практически не возникает;
- проект молодой и активно меняется: между релизами бывают миграции схемы базы и правки формата хранения, поэтому бэкапы перед обновлением — не формальность, а необходимость (подробнее — в разделе про бэкапы).
Из ограничений: по сравнению с Notion экосистема интеграций и готовых шаблонов заметно скромнее, а сообщество self-host пользователей меньше, чем у зрелых проектов вроде Outline или Wiki.js — если что-то ломается на нестандартной конфигурации, ответ на форуме можно ждать дольше. Для команды или соло-пользователя, который хочет держать заметки и канбан под своим контролем и готов иногда следить за обновлениями руками, это разумный компромисс.
Требования к серверу и подготовка VPS
AFFiNE в self-host режиме — это сам сервер плюс PostgreSQL и Redis, то есть по составу стек похож на Outline, но интерфейс заметно тяжелее по фронтенду (полноценный canvas-редактор в браузере), поэтому закладывайте запас по CPU для рендеринга у клиентов, а не только по памяти сервера.
Стартовая конфигурация для соло-пользователя или небольшой команды до 10-15 человек:
- 2 vCPU, 4 ГБ RAM — меньше тоже запустится, но при активной синхронизации нескольких клиентов сервер начинает подтормаживать;
- 20-30 ГБ SSD — сам сервис лёгкий, место съедают вложения (картинки, файлы в документах) и дампы базы для бэкапов;
- Ubuntu 24.04 LTS или Debian 12;
- домен или поддомен, направленный на IP сервера, например
notes.example.com— без HTTPS часть функций (загрузка вложений, PWA-режим) работает нестабильно.
Обновите систему и, если Docker ещё не установлен, поставьте его — порядок с нуля для Ubuntu и Debian разобран в статье установка Docker с нуля:
apt update && apt upgrade -y
adduser deploy
usermod -aG sudo,docker deploy
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверУстановка AFFiNE через Docker Compose
Официальный self-host вариант AFFiNE состоит из трёх контейнеров: сам сервер, PostgreSQL для данных и Redis для очередей и кэша сессий. Создайте директорию проекта:
mkdir -p /opt/affine/{config,storage,pgdata}
cd /opt/affine
Файл docker-compose.yml:
# /opt/affine/docker-compose.yml
services:
affine:
image: ghcr.io/toeverything/affine-graphql:stable
container_name: affine
restart: unless-stopped
ports:
- "3010:3010"
- "5555:5555"
volumes:
- ./config:/root/.affine/config
- ./storage:/root/.affine/storage
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://affine:${POSTGRES_PASSWORD}@postgres:5432/affine
- AFFINE_SERVER_HOST=notes.example.com
- AFFINE_SERVER_HTTPS=true
- NODE_OPTIONS=--max-old-space-size=1024
depends_on:
redis:
condition: service_started
postgres:
condition: service_healthy
migration:
condition: service_completed_successfully
migration:
image: ghcr.io/toeverything/affine-graphql:stable
command: ["sh", "-c", "node ./scripts/self-host-predeploy.js"]
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://affine:${POSTGRES_PASSWORD}@postgres:5432/affine
depends_on:
redis:
condition: service_started
postgres:
condition: service_healthy
redis:
image: redis:7-alpine
container_name: affine_redis
restart: unless-stopped
postgres:
image: postgres:16-alpine
container_name: affine_postgres
restart: unless-stopped
environment:
- POSTGRES_USER=affine
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=affine
volumes:
- ./pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U affine -d affine"]
interval: 10s
timeout: 5s
retries: 5
Замените notes.example.com на реальный домен и сгенерируйте пароль базы в .env рядом с compose-файлом:
echo "POSTGRES_PASSWORD=$(openssl rand -base64 24)" > .env
chmod 600 .env
Запуск:
docker compose up -d
docker compose logs -f affine
Контейнер migration должен один раз отработать и завершиться со статусом Exited (0) — это нормально, он прогоняет миграции схемы и выходит. Если в логах affine видно, что сервер поднялся на порту 3010 без ошибок подключения к базе, можно переходить к первому запуску.
Важный нюанс с версиями: тег stable подтягивает последний стабильный релиз при каждом docker compose pull, что удобно для быстрого старта, но неудобно для предсказуемых обновлений — на проде разумнее зафиксировать конкретный тег образа из релизов проекта и обновлять его осознанно, а не при случайном pull.
Домен, TLS и реверс-прокси
AFFiNE слушает 3010 (веб-интерфейс и API) и 5555 (WebSocket для realtime-синхронизации документов) на самом сервере. Наружу оба порта нужно отдать через реверс-прокси с TLS-сертификатом — без этого совместное редактирование через WebSocket может не подниматься из-за смешанного контента (HTTPS-страница, но незашифрованный WS).
Проще всего — через Caddy, он сам получает и продлевает сертификат Let's Encrypt; подробности установки в статье установка и настройка Caddy с авто-SSL на VPS. Минимальный Caddyfile:
notes.example.com {
reverse_proxy /graphql* 127.0.0.1:3010
reverse_proxy /socket.io* 127.0.0.1:5555
reverse_proxy 127.0.0.1:3010
}
Если вы уже используете Nginx под другие сайты на этом VPS, то же самое можно сделать классическим реверс-прокси с явным пробросом заголовков апгрейда для WebSocket — общий подход разобран в статье Nginx как реверс-прокси на VPS, для AFFiNE в блок location достаточно добавить proxy_set_header Upgrade $http_upgrade; и proxy_set_header Connection "upgrade"; для пути /socket.io/.
Перезапустите прокси-сервер, откройте https://notes.example.com — при первом заходе AFFiNE покажет форму создания администратора: email, пароль, название рабочего пространства. Это отличие от Outline, где нужен внешний OAuth ещё до первого входа, — здесь достаточно свежего сервера и открытого домена.
Первая настройка и переход с Notion
После создания администратора стоит сразу проверить несколько вещей:
- регистрацию новых пользователей — по умолчанию в некоторых сборках она открыта всем, кто попадёт на домен, для приватного инстанса её стоит выключить в настройках рабочего пространства и добавлять участников по прямому приглашению;
- SMTP для писем-приглашений и уведомлений — без него новые участники не получат ссылку на вход;
- лимит на размер вложений — по умолчанию он рассчитан на разумные файлы, для сканов и больших PDF имеет смысл проверить настройку до того, как кто-то упрётся в отказ загрузки.
Перенос из Notion делается через экспорт рабочего пространства Notion в формате Markdown & CSV и последующий импорт в AFFiNE — структура страниц и вложенные документы переносятся достаточно надёжно, а вот сложные блоки (связанные базы данных, формулы, синхронизированные блоки) стоит проверить вручную после импорта: конвертация форматов между разными редакторами никогда не бывает стопроцентной.
Бэкап данных и обновление без потерь
Всё содержимое AFFiNE живёт в двух местах: PostgreSQL (структура документов, метаданные, права) и volume storage (бинарные вложения — картинки, файлы). Бэкапить нужно оба места согласованно.
Дамп базы:
docker compose exec postgres pg_dump -U affine affine > /opt/affine/backups/affine-$(date +%F).sql
Резервная копия вложений — обычный архив volume:
tar czf /opt/affine/backups/storage-$(date +%F).tar.gz -C /opt/affine storage
Обе команды стоит собрать в один cron-скрипт с ротацией старых копий и, желательно, выгрузкой архивов за пределы самого VPS — если диск сервера умрёт вместе с бэкапами на нём же, толку от такого бэкапа не будет.
Перед обновлением образа — особенно с учётом того, что проект активно развивается и между версиями случаются миграции схемы — обязательно снимайте свежий дамп прямо перед pull:
docker compose exec postgres pg_dump -U affine affine > pre-update-backup.sql
docker compose pull
docker compose up -d
Контейнер migration снова отработает при старте и применит накопившиеся изменения схемы автоматически. Если после обновления сервер не поднимается или в логах видны ошибки миграции — откатите тег образа на предыдущий рабочий и восстановите базу из дампа, снятого перед обновлением, а уже потом разбирайтесь с причиной на тестовом окружении.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем AFFiNE принципиально отличается от Outline и Notion?
AFFiNE совмещает документ-редактор, канбан и граф связей в одном приложении с переключением видов, тогда как Outline — специализированная вики для документации, а Notion — облачный сервис с похожим набором функций, но без self-host варианта.
Нужен ли OAuth-провайдер для входа, как в Outline?
Нет, у AFFiNE встроенная авторизация по email и паролю, внешний провайдер не обязателен — это упрощает первый запуск.
Можно ли запустить AFFiNE без Postgres и Redis, совсем просто?
Есть локальный режим (браузер или десктоп-приложение) без сервера вовсе, но там нет синхронизации между устройствами и совместной работы — для этого и нужен self-host стек, описанный выше.
Как перенести существующие заметки из Notion?
Экспортируйте рабочее пространство Notion в Markdown & CSV и импортируйте архив в AFFiNE — простые страницы и структура переносятся хорошо, сложные блоки (связанные базы, формулы) проверьте вручную после импорта.
Что делать, если после обновления сервер не стартует?
Проверьте логи контейнера migration на ошибки схемы, при необходимости откатите тег образа в docker-compose.yml на предыдущую рабочую версию и восстановите базу из дампа, снятого перед обновлением.
Сколько RAM нужно, если в команде 30-50 человек?
Точных цифр без вашей реальной нагрузки никто не даст — начните с 4 vCPU/8 ГБ RAM и следите за потреблением PostgreSQL и самого контейнера affine, при активной совместной работе именно они растут первыми.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →