MAATRIX / Блог / AFFiNE на Ubuntu 24.04: пошаговая установка

AFFiNE на Ubuntu 24.04: пошаговая установка

MAATRIX

Notion удобен, пока не упираешься в цену за команду, привязку к чужому облаку и невозможность выгрузить данные так, как вам нужно. AFFiNE — открытый инструмент, который совмещает заметки, вики-страницы и канбан-доски в одном рабочем пространстве, и при этом его можно поставить на собственный сервер за 15-20 минут. Ниже — рабочий способ развернуть self-hosted AFFiNE на Ubuntu 24.04 через Docker Compose, с доменом и HTTPS.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое AFFiNE и зачем его самостоятельный хостинг

AFFiNE — это редактор нового поколения, который не разделяет "документ" и "доску": один и тот же блок контента можно смотреть как страницу текста, как карточку канбана или как узел на whiteboard. Разработчики позиционируют его как альтернативу Notion + Miro в одном приложении, и по набору функций (блочный редактор, база данных внутри страниц, совместная работа) это действительно близко.

Причины ставить AFFiNE на свой сервер, а не пользоваться облачной версией:

  • Данные остаются у вас. Рабочие заметки, пароли к внутренним системам, черновики контрактов — всё это не покидает ваш VPS.
  • Нет лимитов бесплатного тарифа. Self-hosted версия не считает участников команды и объём хранилища так, как это делает облако.
  • Контроль над бэкапами. Вы сами решаете, как часто и куда сохранять данные — не полагаясь на политику стороннего сервиса.
  • Дешевле в пересчёте на команду. Один VPS обходится дешевле, чем платная подписка на 5-10 человек.

Минус тоже есть: обновления, бэкапы и мониторинг — ваша забота. Ниже разберём, как сделать это без лишней головной боли.

Требования к серверу

AFFiNE — не самое лёгкое self-hosted приложение: под капотом Node.js-бэкенд, PostgreSQL и Redis, плюс сам фронтенд. Для команды до 10-15 человек хватает:

ПараметрМинимумРекомендуется
CPU2 vCPU2-4 vCPU
RAM2 ГБ4 ГБ
Диск20 ГБ SSD40 ГБ SSD (с запасом под вложения)
ОСUbuntu 24.04 LTSUbuntu 24.04 LTS

Если планируете хранить много файлов и изображений внутри страниц (AFFiNE позволяет вставлять вложения прямо в документы), закладывайте диск с запасом — вложения растут быстро, а перенос данных на больший диск — лишняя операция, которую проще не делать в первый месяц.

Для локации выбирайте сервер ближе к команде: если пишете из России, разумный вариант — VPS в России или в Европе с прямым доступом, чтобы редактор не тормозил на автосохранении.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Подготовка сервера: Docker и домен

AFFiNE официально распространяется как Docker-образ, и через Docker Compose поднимается вместе с PostgreSQL и Redis одной командой. Если Docker ещё не установлен — разверните его по шагам из отдельной статьи, здесь просто чек-лист:

# обновляем систему
sudo apt update && sudo apt upgrade -y

# устанавливаем Docker (подробный разбор — в отдельной статье)
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
newgrp docker

# проверяем
docker --version
docker compose version

Полный разбор установки Docker с нуля, включая настройку прав и systemd — в статье Docker на Ubuntu 24.04: установка с нуля.

Заранее заведите A-запись домена (например, notes.example.com) на IP вашего сервера — она понадобится и для SSL, и для внешнего доступа команды. Если DNS ещё не настроен, для этого хватит пары минут в панели вашего регистратора.

Также сразу настройте firewall — открыты должны быть только SSH, HTTP и HTTPS:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Подробнее о настройке UFW и типичных ошибках — в статье UFW на Ubuntu 24.04: пошаговая установка.

Разворачиваем AFFiNE через Docker Compose

Создаём рабочую директорию и файл docker-compose.yml:

mkdir -p ~/affine && cd ~/affine
mkdir -p ./config ./storage
nano docker-compose.yml

Базовая конфигурация — AFFiNE self-hosted, PostgreSQL и Redis:

services:
  affine:
    image: ghcr.io/toeverything/affine:stable
    container_name: affine
    restart: unless-stopped
    ports:
      - "127.0.0.1:3010:3010"
    volumes:
      - ./config:/root/.affine/config
      - ./storage:/root/.affine/storage
    environment:
      - NODE_ENV=production
      - AFFINE_SERVER_HOST=notes.example.com
      - AFFINE_SERVER_HTTPS=true
      - DATABASE_URL=postgresql://affine:${DB_PASSWORD}@postgres:5432/affine
      - REDIS_SERVER_HOST=redis
    depends_on:
      - postgres
      - redis

  postgres:
    image: postgres:16
    container_name: affine-postgres
    restart: unless-stopped
    environment:
      - POSTGRES_USER=affine
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=affine
    volumes:
      - ./postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    container_name: affine-redis
    restart: unless-stopped
    volumes:
      - ./redis-data:/data

Обратите внимание: AFFINE_SERVER_HOST замените на ваш реальный домен, а порт AFFiNE проброшен только на 127.0.0.1 — наружу его открывать не будем, доступ пойдёт через reverse proxy с SSL.

Пароль от базы вынесен в переменную окружения — создаём файл .env рядом:

cat > .env << 'EOF'
DB_PASSWORD=замените_на_длинный_случайный_пароль
EOF

# генерация случайного пароля, если лень придумывать
openssl rand -base64 24

Запускаем стек:

docker compose up -d
docker compose logs -f affine

Первый старт может занять минуту-две — контейнер применяет миграции базы. Дожидаемся строки о том, что сервер слушает порт, и проверяем локально:

curl -I http://127.0.0.1:3010

Ответ 200 OK или 302 означает, что бэкенд поднялся и готов принимать запросы.

Reverse proxy и SSL-сертификат

AFFiNE в контейнере слушает только localhost — снаружи к нему нужно подключить nginx (или Caddy/Traefik, если уже используете их для других сервисов) как reverse proxy с TLS-терминацией. Ниже — вариант с nginx и Certbot, самый предсказуемый для одиночного домена.

Ставим nginx и Certbot:

sudo apt install -y nginx certbot python3-certbot-nginx

Конфиг виртуального хоста:

# /etc/nginx/sites-available/affine
server {
    listen 80;
    server_name notes.example.com;

    location / {
        proxy_pass http://127.0.0.1:3010;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        client_max_body_size 100M;
    }
}

Заголовки Upgrade/Connection важны — AFFiNE использует WebSocket для синхронизации между вкладками и участниками в реальном времени, без них совместное редактирование будет работать нестабильно. client_max_body_size увеличен, чтобы не резать загрузку крупных вложений.

Активируем сайт и получаем сертификат:

sudo ln -s /etc/nginx/sites-available/affine /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

sudo certbot --nginx -d notes.example.com

Certbot сам пропишет редирект на HTTPS и настроит автопродление. Если у вас уже развёрнут Traefik для других контейнеров, логичнее подключить AFFiNE через него — см. Traefik как reverse proxy для Docker, тогда отдельный nginx не понадобится вовсе.

После этого шага AFFiNE доступен по https://notes.example.com — открываем в браузере и должны увидеть экран создания первого рабочего пространства.

Первая настройка: workspace и пользователи

При первом заходе AFFiNE предложит создать локальное рабочее пространство (workspace) — это контейнер для документов, досок и участников. Если вы поднимаете инстанс для команды:

  1. Создайте workspace и сразу переключите его в режим Cloud/Sync (в self-hosted версии это синхронизация через ваш собственный сервер, не через облако AFFiNE) — иначе документы будут храниться только локально в браузере, без общего доступа.
  2. Зарегистрируйте аккаунт администратора — email и пароль, которые будут привязаны к вашему серверу.
  3. Пригласите участников по email — приглашения работают через встроенную систему, но для реальной отправки писем нужно настроить SMTP (см. ниже).
  4. Настройте права — AFFiNE поддерживает роли на уровне workspace (владелец, участник с правом редактирования, только чтение).

Для приглашений и уведомлений по email добавьте SMTP-переменные в docker-compose.yml в секцию affine:

      - MAILER_HOST=smtp.example.com
      - MAILER_PORT=587
      - MAILER_USER=noreply@example.com
      - MAILER_PASSWORD=${SMTP_PASSWORD}
      - MAILER_SENDER=noreply@example.com

После изменения переменных перезапускаем сервис:

docker compose up -d affine

Без корректного SMTP приглашения новых участников просто не дойдут — это частая причина, по которой self-hosted инстанс "не пускает" коллег в команду.

Бэкапы и обновления

Все данные AFFiNE живут в трёх местах: PostgreSQL (структура документов, метаданные), volume storage (вложения и файлы) и volume config (настройки инстанса). Бэкапить нужно все три.

Простой скрипт для регулярного бэкапа через cron:

#!/bin/bash
# /root/backup-affine.sh
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_DIR=/root/affine-backups
mkdir -p "$BACKUP_DIR"

cd ~/affine

# дамп базы
docker compose exec -T postgres pg_dump -U affine affine | gzip > "$BACKUP_DIR/db-$DATE.sql.gz"

# архив вложений и конфига
tar czf "$BACKUP_DIR/storage-$DATE.tar.gz" storage config

# чистим бэкапы старше 14 дней
find "$BACKUP_DIR" -type f -mtime +14 -delete
chmod +x /root/backup-affine.sh
crontab -e
# добавить строку:
0 3 * * * /root/backup-affine.sh

Для более надёжной схемы (с хранением копий вне сервера) стоит посмотреть в сторону выделенного инструмента — общий подход разобран в статье про BorgBackup на Ubuntu 24.04, его несложно направить и на директории AFFiNE.

Обновление до новой версии — обновление образа и перезапуск:

cd ~/affine
docker compose pull affine
docker compose up -d affine

Перед обновлением на проде обязательно делайте свежий бэкап базы — AFFiNE активно развивается, и между минорными версиями иногда меняется схема данных.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

AFFiNE точно заменяет Notion полностью?

Для заметок, вики и канбана — да, функциональность близка и местами удобнее (например, встроенный whiteboard). Но экосистема готовых шаблонов и интеграций у Notion пока шире — если команда завязана на конкретные Notion-плагины, миграция потребует проверки.

Можно ли обойтись без домена и SSL, только по IP?

Технически да, но синхронизация и совместная работа через браузер требуют HTTPS для части современных Web API — без сертификата часть функций (например, буфер обмена, некоторые уведомления) может работать нестабильно. Домен с бесплатным SSL от Let's Encrypt — самый простой путь.

Сколько ресурсов реально нужно на команду из 5-7 человек?

Ориентировочно 2 vCPU и 2-4 ГБ RAM достаточно с запасом — точная нагрузка зависит от объёма вложений и активности синхронизации, у вас цифры могут отличаться. Если заметите нехватку памяти, PostgreSQL и Redis — первые кандидаты на лимиты в Docker Compose.

Как перенести AFFiNE на другой сервер?

Останавливаете стек, копируете директории postgres-data, storage и config целиком на новый сервер, разворачиваете тот же docker-compose.yml и запускаете — данные подхватятся автоматически, так как PostgreSQL восстановит состояние из своего data-каталога.

AFFiNE поддерживает мобильные приложения при self-hosted установке?

Да, официальные приложения для iOS/Android и десктопные клиенты умеют подключаться к произвольному self-hosted серверу — в настройках клиента нужно указать адрес вашего домена вместо облака AFFiNE.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →