VPSРейтинг
Базы данных25 августа 2026 · 22 мин

Databasus на VPS: бэкапы PostgreSQL, которые точно восстановятся

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

Проблема: pg_dump по крону — это ещё не бэкап

Типовая схема выглядит так: в crontab строчка, которая раз в сутки складывает дамп базы в папку на том же сервере. Схема кажется рабочей ровно до дня, когда она понадобится. Ломается она в четырёх местах, и все четыре встречаются в жизни.

Откатиться на пятнадцать минут назад нельзя

Кто-то выполнил UPDATE без WHERE в три часа дня. Последний дамп — ночной. Значит, выбор такой: потерять весь рабочий день или оставить испорченные данные. Промежуточных вариантов схема не предусматривает.

Никто ни разу не пробовал восстановиться

Скрипт отработал без ошибок — значит, всё хорошо? Не обязательно. Если у роли, от которой делается дамп, не хватило прав на часть объектов, pg_dump может тихо их пропустить и завершиться с нулевым кодом. Узнать об этом в день аварии — худший из возможных вариантов.

Дамп лежит на том же диске, что и база

Диск сервера умер, файловая система развалилась, хостер по ошибке удалил виртуалку — и база, и её копия исчезают одновременно. Копия на том же носителе спасает ровно от одного сценария: «случайно удалил таблицу».

Скрипт молчит

Cron не пишет в Telegram. Если бэкап падает третью неделю подряд — из-за кончившегося места, смены пароля или обновления PostgreSQL, — вы узнаете об этом только тогда, когда полезете за копией.

Первые три пункта решает не другой скрипт, а другой подход к бэкапу — восстановление на момент времени. Четвёртый решается любым уведомителем. Databasus даёт и то, и другое в одном месте.

Что такое «восстановление на момент времени» простыми словами

PostgreSQL никогда не меняет данные сразу «на месте». Сначала он записывает, что именно собирается изменить, в журнал предзаписи — это и есть загадочные три буквы WAL (write-ahead log). Только потом изменение доезжает до файлов базы. Журнал нужен самой базе, чтобы пережить внезапное выключение питания, и он ведётся всегда, независимо от бэкапов.

Аналогия. Полный бэкап — это фотография базы: как она выглядела в 04:00. Журнал WAL — видеозапись всего, что происходило после. Имея фотографию и видео, можно взять фотографию и «доиграть» видео до нужной секунды — например, до 14:59:30, за полминуты до рокового UPDATE. Это и называется восстановлением на момент времени, PITR.

Чтобы это работало, кто-то должен непрерывно забирать журнал с сервера и складывать рядом с бэкапами. Именно этим и занимается Databasus: он подключается к PostgreSQL как обычная реплика и читает поток WAL. Раз в сутки — полная копия, раз в час — инкремент (только изменившиеся блоки), между ними — непрерывный журнал.

Два слова, которые дальше встретятся в интерфейсе. RPO — сколько данных вы теряете при аварии (у нас это будут минуты, а не сутки). RTO — сколько времени занимает восстановление.

Что такое Databasus

Databasus — открытый инструмент для бэкапа баз данных, который вы ставите на свой сервер. Лицензия Apache 2.0, около 8,3 тысячи звёзд на GitHub, релизы примерно раз в неделю: версия 3.55.0 вышла 22 августа 2026 года. Проект появился в июне 2025 года под именем Postgresus и был переименован, когда научился работать не только с PostgreSQL, но и с MySQL, MariaDB и MongoDB. Гайды под старым названием — про него же.

Вся установка — один контейнер Docker. Внутри уже лежат клиентские утилиты PostgreSQL всех версий с 12 по 18, MySQL, MariaDB и MongoDB, так что подгонять версию pg_dump под версию сервера не придётся — Databasus сам выберет нужную.

Что он делает из коробки

  • Расписание — раз в час, в сутки, в неделю, в месяц или по выражению cron, с указанием времени.
  • Хранилища — локальный диск, S3 и всё S3-совместимое, Cloudflare R2, Azure Blob, Google Drive, NAS, FTP, SFTP, rclone.
  • Шифрование — AES-256-GCM, у каждого бэкапа свой ключ. Поэтому копии не страшно класть в чужое хранилище.
  • Уведомления — Telegram, Email, Slack, Discord, Teams, Mattermost, вебхуки.
  • Хранение — по сроку, по количеству копий или по схеме «дед-отец-сын», когда отдельно держат почасовые, дневные, недельные, месячные и годовые копии.
  • Восстановление на момент времени — на любую секунду между бэкапами.
  • Автопроверка восстановления — главная особенность, ради которой стоит смотреть на проект.

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

Важное свойство, о котором забывают. Бэкапы Databasus не привязаны к Databasus. Они лежат в стандартных форматах PostgreSQL, и если сервер с панелью исчезнет, копии всё равно разворачиваются обычнымиpg_restore и pg_combinebackup. Единственное, что нужно сохранить отдельно, — файл ключа шифрования; про него будет отдельный раздел.

Два режима: логический и физический

При добавлении базы Databasus задаст первый и самый важный вопрос: какой бэкап делать. Разница принципиальная, и от ответа зависит всё остальное.

 ЛогическийФизический
Что копируетСодержимое базы — дампФайлы кластера целиком
На чём построенpg_dump + сжатие zstdpg_basebackup + pg_receivewal
Версии PostgreSQL14–18 (в списке есть и 12–13)только 17 и 18
Откат на момент временинетда, на любую секунду
Инкрементынет, каждый раз полный дампда, только изменённые блоки
Как разворачиваетсяв существующий сервер PostgreSQLподнимается отдельный кластер
Настройкалогин и пароль — и всётри настройки в psql
Комубазы примерно до 50 ГБкрупные базы и там, где важен RPO

Почему физический бэкап требует именно PostgreSQL 17 — вопрос не про Databasus, а про сам PostgreSQL. Блочные инкременты появились в ядре только в семнадцатой версии: сервер научился сам вести сводки изменённых блоков, а pg_basebackup — забирать разницу. Databasus сознательно не стал писать свой формат инкрементов и опирается на родной механизм PostgreSQL, поэтому на версиях до 17 физический бэкап просто не предлагается.

Как выбрать за пять секунд. PostgreSQL 17 или 18 — берите физический: он даёт откат на момент времени, ради которого всё и затевалось. PostgreSQL 16 и более ранние — доступен только логический; он тоже сильно лучше крона, но потолок остаётся прежним: откат только на момент дампа. Дальше в статье настраивается физический режим, а отличия для логического отмечены по ходу.

Что понадобится

  • VPS с Ubuntu 22.04 или 24.04 и установленным Docker. Официальный минимум — 1 ядро и 500 МБ памяти; на замерах контейнер занимал 136 МБ, но берите сервер хотя бы с 1 ГБ, если на нём же живёт база.
  • Место на диске: около 5 ГБ на само приложение плюс объём под бэкапы. Образ весит 317 МБ.
  • PostgreSQL 17 или 18 — в этой статье он стоит на том же сервере. База на другой машине тоже поддерживается, отличия описаны ниже.
  • Права root на сервере и доступ к psql под пользователем postgres.
  • Домен — по желанию, чтобы открывать панель по HTTPS. Без домена можно работать через SSH-туннель, и первое время это даже лучше.

Шаг 1. Ставим Databasus

У проекта есть установочный скрипт install-databasus.sh, но мы им пользоваться не будем — по двум конкретным причинам. Он публикует порт панели на все сетевые интерфейсы и запускает контейнер в отдельной сети Docker, из которой 127.0.0.1:5432 — это уже не ваш PostgreSQL, а пустота внутри контейнера. Свой compose-файл решает обе проблемы сразу.

создаём каталог и файл конфигурации
sudo mkdir -p /opt/databasus
cd /opt/databasus
sudo nano docker-compose.yml

Вставьте в файл:

/opt/databasus/docker-compose.yml
services:
  databasus:
    container_name: databasus
    image: databasus/databasus:latest
    network_mode: host
    volumes:
      - ./databasus-data:/databasus-data
    restart: unless-stopped

Ключевая строка здесь — network_mode: host. Она означает «контейнер пользуется сетью самого сервера». Благодаря ей Databasus видит PostgreSQL по адресу 127.0.0.1:5432, и базу не приходится открывать наружу: она остаётся слушать только локальный адрес, как и настроена по умолчанию. Это самый безопасный вариант из возможных.

запуск
sudo docker compose up -d

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

проверка готовности
curl -s http://127.0.0.1:4005/api/v1/system/health

В ответ должна прийти строка со словами Application is healthy. Этот же адрес удобно скормить внешнему мониторингу: он отдаёт код 200, когда всё в порядке, и 503 с причиной, когда что-то требует внимания — например, диск заполнен больше чем на 95 %.

Сразу закройте панель файрволом

В режиме network_mode: host Databasus слушает порт 4005 на всех адресах — в этом легко убедиться командой sudo ss -tlnp | grep 4005, в выводе будет*:4005. Пока файрвол не настроен, панель доступна из интернета. Хорошая новость: в отличие от обычного проброса портов Docker, который умеет обходить правила UFW, host-сеть подчиняется им как обычное приложение.

разрешаем только нужное, остальное закрыто
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Порт 4005 в списке не появляется намеренно. Открывать его наружу не нужно вообще никогда: до панели добираются либо через SSH-туннель, либо через обратный прокси на 443-м порту.

Пока домен не настроен, откройте панель через SSH-туннель. Команда выполняется на вашем компьютере, не на сервере:

на своём компьютере; IP замените на адрес сервера
ssh -L 4005:127.0.0.1:4005 root@203.0.113.10

Пока это окно терминала открыто, панель доступна в браузере по адресу http://127.0.0.1:4005. Когда захотите постоянный доступ по домену, поставьте перед Databasus обратный прокси — как это делается, разобрано в отдельной статье про Caddy и автоматический HTTPS. Проксировать нужно на 127.0.0.1:4005.

Шаг 2. Первый вход

На первом экране Databasus попросит придумать пароль администратора — форма называется Sign up admin. Логин при этом фиксированный и равен строке admin: поле с ним показано, но недоступно для правки. Введите пароль дважды, и вы окажетесь внутри.

Если пароль потеряется, его можно сбросить с сервера одной командой:

сброс пароля администратора
sudo docker exec -it databasus ./main \
  --new-password="НовыйДлинныйПароль" --email="admin"

Дальше в настройках стоит сделать ещё одну вещь: открыть Settings и выключить Allow sign up. Иначе, когда панель окажется за доменом, зарегистрироваться в ней сможет любой желающий.

Шаг 3. Готовим PostgreSQL — три настройки

Физический бэкап читает базу по протоколу репликации — тому же, по которому живут обычные реплики PostgreSQL. Значит, нужна роль с правом репликации и включённая сводка журнала. Всё это делается в psql и занимает минуту.

Дальше в статье во всех путях стоит число 17 /etc/postgresql/17/main/, /usr/lib/postgresql/17/bin/, postgresql@17-main. Если у вас PostgreSQL 18, подставляйте 18. Свою версию и путь к конфигурации всегда можно спросить у самой базы: sudo -u postgres psql -Atc "SHOW config_file".

заходим в psql от системного пользователя postgres
sudo -u postgres psql
внутри psql; пароль придумайте свой, длинный
CREATE ROLE databasus WITH LOGIN REPLICATION PASSWORD 'ZamenIteEtotParol_2026';
ALTER SYSTEM SET summarize_wal = on;
SELECT pg_reload_conf();
GRANT EXECUTE ON FUNCTION pg_switch_wal() TO databasus;
\q

Что здесь происходит:

CREATE ROLE ... REPLICATION

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

summarize_wal = on

Включает тот самый механизм PostgreSQL 17: сервер начинает вести сводки о том, какие блоки данных менялись. Без него инкрементальные бэкапы физически невозможны, и Databasus просто откажется сохранить настройку с ошибкойWAL summarization is off. Параметр применяется по перезагрузке конфигурации — перезапускать PostgreSQL не нужно, достаточноpg_reload_conf() в той же строке.

GRANT EXECUTE ON FUNCTION pg_switch_wal()

Самый неочевидный пункт, и он про RPO. Журнал уезжает в хранилище сегментами по 16 МБ, и только когда сегмент заполнен целиком. На нагруженной базе он заполняется за секунды, а на тихой — может копиться часами, и всё это время точка восстановления стоит на месте. Databasus умеет сам подталкивать PostgreSQL закрыть сегмент раз в пять минут, но функция pg_switch_wal() по умолчанию доступна только суперпользователю. Этот GRANT и открывает её нашей роли. Без него Databasus пришлёт уведомление Cannot force WAL rotation и перестанет пытаться.

Альтернатива для управляемых баз. Если базой управляет провайдер и выдать GRANT нельзя, тот же эффект даёт штатный параметр PostgreSQL: ALTER SYSTEM SET archive_timeout = '5min'; и перезагрузка конфигурации. Проверено на PostgreSQL 17: он закрывает сегмент по таймеру, даже когда встроенное архивирование выключено, и в панели провайдера такой параметр обычно доступен.

А как же pg_hba.conf?

Правильный вопрос: подключения по протоколу репликации разрешаются вpg_hba.conf отдельно, и обычная строка host all их не покрывает. Хорошая новость — для нашей схемы править ничего не нужно. В PostgreSQL, установленном из официального репозитория PGDG на Ubuntu, уже есть нужная строка (проверено на чистой установке 17-й версии):

/etc/postgresql/17/main/pg_hba.conf — уже есть по умолчанию
host    replication     all             127.0.0.1/32            scram-sha-256

Так как Databasus работает в сети сервера, он приходит именно с адреса127.0.0.1 и попадает под это правило. Проверить свой файл можно так:

sudo grep '^host.*replication' /etc/postgresql/17/main/pg_hba.conf

Если строки нет — допишите её в конец файла и выполните sudo -u postgres psql -c "SELECT pg_reload_conf();".

Если база на другом сервере

Тогда добавляются три вещи. Разрешить PostgreSQL слушать не только локальный адрес, разрешить репликацию с адреса Databasus и открыть порт только этому адресу.

на сервере с базой; 203.0.113.10 — адрес машины с Databasus
# 1. слушать не только localhost; здесь перезапуск обязателен
sudo -u postgres psql -c "ALTER SYSTEM SET listen_addresses = '*';"
sudo systemctl restart postgresql@17-main

# 2. разрешить подключения с адреса Databasus
echo "host    replication     databasus       203.0.113.10/32         scram-sha-256
host    all             databasus       203.0.113.10/32         scram-sha-256" \
  | sudo tee -a /etc/postgresql/17/main/pg_hba.conf
sudo -u postgres psql -c "SELECT pg_reload_conf();"

# 3. открыть порт только этому адресу
sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp

Если открывать порт базы наружу не хочется совсем, в настройках подключения Databasus есть встроенный SSH-туннель: тогда снаружи торчит только SSH, а до PostgreSQL Databasus добирается через него.

Шаг 4. Решаем, куда складывать копии

В интерфейсе это раздел Storages. Начать проще всего с типа Local — копии лягут в /opt/databasus/databasus-data/backups. Для первых экспериментов этого достаточно, но как постоянное решение локальное хранилище не годится: копия на том же сервере не спасает ни от смерти диска, ни от удаления виртуалки.

Рабочий вариант — второе хранилище типа S3. Подойдёт любой S3-совместимый сервис: объектное хранилище российского облака, Cloudflare R2 или своё S3-хранилище на отдельном VPS. Поля при добавлении такие:

ПолеЧто вписывать
Bucketимя бакета, например pg-backups
Regionрегион хранилища; для своего S3 подойдёт us-east-1
Access key / Secret keyключ доступа и секрет
Endpointадрес сервиса обязательно со схемой: https://s3.example.com
Prefixнеобязательная папка внутри бакета, например prod/

Грабля на ровном месте. В поле Endpoint схему http:// или https:// нужно писать явно. Если вписать просто s3.example.com:9000, Databasus решит, что там HTTPS, и проверка соединения упадёт с сообщением server gave HTTP response to HTTPS client. Проверено: тот же адрес со схемой http:// подключается с первой попытки.

Кнопка Test рядом с формой кладёт в бакет пробный файл и сразу показывает результат — жмите её до сохранения. И не переживайте за содержимое: бэкапы шифруются AES-256-GCM ещё до отправки, у каждого свой ключ, так что в чужом хранилище лежит нечитаемый набор байтов.

Шаг 5. Добавляем базу и расписание

Кнопка New database запускает мастер. Порядок шагов такой:

  1. Тип базы — PostgreSQL.
  2. Choose backup type — тот самый выбор из прошлого раздела. В интерфейсе варианты подписаны так: Logical — recommended for databases under 50 GB. Simpler to set up и Physical — for databases over 50 GB. Enables point-in-time recovery and better RPO/RTO, but needs extra setup. Выбираем Physical.
  3. Подключение: host 127.0.0.1, port 5432, пользователь databasus и пароль, который вы задали в третьем шаге. Версию укажите свою — 17 или 18.
  4. Режим физического бэкапа — из трёх вариантов беритеFull + incremental + WAL. Только он даёт откат на момент времени; два других делают либо просто полные копии, либо полные с инкрементами.
  5. Расписание: полная копия раз в сутки в 04:00, инкремент — раз в час. Инкремент обязан быть чаще полной копии, иначе Databasus сам подтянет интервал.
  6. Хранение: проще всего выбрать хранение цепочек и указать 7 — это семь последних наборов «полная копия плюс её инкременты».
  7. Хранилище — то, что настроили на четвёртом шаге.
  8. Шифрование — оставьте включённым.

Кнопка Test connection здесь не формальность: она проверяет не только логин с паролем, но и все требования к серверу — версию, права роли, параметры wal_level, max_wal_senders, max_replication_slots, summarize_wal и правила в pg_hba.conf. Если чего-то не хватает, Databasus покажет не абстрактную ошибку, а готовую команду для исправления.

Сразу после сохранения Databasus снимет первую полную копию и включит поток журнала. Убедиться, что поток пошёл, можно на стороне базы:

слот репликации должен появиться и быть активным
sudo -u postgres psql -c "SELECT slot_name, active, slot_type FROM pg_replication_slots;"

Ожидаемый вывод — одна строка вида databasus_slot_ba8e9e3c... | t | physical. Буква t означает, что потребитель подключён и журнал уезжает.

Слот репликации — обратная сторона медали

Пока слот существует, PostgreSQL не имеет права удалять журнал, который этот слот ещё не забрал. Это ровно то, что нужно: ни один байт не потеряется, даже если Databasus на минуту отключился. Но если выключить его на неделю, WAL будет копиться, пока не кончится диск, — а кончившееся место останавливает базу. Страховка ставится одной командой:

потолок для отставшего слота; перезапуск не нужен
sudo -u postgres psql -c "ALTER SYSTEM SET max_slot_wal_keep_size = '10GB';" \
                          -c "SELECT pg_reload_conf();"

При превышении лимита PostgreSQL пожертвует слотом, а не диском. Цепочка бэкапов при этом порвётся, но Databasus пришлёт уведомление, и вы просто сделаете новую полную копию. Это несравнимо лучше, чем вставшая база. А если базу штатно удалить из Databasus, слот он снимет сам.

Шаг 6. Уведомления, чтобы узнавать о поломке не в день аварии

Раздел Notifiers. Проще всего Telegram: создайте бота у @BotFather, получите токен, напишите боту любое сообщение и узнайте свойchat id — например, через @userinfobot. Вставьте оба значения в форму и нажмите кнопку проверки: тестовое сообщение придёт сразу.

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

  • Backup failed — бэкап не удался.
  • Chain broken — цепочка «полная копия плюс инкременты» порвалась: новые инкременты к ней уже не пристроить, нужна свежая полная копия.
  • WAL gap — в потоке журнала образовалась дыра, то есть точка восстановления перестала двигаться.
  • Verification failed — автопроверка не смогла восстановить бэкап. Самое важное письмо из всех.

Уведомления об успехе включать не советую: через неделю вы перестанете их читать, а вместе с ними — и сообщения о сбоях.

Отдельно стоит включить health check в настройках базы: Databasus будет с заданным интервалом проверять, отвечает ли PostgreSQL, и напишет, если база перестала отвечать. Это уже не про бэкапы, но узнать о лежащей базе от своего же сервера, а не от пользователей, приятно.

Шаг 7. Включаем автопроверку восстановления

Это то, ради чего стоит ставить Databasus. Проверка устроена честно: берётся свежий бэкап, поднимается одноразовый контейнер с PostgreSQL нужной версии, данные реально восстанавливаются, считаются строки в каждой таблице, формируется отчёт, контейнер удаляется.

Раз проверка поднимает контейнеры, её выполняет отдельная маленькая программа — verification agent. Ей нужен доступ к Docker, поэтому она живёт не внутри Databasus, а рядом. Для одного сервера её можно запустить на этой же машине; если хочется не нагружать боевой сервер — на любой другой, хоть на домашнем компьютере.

1. В панели откройте Settings → Verification agents и нажмите Create verification agent. Придумайте имя. В следующем окне будут показаны идентификатор агента и токен.

Токен показывается ровно один раз. Скопируйте его, прежде чем закрыть окно. Если всё-таки потеряли — в строке агента есть действие Rotate token, старый перестанет работать.

2. Скачайте агент прямо со своего Databasus и запустите. Файл весит около 17 МБ, авторизация для скачивания не нужна:

на сервере; для ARM замените amd64 на arm64
sudo mkdir -p /opt/databasus/agent && cd /opt/databasus/agent

sudo curl -L -o verification-agent \
  "http://127.0.0.1:4005/api/v1/system/verification-agent?arch=amd64"
sudo chmod +x verification-agent
запуск; идентификатор и токен подставьте свои
sudo ./verification-agent start \
  --databasus-host=http://127.0.0.1:4005 \
  --allow-insecure-http \
  --agent-id=98ed9f37-df0f-4e47-88d9-655870e13b21 \
  --token=54327bef09be4da7ac29f4c871a27e51 \
  --max-cpu=2 --max-ram-mb=2048 --max-disk-gb=20 --max-concurrent-jobs=1

Флаг --allow-insecure-http нужен потому, что агент требует HTTPS и делает исключение только по явному указанию. Здесь он уместен: соединение не выходит за пределы сервера. Если агент запускается на другой машине, флаг убирайте и указывайте адрес панели по HTTPS — иначе токен полетит по сети открытым текстом.

Команда start запускает агент фоном и запоминает все флаги в файле databasus-verification.json рядом с собой. После перезагрузки сервера достаточно выполнить sudo ./verification-agent start без аргументов — но обязательно из того же каталога, иначе файл с настройками не найдётся. Есть ещё status — посмотреть, что происходит, и stop — остановить. Логи пишутся в файлы databasus-verification.log и databasus-verification.daemon.log в том же каталоге. Автозапуска у агента нет: после перезагрузки сервера поднимите его руками или заверните в systemd-юнит, указав в нём команду run вместо start — она не уходит в фон, а именно этого systemd и ждёт.

Флаги --max-* — это не выделенные ресурсы, а общий бюджет, который Databasus делит между одновременными задачами. При --max-concurrent-jobs=1 единственная проверка получит все два ядра и два гигабайта памяти. Внимательнее всего с диском: одной проверке нужно место под файл бэкапа, под развёрнутую базу и запас сверху, поэтому ставьте --max-disk-gb с хорошим запасом относительно самой большой базы.

3. Осталось включить расписание. В настройках базы, во вкладке проверки восстановления, включите Scheduled verification и выберите частоту. Вариант After backup — самый строгий: каждая успешная копия проверяется сразу. Если бэкапы приходят чаще, чем успевают проверяться, Databasus не копит очередь, а отменяет проверку устаревшей копии в пользу свежей.

На тестовом сервере проверка небольшой базы заняла 13 секунд от постановки задачи до отчёта. В отчёте видно код возврата восстановления, размер получившейся базы, количество схем и таблиц, а также разбивку по таблицам с числом строк в каждой. Ровно та информация, которой не даёт ни одна контрольная сумма.

Шаг 8. Тренировочное восстановление на момент времени

Автопроверка отвечает на вопрос «бэкап живой?». Остался второй вопрос: «а вы сами умеете им пользоваться?». Ответ надо получить заранее, а не в день аварии. Разберём полный сценарий: в базе shop было 2000 заказов, потом таблицу снесли, и мы возвращаем состояние на секунду до этого.

Важно понимать. Физический бэкап восстанавливается не «в существующую базу», а поднимается как отдельный кластер PostgreSQL. Рабочую базу это не трогает: мы поднимем копию на соседнем порту 5433, заберём оттуда нужные данные и погасим её. Именно так и надо тренироваться.

1. Поставьте zstd. Бэкапы и журнал сжаты этим алгоритмом, и распаковывает их та машина, на которой вы восстанавливаете. На чистой Ubuntu утилиты нет — без неё восстановление остановится на первом же шаге:

sudo apt-get install -y zstd

2. В панели откройте базу, вкладку с бэкапами, и выберите восстановление на момент времени. Укажите время (в UTC) — Databasus выдаст готовую команду с одноразовой ссылкой на набор файлов. В панели она одной строкой, здесь то же самое разбито на два шага, чтобы было видно, что происходит:

ссылка с токеном у вас будет своя
sudo mkdir -p /var/tmp/pgrestore && cd /var/tmp/pgrestore

sudo curl -fsSL "http://127.0.0.1:4005/api/v1/backups/physical/recovery-script" \
  -o databasus-recovery.sh

sudo sh databasus-recovery.sh \
  --pg-bin /usr/lib/postgresql/17/bin \
  --target-time "2026-08-25 09:37:59+00" \
  "http://127.0.0.1:4005/api/v1/backups/physical/restore-stream?token=ВАШ_ТОКЕН" \
  restored

Скрипт скачает набор, проверит контрольные суммы, распакует полную копию и все инкременты, склеит их утилитой pg_combinebackup в готовый каталог данных, распакует журнал и пропишет всё, что нужно для доигрывания до указанной секунды. Флаг --pg-bin обязателен на Ubuntu: утилиты PostgreSQL лежат не в общемPATH, а в каталоге версии. Если на сервере вообще нет PostgreSQL, вместо этого флага используйте --combine-image postgres:17 — тогда склейка выполнится внутри контейнера.

Здесь вас ждёт главная грабля Ubuntu и Debian

Скрипт закончит работу и напечатает ACTION REQUIRED: в восстановленном каталоге не хватает postgresql.conf, pg_hba.conf и pg_ident.conf. Это не ошибка Databasus и не порча бэкапа. В Ubuntu и Debian конфигурация PostgreSQL лежит вне каталога данных, в /etc/postgresql/17/main/, а физический бэкап копирует только каталог данных. Этих файлов там нет и быть не может — ни у одного инструмента. Лечится копированием трёх файлов с рабочего сервера.

3. Донесите конфигурацию и запустите копию на порту 5433:

каталог восстановления — /var/tmp/pgrestore/restored/data
# три файла конфигурации с рабочего сервера
sudo cp /etc/postgresql/17/main/postgresql.conf \
        /etc/postgresql/17/main/pg_hba.conf \
        /etc/postgresql/17/main/pg_ident.conf \
        /var/tmp/pgrestore/restored/data/

# отключаем пути, которые ведут на рабочий кластер, и меняем порт
sudo sed -i \
  -e "s|^data_directory|#data_directory|" \
  -e "s|^hba_file|#hba_file|" \
  -e "s|^ident_file|#ident_file|" \
  -e "s|^external_pid_file|#external_pid_file|" \
  -e "s|^ssl = on|#ssl = on|" \
  -e "s|^ssl_cert_file|#ssl_cert_file|" \
  -e "s|^ssl_key_file|#ssl_key_file|" \
  -e "s|^port =.*|port = 5433|" \
  /var/tmp/pgrestore/restored/data/postgresql.conf

sudo mkdir -p /var/tmp/pgrestore/restored/data/conf.d

# права: каталог должен принадлежать пользователю postgres
sudo chown -R postgres:postgres /var/tmp/pgrestore/restored/data
sudo chmod 700 /var/tmp/pgrestore/restored/data
запуск восстановленного кластера
sudo -u postgres /usr/lib/postgresql/17/bin/pg_ctl \
  -D /var/tmp/pgrestore/restored/data -l /tmp/restore.log start

Если pg_ctl напишет could not start server, загляните в лог командой sudo tail -n 20 /tmp/restore.log (без sudo его не прочитать — файл создаёт пользователь postgres). Чаще всего там окажется Address already in use — порт 5433 занят вторым кластером PostgreSQL, который уже стоит на сервере. Возьмите любой свободный порт вместо 5433.

4. Смотрим, что получилось. В логе будут строки, по которым видно, что PostgreSQL доиграл журнал ровно до нужной секунды и остановился перед роковой транзакцией:

sudo tail -n 20 /tmp/restore.log
LOG:  starting point-in-time recovery to 2026-08-25 09:37:59.404205+00
LOG:  recovery stopping before commit of transaction 754, time 2026-08-25 09:38:01.491857+00
LOG:  archive recovery complete
LOG:  database system is ready to accept connections
сравниваем восстановленную копию и рабочую базу
sudo -u postgres psql -p 5433 -d shop -Atc "SELECT count(*) FROM orders;"
# 2000

sudo -u postgres psql -p 5432 -d shop -Atc "SELECT count(*) FROM orders;"
# ERROR:  relation "orders" does not exist

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

5. Уберите за собой. Тренировочный кластер занимает место и держит порт:

sudo -u postgres /usr/lib/postgresql/17/bin/pg_ctl \
  -D /var/tmp/pgrestore/restored/data stop
sudo rm -rf /var/tmp/pgrestore

Проделайте это один раз сейчас — и вы будете знать, сколько времени занимает восстановление именно вашей базы. Это и есть RTO, о котором все говорят и который почти никто не измерял. Заодно выяснится, хватает ли на сервере места под развёрнутую копию.

Сколько это ест ресурсов

Замеры на тестовом сервере с Ubuntu 22.04, PostgreSQL 17 из репозитория PGDG и Databasus 3.55.0.

ЧтоСколько
Память контейнера в покое136 МБ
Образ Docker317 МБ
Каталог databasus-data с парой бэкапов67 МБ
Полная копия свежего кластера PostgreSQL 172,5 МБ
Проверка восстановления небольшой базы13 секунд

Про место под журнал стоит сказать точнее, потому что это единственная строка, которая может неприятно удивить. Сегмент WAL весит 16 МБ до сжатия. На тихой базе Databasus раз в пять минут просит PostgreSQL закрыть сегмент — но только если с прошлого раза вообще были записи, так что простаивающая база пустых файлов не плодит. Такие почти пустые сегменты ужимаются в килобайты. На нагруженной базе считайте по-другому: сколько журнала она пишет в сутки, столько и уедет в хранилище (в сжатом виде).

Заметная нагрузка на процессор возникает в момент снятия копии — из-за сжатия. Разработчики оценивают накладные расходы примерно в 20 % времени в обмен на уменьшение размера в 4–8 раз. Именно поэтому полную копию ставят на ночь.

Что делать, если сервер с Databasus исчезнет

Резонный страх: бэкапы вроде бы есть, но лежат зашифрованными, а панель, которая умела их читать, вместе с сервером и пропала. У Databasus на этот случай нет привязки к себе — бэкапы хранятся в стандартных форматах PostgreSQL. Но одна вещь нужна обязательно.

Сохраните файл ключа шифрования прямо сейчас

Он один на всю установку и лежит здесь:

sudo cat /opt/databasus/databasus-data/secret.key

Скопируйте содержимое в менеджер паролей или в любое место, не связанное с этим сервером. Без него зашифрованные копии не расшифровать — ни вам, ни кому-либо ещё. Это тридцать секунд работы, которые однажды решат всё.

Имея файл бэкапа, соседний файл .metadata и ключ, копию разворачивают без Databasus: в документации проекта есть готовый скрипт расшифровки на Python, после которого получившийся файл скармливается обычному pg_restore или pg_combinebackup.

Если хочется вернуть не только данные, но и саму панель со всеми настройками, расписаниями и историей — забэкапьте вдобавок каталог /opt/databasus/databasus-data/pgdata. Тогда на новом сервере достаточно положить каталог databasus-data на место и запустить контейнер. Кстати, каталог с данными Databasus — отличный кандидат на попадание в общий бэкап сервера, о котором есть отдельная статья про restic и rclone.

Обновление

Релизы выходят часто, обновление — три команды:

cd /opt/databasus
sudo docker compose pull
sudo docker compose up -d

Данные лежат в примонтированном каталоге и переезд переживают. Схема внутренней базы обновляется при старте автоматически. Перед обновлением через несколько версий стоит заглянуть в примечания к релизам: например, старый режим бэкапов через агент на сервере базы был признан ошибочным и убран — если вы обновляетесь с версии 3.42 или более ранней, где такие бэкапы ещё были, Databasus предупредит об этом и не станет ломать существующие копии молча.

Частые проблемы

«Replication is not allowed from this host»

В pg_hba.conf нет правила, разрешающего подключение по протоколу репликации с адреса Databasus. Частая ловушка: строка host all all ... такие подключения не покрывает, для них нужно отдельное правило со словом replication. Особенно часто встречается, когда PostgreSQL запущен в Docker: в официальном образе репликация разрешена только с самого 127.0.0.1 внутри контейнера.

в конец pg_hba.conf, адрес сузьте до своего
host    replication     databasus       203.0.113.10/32         scram-sha-256

Затем sudo -u postgres psql -c "SELECT pg_reload_conf();".

«WAL summarization is off» — не сохраняются настройки бэкапа

Databasus намеренно не даёт включить инкременты, пока сервер не ведёт сводки изменённых блоков: иначе вместо инкрементов вы получили бы полные копии и очень долгое восстановление. В стандартной установке PostgreSQL 17 параметр выключен — включается без перезапуска:

sudo -u postgres psql -c "ALTER SYSTEM SET summarize_wal = on;" \
                          -c "SELECT pg_reload_conf();"

Физический бэкап вообще не предлагается

Значит, на сервере PostgreSQL 16 или более ранняя версия. Механизма блочных инкрементов там нет, и Databasus не станет делать вид, что он есть. Варианта два: настроить логический бэкап (он даст расписание, шифрование, отправку в S3, уведомления и ту же автопроверку восстановления — только без отката на момент времени) или запланировать обновление PostgreSQL до 17-й версии.

Хранилище S3 не подключается: «server gave HTTP response to HTTPS client»

В поле Endpoint забыта схема. Databasus по умолчанию считает адрес HTTPS-адресом, а хранилище отвечает по HTTP. Напишите адрес полностью — http://s3.example.com:9000 — и проверка пройдёт. То же самое, если у вашего S3 самоподписанный сертификат: тогда либо поставьте нормальный сертификат, либо включите в форме пропуск проверки TLS (и понимайте, что это ослабляет защиту).

Восстановленный кластер не стартует, в логе — «could not open configuration file»

Это описанная выше особенность Ubuntu и Debian: postgresql.conf, pg_hba.conf и pg_ident.conf лежат в /etc/postgresql/17/main/, вне каталога данных, поэтому в физический бэкап они не попадают. Скопируйте три файла в восстановленный каталог и закомментируйте в postgresql.conf строки data_directory, hba_file, ident_file, external_pid_file и настройки SSL — все они ведут на рабочий кластер. Готовые команды есть в разделе про тренировочное восстановление, а сам скрипт печатает подробную инструкцию под заголовком ACTION REQUIRED.

Место на диске сервера с базой быстро кончается

Почти наверняка виноват слот репликации: Databasus остановлен или потерял связь, а PostgreSQL послушно копит для него журнал. Посмотреть отставание:

sudo -u postgres psql -c \
  "SELECT slot_name, active, wal_status, \
          pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag \
   FROM pg_replication_slots;"

Лечение — поднять Databasus обратно. Профилактика — заранее выставить max_slot_wal_keep_size, как описано в пятом шаге. Аварийный вариант, если Databasus вам больше не нужен, а диск кончается прямо сейчас: SELECT pg_drop_replication_slot('имя_слота'); — журнал сразу начнёт очищаться, но цепочка бэкапов будет разорвана.

Панель доступна из интернета без пароля… точнее, с формой регистрации

При network_mode: host порт 4005 слушает все адреса, а форма регистрации по умолчанию открыта. Два обязательных действия: включить UFW, не открывая 4005, и выключить Allow sign up в настройках. Проверить, что порт действительно закрыт снаружи, можно с любой другой машины: curl -m 5 http://ВАШ_IP:4005 должен упереться в таймаут.

Коротко: порядок действий

  1. VPS с Ubuntu 22.04/24.04, Docker и PostgreSQL 17 или 18
  2. /opt/databasus/docker-compose.yml с network_mode: host, затем docker compose up -d
  3. UFW: разрешить только 22, 80 и 443 — порт 4005 наружу не открывать
  4. Зайти через SSH-туннель на http://127.0.0.1:4005, задать пароль администратора (логин admin), выключить Allow sign up
  5. В psql: роль databasus с правом REPLICATION, summarize_wal = on, GRANT EXECUTE ON FUNCTION pg_switch_wal()
  6. Добавить хранилище S3 — эндпоинт обязательно со схемой https://
  7. Добавить базу: Physical, полный режим с инкрементами и потоком журнала, полная копия в 04:00, инкремент раз в час, хранение семи цепочек
  8. Проверить слот: SELECT slot_name, active FROM pg_replication_slots;, поставить max_slot_wal_keep_size
  9. Уведомитель Telegram на события Backup failed, Chain broken, WAL gap и Verification failed
  10. Запустить verification agent и включить проверку восстановления по расписанию
  11. Один раз проделать тренировочное восстановление на момент времени и засечь, сколько оно заняло
  12. Сохранить secret.key вне этого сервера

Бэкапы базы упираются в скорость диска: и снятие копии, и восстановление — это непрерывная запись и чтение. Подобрали тарифы на NVMe, где это не превращается в узкое место

VPS на NVMe 2026 →