MAATRIX / Блог / Сколько RAM нужно для Documenso

Сколько RAM нужно для Documenso

MAATRIX

Documenso — открытый аналог DocuSign: загружаете PDF, расставляете поля для подписи, отправляете ссылку получателям, документ подписывается криптографически и хранится у вас, а не у стороннего облака. Логичный вопрос при выборе сервера — сколько памяти реально нужно связке Next.js-приложения, PostgreSQL и модуля цифровой подписи PDF, и не окажется ли тариф на 1 ГБ ловушкой в момент, когда пять человек одновременно откроют документ на подпись. Разберём архитектуру Documenso по компонентам и дадим рабочий ориентир для личного использования, малой команды и юрфирмы с потоком договоров.

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

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

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

Из чего состоит Documenso и что ест память

Documenso — это монолитное веб-приложение на Next.js (React на сервере и клиенте, единый процесс Node.js), под капотом Prisma ORM и PostgreSQL как основное хранилище. По официальной документации проекта минимальный набор для self-hosted инсталляции — три части:

  • Веб-приложение (Next.js/Node.js) — отдаёт интерфейс, обрабатывает API-запросы, рендерит страницы редактирования полей подписи. Один процесс Node.js держит в памяти скомпилированный бандл приложения плюс рантайм V8 — база в 250–400 МБ есть уже на старте, ещё до первого пользователя.
  • PostgreSQL — хранит документы (метаданные, не всегда сами PDF-файлы), получателей, поля подписи, историю событий (audit trail — кто и когда открыл, подписал, отклонил документ). Требование к версии — PostgreSQL 13+.
  • Хранилище файлов — сами PDF по умолчанию можно писать на локальный диск контейнера/сервера, либо подключить S3-совместимое хранилище (переменные NEXT_PRIVATE_UPLOAD_TRANSPORT=s3 и связанные с ним NEXT_PRIVATE_UPLOAD_*). На RAM это не влияет напрямую — диск и сеть, а не память, — но при локальном хранении на слабом сервере стоит следить за свободным местом отдельно от расчёта памяти.

Отдельная деталь, которую часто упускают: обработка самого PDF (встраивание подписи, сертификата, штампа) — операция, которая на короткое время требует заметно больше памяти, чем обычный HTTP-запрос: файл целиком читается в память процесса Node.js, обрабатывается через pdf-lib и криптографический модуль подписи, затем записывается обратно. Для документа в 5–10 страниц это доли секунды и десятки мегабайт, но для PDF на 50+ страниц со сканами пиковое потребление одного запроса подписи может кратно превышать базовый расход в состоянии покоя.

Обязательный сертификат для подписи: единоразовый расход, не постоянный

Documenso требует сертификат для криптографической подписи PDF — по умолчанию self-hosted инсталляция использует локальный .p12-файл (переменная NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH), который либо кладут вручную, либо генерируют самоподписанным сертификатом для тестового контура:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
  -days 3650 -nodes -subj "/CN=documenso-local"
openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem \
  -passout pass:changeme

Сама операция подписи с этим сертификатом — разовое действие с известной криптографической нагрузкой (RSA-подпись хэша), она не держит память постоянно занятой и не требует отдельного планирования RAM сверх запаса под пиковую обработку PDF, описанного выше. Для продакшена вместо self-signed лучше использовать сертификат от реального удостоверяющего центра — юридическая значимость подписи зависит от доверия к сертификату, а не от нагрузки на сервер.

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

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

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

Сколько закладывать: ориентир по сценариям

Ниже — инженерный ориентир, а не измеренный бенчмарк: он строится на архитектуре (один процесс Node.js + PostgreSQL + периодические пики на обработке PDF), а не на нагрузочном тестировании. Точные цифры у вас сдвинутся в зависимости от версии Node.js, объёма загружаемых документов и настроек PostgreSQL.

RAM сервераДля кого подходитКомментарий
1 ГБЛичное использование, тест перед покупкой, единичные документы на подписьРаботает, но впритык: пик на обработке PDF в 20+ страниц вместе с PostgreSQL может упереться в своп
2 ГБФрилансер, малый бизнес, несколько договоров в деньКомфортный минимум для реального рабочего процесса без постоянного контроля памяти
4 ГБОтдел, юрфирма, десятки документов в день, несколько сотрудников работают одновременноЗапас под параллельную обработку PDF и рост базы событий (audit trail копится с каждым действием)
8 ГБ+Организация с потоком в сотни документов, интеграция с внешними системами через API/вебхукиОбычно берут не под сам Documenso, а под соседние сервисы на том же сервере — почтовую очередь, S3-совместимое хранилище, мониторинг

Если сомневаетесь между соседними уровнями — берите больший: разница в цене между тарифами на 2 и 4 ГБ обычно меньше, чем цена простоя из-за OOM-killer в момент, когда клиент ждёт подписанный договор. Общий подход к запасу по памяти для любого сервиса разобран в статье сколько оперативной памяти закладывать с запасом.

Запуск в Docker Compose: минимальная рабочая конфигурация

Официальный путь установки Documenso — Docker Compose с двумя сервисами: приложение и PostgreSQL. Минимальный рабочий файл выглядит так:

services:
  documenso:
    image: documenso/documenso:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NEXTAUTH_URL=https://sign.example.com
      - NEXTAUTH_SECRET=замените_на_случайную_строку
      - NEXT_PRIVATE_ENCRYPTION_KEY=замените_на_32_символа
      - NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=замените_на_другую_32_символа
      - NEXT_PRIVATE_DATABASE_URL=postgresql://documenso:changeme@db:5432/documenso
      - NEXT_PRIVATE_DIRECT_DATABASE_URL=postgresql://documenso:changeme@db:5432/documenso
      - NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12
      - NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS=changeme
      - NEXT_PRIVATE_SMTP_TRANSPORT=smtp-auth
      - NEXT_PRIVATE_SMTP_HOST=smtp.example.com
      - NEXT_PRIVATE_SMTP_PORT=587
    volumes:
      - ./cert.p12:/opt/documenso/cert.p12
    depends_on:
      - db

  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      - POSTGRES_USER=documenso
      - POSTGRES_PASSWORD=changeme
      - POSTGRES_DB=documenso
    volumes:
      - ./pgdata:/var/lib/postgresql/data

Два контейнера — это два независимых процесса с собственным базовым оверхедом: Node.js-приложение (250–400 МБ в покое) плюс PostgreSQL (по умолчанию скромный, но растёт с shared_buffers). На сервере в 1 ГБ это ощутимая доля памяти ещё до первого запроса — общие принципы того, как Docker и лимиты контейнеров расходуют RAM, разобраны в статье Docker: лимиты CPU и памяти. Если планируете держать на том же сервере ограничение по контейнерам, стоит явно задать mem_limit для documenso, чтобы пик на обработке крупного PDF не утащил в своп весь сервер целиком.

PostgreSQL: что действительно растёт с объёмом документов

База Documenso хранит не сами PDF (при локальном или S3-хранилище файлы лежат отдельно), а метаданные: документы, поля подписи, получателей и, что важнее всего для роста базы, — журнал событий. Каждое открытие документа получателем, каждый просмотр, каждая подпись пишется в audit trail отдельной записью. Для юрфирмы с активным документооборотом это означает, что база растёт быстрее, чем кажется на глаз по количеству самих договоров.

Базовая настройка PostgreSQL для инсталляции с умеренным потоком документов:

# postgresql.conf
shared_buffers = 256MB
effective_cache_size = 768MB
work_mem = 8MB
maintenance_work_mem = 64MB
max_connections = 50

max_connections можно держать умеренным — Documenso не открывает по соединению на каждого пользователя в браузере, основная нагрузка идёт через пул на стороне Prisma. Если параллельно с Documenso на сервере крутятся другие сервисы с PostgreSQL, общие принципы установки и тюнинга разобраны в статьях установка и настройка PostgreSQL на VPS и тюнинг PostgreSQL на VPS — методика применима и к базе Documenso без изменений.

Фоновая обработка: письма, вебхуки, истечение срока документов

У Documenso есть не только синхронный путь запрос-ответ в браузере, но и фоновые задачи: отправка email-уведомлений (получателю пришло приглашение подписать, отправителю — что документ подписан), доставка вебхуков во внешние системы при интеграции по API, а также плановая проверка документов с истёкшим сроком действия. В self-hosted версии эти задачи выполняются тем же процессом Node.js, что обслуживает веб-интерфейс, — отдельного тяжёлого воркера с собственным пулом памяти, как у некоторых очередей задач, здесь нет, но каждая параллельная фоновая операция добавляет свою долю к общей нагрузке на процесс.

Практический вывод: если в сервисе одновременно происходит рассылка приглашений на пакет из десятков документов и пользователи активно работают в интерфейсе, пиковая нагрузка складывается, а не размазывается по отдельным процессам. На серверах от 2 ГБ это некритично, но на 1 ГБ стоит закладывать, что массовая рассылка — не самый подходящий момент для одновременного импорта большого PDF. Сам SMTP-транспорт памяти почти не ест — это тонкий клиент, отправляющий сообщения на внешний сервер; если для рассылок используется собственный SMTP-релей на том же сервере, его расход считается отдельно от Documenso.

Что растёт со временем и что на это не влияет

Стоит развести два типа роста, которые легко перепутать при планировании сервера:

  • Растёт диск, не RAM напрямую: сами PDF-документы при локальном хранении, история версий, вложения. Это увеличивает объём файловой системы и — при активном использовании буферов ОС для кэширования файлов — косвенно влияет на то, сколько свободной памяти остаётся системе под дисковый кэш, но не требует роста shared_buffers PostgreSQL или памяти процесса Node.js напрямую.
  • Растёт RAM ощутимо: число одновременных активных пользователей (сотрудники, редактирующие поля подписи, получатели, открывающие документ по ссылке в один момент времени) и размер отдельных PDF, проходящих через обработку подписи. Долгоживущих сессий, занимающих память постоянно, у Documenso нет — как и большинство веб-приложений, память освобождается по завершении запроса.

Если Documenso — часть более широкой инфраструктуры документооборота с хранением файлов на S3-совместимом сервисе, стоит закладывать память отдельно под каждый компонент: сам S3-сервер (например, MinIO) держит собственный процесс с базовым потреблением, разобранным в статье сколько RAM нужно для MinIO — это не заменяет расчёт под Documenso, а складывается с ним, если оба сервиса на одной машине.

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

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

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

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

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

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

Хватит ли 512 МБ RAM для теста?

Технически контейнеры запустятся, но Node.js-приложение и PostgreSQL на такой машине будут постоянно бороться за память — своп включится уже на этапе миграций базы при первом старте. Для реального теста берите минимум 1 ГБ, а лучше сразу 2 ГБ, чтобы не путать нехватку памяти с реальными багами при первом знакомстве с сервисом.

Можно ли использовать SQLite вместо PostgreSQL, чтобы сэкономить память?

Нет, Documenso официально поддерживает только PostgreSQL — это жёсткое требование архитектуры (Prisma-схема писалась под PostgreSQL-специфичные типы), переключение на SQLite не документировано и не поддерживается.

Нужен ли Redis для Documenso?

В стандартной self-hosted поставке — нет, обязательных зависимостей от Redis документация не описывает. Если у вас на сервере уже есть Redis для других сервисов, добавлять его ради Documenso без явной необходимости смысла нет.

Растёт ли расход памяти с количеством отправленных документов?

Не напрямую в моменте — Node.js не держит все документы в памяти между запросами. Косвенно да: чем больше строк в таблицах audit trail и документов, тем больше пользы от увеличенного shared_buffers в PostgreSQL, чтобы выборки списков и поиск оставались быстрыми без обращения к диску.

Что произойдёт, если памяти не хватит в момент подписи большого PDF?

Скорее всего процесс Node.js упадёт по OOM или запрос завершится ошибкой 500 без записи подписи в документ — пользователь увидит, что подписание не завершилось, и должен будет повторить попытку. Хронически это лечится либо увеличением RAM, либо ограничением максимального размера загружаемого файла на уровне прокси (nginx client_max_body_size) и самого приложения.

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

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

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