MAATRIX / Блог / Бэкап и восстановление Documenso

Бэкап и восстановление Documenso

MAATRIX

Documenso — открытая платформа электронной подписи документов, альтернатива DocuSign с прицелом на self-hosting и контроль над своими данными. Именно в этом контроле и кроется ловушка: если вы подняли Documenso на своём VPS, ответственность за сохранность подписанных договоров, ключей шифрования и сертификата подписи целиком на вас — никакого «облачного» бэкапа по умолчанию не будет. Ниже — рабочая схема бэкапа и восстановления self-hosted Documenso: что копировать, в каком порядке и какие два файла нельзя потерять ни при каких обстоятельствах.

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

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

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

Что хранит Documenso и почему бэкап — это не только база

Documenso построена на Next.js и Prisma поверх PostgreSQL, и большая часть состояния — сами документы, статусы подписания, пользователи, команды, шаблоны — действительно лежит в базе. Но полноценный бэкап требует ещё нескольких вещей, каждая из которых по-своему критична:

  • PostgreSQL — основная база: пользователи, документы (метаданные), получатели, поля для подписи, аудит-лог событий, API-ключи, настройки команд.
  • Файлы документов — сами PDF, которые загружают на подпись. В зависимости от конфигурации (NEXT_PRIVATE_UPLOAD_TRANSPORT) они хранятся либо на диске сервера (режим local), либо в S3-совместимом хранилище (режим s3), либо (в упрощённых установках) прямо в базе как blob — уточните у себя, какой транспорт задан в .env, это меняет всё остальное в бэкапе.
  • Ключи шифрованияNEXT_PRIVATE_ENCRYPTION_KEY и NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY (или их аналоги в вашей версии .env). Documenso шифрует часть чувствительных полей в базе этими ключами на уровне приложения. Потеряете ключи — потеряете возможность расшифровать эти поля, даже имея свежий дамп базы.
  • Сертификат для цифровой подписи PDF — файл сертификата (обычно .p12), которым Documenso подписывает готовые документы, чтобы подпись была технически проверяемой в PDF-читалках. Путь и пароль к нему задаются переменными вида NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH и NEXT_PRIVATE_SIGNING_PASSPHRASE — точные имена стоит свериться с вашим .env, так как в разных релизах они могли отличаться.
  • Файл .env целиком — кроме уже названного, там строка подключения к базе, NEXTAUTH_SECRET, настройки SMTP для отправки писем на подпись.

Ключевой вывод: дамп базы без файлов документов — это база с висящими ссылками на несуществующие вложения. Файлы без базы — груда PDF без метаданных, кто, кому и когда их отправил на подпись. А база и файлы без ключей шифрования и сертификата — это неполный бэкап, который может не позволить корректно поднять систему на новом сервере. Бэкапить нужно всё вместе, синхронно.

Бэкап базы PostgreSQL

Если PostgreSQL развёрнута рядом с Documenso в том же docker-compose (типовая официальная схема — сервисы documenso и database), дамп снимается через pg_dump внутри контейнера базы:

mkdir -p /backup/documenso
docker compose -f /app/documenso/docker-compose.yml exec -T database \
  pg_dump -U documenso -d documenso -F c \
  > /backup/documenso/documenso_db_$(date +%F).dump

Формат -F c (custom) даёт сжатый дамп, который можно восстанавливать выборочно через pg_restore, а не только целиком, как обычный SQL-дамп. Имя пользователя и базы (-U, -d) проверьте в своём .env по переменной NEXT_PRIVATE_DATABASE_URL — они не всегда совпадают со значением documenso по умолчанию, особенно если вы меняли их при установке.

Если PostgreSQL внешняя (управляемая СУБД или отдельный сервер), команда та же, но без обёртки в docker compose exec — просто pg_dump с хоста, указав -h, -p и переменные окружения PGPASSWORD или .pgpass. Про тонкую настройку самой PostgreSQL на сервере, если вы её администрируете отдельно, есть отдельный разбор — установка и настройка PostgreSQL на VPS.

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

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

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

Бэкап файлов документов: локальное хранилище или S3

Если NEXT_PRIVATE_UPLOAD_TRANSPORT=local, файлы лежат на диске сервера — обычно в директории, смонтированной в контейнер documenso (путь ищите в docker-compose.yml как volume-маппинг, часто что-то вроде ./uploads:/app/uploads или аналогично, конкретный путь зависит от версии образа). Архивируем её тем же прогоном, что и дамп базы, чтобы моменты снятия совпадали:

tar -czf /backup/documenso/documenso_uploads_$(date +%F).tar.gz \
  -C /app/documenso uploads

Если транспорт s3 — файлы уже вне сервера, в объектном хранилище, и бэкапить их нужно на стороне этого хранилища: либо версионированием бакета, либо регулярной синхронизацией через rclone в отдельное место. Если в качестве S3-совместимого хранилища у вас поднят собственный MinIO, у бэкапа такого узла есть отдельная специфика — она разобрана в статье бэкап и восстановление MinIO.

Важно: не полагайтесь на то, что дамп базы «сам подскажет», какой транспорт используется — если сервер переживал миграцию хранилища (например, с local на s3), в базе могут быть ссылки на файлы обоих типов. В такой ситуации бэкапьте оба источника, пока не убедитесь, что старый локальный путь пуст.

Ключи шифрования и сертификат подписи — почему без них бэкап бесполезен

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

cp /app/documenso/.env /backup/documenso/env_$(date +%F).bak
cp /app/documenso/resources/certificate.p12 \
  /backup/documenso/certificate_$(date +%F).p12 2>/dev/null || \
  echo "проверьте фактический путь к сертификату в NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH"

Храните эту пару файлов отдельно от общего архива с документами и базой — доступ к ним фактически равносилен доступу к возможности расшифровать данные и подделывать подписи от имени вашего инстанса, так что уровень защиты для них должен быть выше, чем для рядового бэкапа. Отдельное зашифрованное хранилище или менеджер секретов здесь уместнее, чем очередная папка /backup.

Автоматизация и офсайт-копии

Собираем всё в один скрипт с ротацией и выносом наружу — на сервере бэкап бесполезен, если диск с самим сервером выйдет из строя целиком:

#!/bin/bash
# /usr/local/bin/documenso-backup.sh
set -euo pipefail

APP=/app/documenso
DEST=/backup/documenso
DATE=$(date +%F)
RETENTION_DAYS=14

mkdir -p "$DEST"

docker compose -f "$APP/docker-compose.yml" exec -T database \
  pg_dump -U documenso -d documenso -F c \
  > "$DEST/documenso_db_$DATE.dump"

tar -czf "$DEST/documenso_uploads_$DATE.tar.gz" -C "$APP" uploads

cp "$APP/.env" "$DEST/env_$DATE.bak"

find "$DEST" -name 'documenso_*' -mtime +"$RETENTION_DAYS" -delete
find "$DEST" -name 'env_*.bak' -mtime +"$RETENTION_DAYS" -delete
chmod +x /usr/local/bin/documenso-backup.sh
crontab -e
# бэкап Documenso каждую ночь в 03:15
15 3 * * * /usr/local/bin/documenso-backup.sh >> /var/log/documenso-backup.log 2>&1

Дамп pg_dump можно снимать на живой базе без остановки сервиса — PostgreSQL делает это консистентно средствами MVCC, простой не требуется. А вот файл сертификата и .env меняются редко, их можно копировать реже или просто проверять хэшем, что они не изменились с прошлого раза.

Для выноса копий за пределы сервера логично взять rclone или restic — восстановление после полного отказа VPS без офсайт-копии превращается в восстановление из ничего. Если ещё не настраивали регулярный офсайт-бэкап, есть пошаговый разбор — установка и настройка restic на VPS, а если выбираете между инструментами — сравнение в статье restic или BorgBackup — что выгоднее и когда. Отдельно про общие грабли с бэкапом смонтированных в Docker томов (права доступа, потерянные bind-mount мимо compose-файла) — в статье про бэкап Docker-томов на сервере, они актуальны и для директории uploads Documenso.

# добавить в конец documenso-backup.sh после find ... -delete
rclone sync /backup/documenso remote-s3:documenso-backups \
  --transfers 4 --checksum

Восстановление и перенос на новый сервер

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

docker compose -f /app/documenso/docker-compose.yml stop documenso

# база
docker compose -f /app/documenso/docker-compose.yml exec -T database \
  pg_restore -U documenso -d documenso --clean --if-exists \
  < /backup/documenso/documenso_db_2026-08-25.dump

# файлы документов
rm -rf /app/documenso/uploads
tar -xzf /backup/documenso/documenso_uploads_2026-08-25.tar.gz -C /app/documenso

# конфиг и ключи
cp /backup/documenso/env_2026-08-25.bak /app/documenso/.env
cp /backup/documenso/certificate_2026-08-25.p12 /app/documenso/resources/certificate.p12

docker compose -f /app/documenso/docker-compose.yml start documenso

Флаг --clean --if-exists у pg_restore дропает существующие объекты перед восстановлением — это нужно, если в базе уже есть свежие (но битые или частичные) данные с момента сбоя. Если восстанавливаете в пустую базу с нуля, флаг не обязателен, но и не мешает.

Перенос на новый VPS — те же шаги плюс дополнительные пункты:

  • обновить DNS-запись на новый IP;
  • проверить, что NEXT_PUBLIC_WEBAPP_URL и NEXTAUTH_URL в .env указывают на правильный домен — несовпадение ломает и генерацию ссылок на подпись в письмах, и аутентификацию;
  • перевыпустить SSL-сертификат для нового адреса, если раньше он был привязан к старому серверу вручную — например, через Let's Encrypt на VPS;
  • убедиться, что SMTP-настройки в .env актуальны — если письма с приглашением подписать документ перестанут уходить, для внешних получателей сервис фактически перестанет работать, даже если сам сайт открывается.

После восстановления на новом сервере откройте один-два уже подписанных документа и убедитесь, что PDF открывается и подпись в нём проверяется штатным способом — это лучший сигнал, что связка база + файлы + сертификат восстановлена целиком и согласованно, а не частично.

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

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

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

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

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

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

Что случится, если восстановить базу и файлы, но потерять NEXT_PRIVATE_ENCRYPTION_KEY?

Часть чувствительных полей, зашифрованных на уровне приложения этим ключом, станет нечитаемой для Documenso — это не всегда фатально для всего сервиса, но точно ломает конкретную функциональность, которая на них завязана. Проще относиться к ключу как к обязательной части бэкапа, а не как к опции.

Нужно ли останавливать Documenso на время pg_dump?

Нет, PostgreSQL снимает консистентный снимок данных на лету средствами MVCC, простой сервиса не требуется. А вот архивацию файловой директории uploads лучше делать по возможности без активных загрузок больших PDF в этот момент, чтобы не поймать файл в процессе записи.

Как понять, какой транспорт хранения файлов используется — локальный или S3?

Посмотрите значение переменной NEXT_PRIVATE_UPLOAD_TRANSPORT в вашем .env. Если она не задана явно, скорее всего используется значение по умолчанию для вашей версии — сверьтесь с .env.example из репозитория той версии Documenso, которую вы разворачивали.

Обязательно ли бэкапить сертификат подписи, если можно сгенерировать новый?

Технически новый самоподписанный сертификат Documenso сгенерирует сам при первом запуске без старого. Но тогда уже подписанные ранее документы останутся привязаны к старому сертификату, а новые будут подписываться другим — для аудита и юридической прослеживаемости лучше сохранить оригинальный файл, а не полагаться на автогенерацию.

Можно ли восстановить один конкретный документ без полного восстановления базы?

Да, если дамп снят в формате -F c (custom) — pg_restore с флагами -t и --data-only позволяет выборочно вытащить строки по конкретным таблицам, но потребует ручной сверки связанных таблиц (получатели, поля подписи), поскольку Documenso хранит документ не одной строкой, а набором связанных записей.

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

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

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