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 + сжатие zstd | pg_basebackup + pg_receivewal |
| Версии PostgreSQL | 14–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Вставьте в файл:
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-туннель. Команда выполняется на вашем компьютере, не на сервере:
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".
sudo -u postgres psqlCREATE 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-й версии):
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 и открыть порт только этому адресу.
# 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 запускает мастер. Порядок шагов такой:
- Тип базы — PostgreSQL.
- 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.
- Подключение: host
127.0.0.1, port5432, пользовательdatabasusи пароль, который вы задали в третьем шаге. Версию укажите свою — 17 или 18. - Режим физического бэкапа — из трёх вариантов берите
Full + incremental + WAL. Только он даёт откат на момент времени; два других делают либо просто полные копии, либо полные с инкрементами. - Расписание: полная копия раз в сутки в 04:00, инкремент — раз в час. Инкремент обязан быть чаще полной копии, иначе Databasus сам подтянет интервал.
- Хранение: проще всего выбрать хранение цепочек и указать 7 — это семь последних наборов «полная копия плюс её инкременты».
- Хранилище — то, что настроили на четвёртом шаге.
- Шифрование — оставьте включённым.
Кнопка 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 МБ, авторизация для скачивания не нужна:
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-agentsudo ./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 zstd2. В панели откройте базу, вкладку с бэкапами, и выберите восстановление на момент времени. Укажите время (в 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:
# три файла конфигурации с рабочего сервера
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/datasudo -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 доиграл журнал ровно до нужной секунды и остановился перед роковой транзакцией:
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 connectionssudo -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 МБ |
| Образ Docker | 317 МБ |
| Каталог databasus-data с парой бэкапов | 67 МБ |
| Полная копия свежего кластера PostgreSQL 17 | 2,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 внутри контейнера.
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 должен упереться в таймаут.
Коротко: порядок действий
- VPS с Ubuntu 22.04/24.04, Docker и PostgreSQL 17 или 18
/opt/databasus/docker-compose.ymlсnetwork_mode: host, затемdocker compose up -d- UFW: разрешить только 22, 80 и 443 — порт 4005 наружу не открывать
- Зайти через SSH-туннель на
http://127.0.0.1:4005, задать пароль администратора (логинadmin), выключить Allow sign up - В
psql: рольdatabasusс правомREPLICATION,summarize_wal = on,GRANT EXECUTE ON FUNCTION pg_switch_wal() - Добавить хранилище S3 — эндпоинт обязательно со схемой
https:// - Добавить базу: Physical, полный режим с инкрементами и потоком журнала, полная копия в 04:00, инкремент раз в час, хранение семи цепочек
- Проверить слот:
SELECT slot_name, active FROM pg_replication_slots;, поставитьmax_slot_wal_keep_size - Уведомитель Telegram на события Backup failed, Chain broken, WAL gap и Verification failed
- Запустить verification agent и включить проверку восстановления по расписанию
- Один раз проделать тренировочное восстановление на момент времени и засечь, сколько оно заняло
- Сохранить
secret.keyвне этого сервера
Бэкапы базы упираются в скорость диска: и снятие копии, и восстановление — это непрерывная запись и чтение. Подобрали тарифы на NVMe, где это не превращается в узкое место
VPS на NVMe 2026 →