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

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

MAATRIX

Metabase удобен именно тем, что аналитики сами строят дашборды без SQL — но вся эта работа, десятки сохранённых вопросов, коллекций, подключений к источникам и настроенных прав доступа, живёт не в исходном коде, а в одной служебной базе данных. Потеряйте её без бэкапа — и восстанавливать придётся не сервис, а недели ручной настройки дашбордов. Разберём, что конкретно нужно бэкапить в Metabase, как это автоматизировать и как поднять инстанс на чистом сервере без сюрпризов.

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

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

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

Что именно нужно бэкапить в Metabase

Metabase хранит два принципиально разных типа данных, и путаница между ними — источник большинства проблем с восстановлением.

Во-первых, это application database — служебная база самого Metabase, где лежат учётные записи пользователей, настроенные подключения к источникам данных (со шифрованными паролями), сохранённые вопросы, дашборды, коллекции, пермишены, пульсы (алерты и рассылки) и лог активности. Это то, что вы теряете при сбое, если не бэкапите — не бизнес-данные, а слой аналитики поверх них.

Во-вторых — сами источники данных (ваш продовый PostgreSQL, ClickHouse, MySQL и так далее), к которым Metabase просто подключается по сети. Их бэкап — отдельная задача, не относящаяся к Metabase напрямую; об этом стоит почитать в статье про бэкап MySQL на сервере, если один из источников — MySQL.

КомпонентЧто хранитБэкапить
Application databaseпользователей, вопросы, дашборды, коллекции, шифрованные connection string к источникамда, обязательно
Docker volume metabase-data (при H2) или plugins-каталогвстроенная H2-база (тестовые инсталляции) или JDBC-драйверы для внешних БДда
MB_ENCRYPTION_SECRET_KEYключ шифрования паролей от источников данных внутри application databaseда, критично
docker-compose.yml / .envверсия образа, порты, переменные окруженияда, желательно в git
Сами источники данныхпродовые базы, к которым подключён Metabaseнет, это отдельный бэкап

По умолчанию Metabase в Docker-образе metabase/metabase использует встроенную базу H2, которая физически лежит файлом внутри контейнера. Это работает для теста за 10 минут, но не годится для продакшена: H2 не терпит параллельных подключений и плохо переживает бэкап на лету — прямое копирование файла базы во время работы сервиса легко даёт битую копию из-за незавершённых транзакций. Для рабочей инсталляции application database сразу выносят на внешний PostgreSQL; миграция с H2 делается один раз через переменные MB_DB_TYPE при первом запуске на новой базе, дальше и рассмотрим бэкап именно для этого варианта.

Бэкап application database на PostgreSQL

Если Metabase уже настроен на внешний PostgreSQL (переменные MB_DB_TYPE=postgres, MB_DB_HOST, MB_DB_DBNAME и так далее), бэкап ничем не отличается от бэкапа любой другой базы — снимаем дамп через pg_dump в custom-формате.

Если Postgres поднят рядом в том же docker-compose стеке:

cd /opt/metabase
set -a; source .env; set +a

mkdir -p /opt/metabase-backup/db

docker compose exec -T postgres pg_dump \
  -U "${MB_DB_USER}" -Fc "${MB_DB_DBNAME}" \
  > /opt/metabase-backup/db/metabase_$(date +%F_%H%M).dump

Если application database вынесена на отдельный управляемый PostgreSQL, команда та же — просто добавьте -h db.internal и PGPASSWORD перед вызовом вместо docker compose exec.

Custom-формат (-Fc) даёт сжатие и выборочное восстановление отдельных таблиц через pg_restore --table, что удобно, если нужно вытащить только report_dashboard или core_user, не поднимая всю базу целиком. Если на сервере уже настроен PostgreSQL, посмотрите общую статью про установку и настройку PostgreSQL на VPS — тюнинг work_mem и maintenance_work_mem заметно ускоряет и дамп, и восстановление на базах от нескольких гигабайт.

Если инсталляция ещё на H2 и переносить рано — снимайте бэкап штатным экспортом Metabase, а не копированием файла напрямую:

docker compose exec metabase java -jar /app/metabase.jar \
  export /tmp/metabase_export.zip

docker compose cp metabase:/tmp/metabase_export.zip \
  /opt/metabase-backup/db/metabase_export_$(date +%F).zip

Синтаксис команды может отличаться между версиями образа — проверьте --help перед первым запуском в проде.

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

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

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

Бэкап volume, конфигов и ключа шифрования

Кроме базы данных нужно сохранить ещё три вещи, без которых восстановленный Metabase либо не запустится, либо не сможет читать сохранённые подключения к источникам.

Ключ шифрования. Если задана переменная MB_ENCRYPTION_SECRET_KEY, Metabase шифрует ею пароли к источникам данных прямо в application database. Потеряете ключ — потеряете доступ ко всем настроенным подключениям, даже если сам дамп базы цел: вернуть пароли из БД без ключа невозможно, придётся вручную заново вводить их в каждый источник.

grep MB_ENCRYPTION_SECRET_KEY /opt/metabase/.env \
  >> /opt/metabase-backup/config/secrets_$(date +%F).env

Конфигурация и docker-compose. Файлы .env и docker-compose.yml держите в приватном git-репозитории или как минимум копируйте вместе с остальным бэкапом — это описание всего стека, без которого поднимать сервис заново придётся по памяти.

Плагины и загруженные ассеты. Если в Metabase установлены сторонние JDBC-драйверы (например, для ClickHouse или Databricks) или используется кастомный logo/theming через enterprise-функции, они лежат в volume metabase-data или каталоге plugins:

docker run --rm \
  -v metabase_metabase-data:/data:ro \
  -v /opt/metabase-backup/volume:/backup \
  alpine tar czf /backup/metabase-data_$(date +%F).tar.gz -C /data .

Автоматизация: скрипт, ротация, шифрование, офф-сайт

Собираем всё в один скрипт и вешаем на cron. Дамп базы, архив volume, шифрование через GPG и удаление бэкапов старше двух недель.

#!/usr/bin/env bash
set -euo pipefail

STAMP=$(date +%F_%H%M)
DEST=/opt/metabase-backup
GPG_RECIPIENT="backup@yourdomain.example"

cd /opt/metabase
set -a; source .env; set +a

mkdir -p "$DEST"/{db,volume,config}

# 1. дамп application database
docker compose exec -T postgres pg_dump \
  -U "${MB_DB_USER}" -Fc "${MB_DB_DBNAME}" \
  > "$DEST/db/metabase_${STAMP}.dump"

# 2. конфиги и ключ шифрования
cp docker-compose.yml .env "$DEST/config/"

# 3. шифруем дамп перед выгрузкой наружу
gpg --yes --batch --recipient "$GPG_RECIPIENT" \
  --output "$DEST/db/metabase_${STAMP}.dump.gpg" \
  --encrypt "$DEST/db/metabase_${STAMP}.dump"
rm "$DEST/db/metabase_${STAMP}.dump"

# 4. ротация — хранить 14 дней
find "$DEST/db" -name '*.gpg' -mtime +14 -delete

# 5. синхронизация на удалённое хранилище
rclone sync "$DEST" remote:metabase-backups --log-file=/var/log/metabase-backup.log

Добавьте в cron ежедневный запуск ночью:

0 3 * * * /opt/metabase-backup/backup.sh >> /var/log/metabase-backup-cron.log 2>&1

Шифрование важно не формальности ради: в дампе application database лежат хеши паролей пользователей Metabase и (если не задан MB_ENCRYPTION_SECRET_KEY) пароли к источникам данных в открытом виде. Отправлять такой архив на внешнее хранилище без GPG — плохая идея. Для настройки rclone под конкретное S3-совместимое хранилище или для сравнения с альтернативами вроде restic пригодится статья restic или BorgBackup — что выгоднее и когда.

Если объём данных небольшой, а инфраструктура простая, вместо самописного скрипта можно сразу отталкиваться от готового шаблона: пошаговая настройка VPS под бэкапы и архив с нуля описывает разметку диска, ротацию и мониторинг свободного места под архив бэкапов на отдельном сервере.

Восстановление Metabase из бэкапа

Порядок одинаковый что при аварии на текущем сервере, что при переезде на новый.

1. Поднимаем чистую инфраструктуру. Разворачиваем PostgreSQL и создаём пустую базу с тем же именем, что было в MB_DB_DBNAME:

docker compose up -d postgres
docker compose exec postgres createdb -U "${MB_DB_USER}" "${MB_DB_DBNAME}"

2. Восстанавливаем дамп. Если бэкап зашифрован — сначала расшифровываем:

gpg --output metabase_restore.dump --decrypt metabase_2026-08-30_0300.dump.gpg

docker compose exec -T postgres pg_restore \
  -U "${MB_DB_USER}" -d "${MB_DB_DBNAME}" --clean --if-exists \
  < metabase_restore.dump

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

3. Возвращаем ключ шифрования. Это критический шаг — переменная MB_ENCRYPTION_SECRET_KEY в новом .env должна быть точно той же, что была на старом сервере, иначе Metabase не сможет расшифровать сохранённые пароли источников данных при чтении из восстановленной базы.

4. Восстанавливаем volume с плагинами (если использовались):

docker run --rm \
  -v metabase_metabase-data:/data \
  -v /opt/metabase-backup/volume:/backup:ro \
  alpine sh -c "cd /data && tar xzf /backup/metabase-data_2026-08-30.tar.gz"

5. Запускаем Metabase и проверяем миграции. При первом старте на восстановленной базе Metabase сверяет версию схемы и накатывает недостающие миграции — это нормально, но стоит смотреть логи, а не просто ждать «зелёного» статуса:

docker compose up -d metabase
docker compose logs -f metabase | grep -i migrat

6. Проверяем сохранённые вопросы и подключения. Зайдите под админом, откройте пару дашбордов из разных коллекций и один источник данных — если пароль подключения читается без ошибки «не удалось расшифровать», ключ восстановлен верно.

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

Типичные грабли

Потеря MB_ENCRYPTION_SECRET_KEY. Самая частая и самая болезненная проблема. База восстановилась, Metabase запустился, но каждый источник данных при попытке выполнить запрос выдаёт ошибку расшифровки. Решение одно — вручную заново ввести пароли ко всем источникам через UI. Храните ключ отдельно от дампа базы, но так же надёжно.

Несовпадение версий Metabase. Если версия образа при восстановлении новее той, что писала бэкап, обычно всё в порядке — Metabase накатывает миграции вперёд автоматически. А вот откатить схему назад (восстановить дамп от новой версии на старый образ) штатно нельзя — миграции необратимы. Фиксируйте версию образа тегом (metabase/metabase:v0.51.x), а не latest, чтобы не словить неожиданный апгрейд при пересоздании контейнера.

Дамп application database не то же самое, что бэкап источников данных. Восстановив Metabase, вы вернёте дашборды и запросы, но не сами данные, которые они визуализируют — если продовый PostgreSQL или ClickHouse недоступны или тоже потеряли данные, дашборды просто покажут ошибки подключения или пустые графики.

Кодировка базы при восстановлении на новый сервер. Если целевой PostgreSQL создан с локалью или кодировкой, отличной от исходной (типично при переезде между разными дистрибутивами или облаками), pg_restore может падать на текстовых полях с не-ASCII названиями дашбордов. Создавайте новую базу явно с --encoding=UTF8 --locale=en_US.UTF-8 (или той локалью, что была на исходном сервере) — это сильно снижает шанс сюрприза.

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

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

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

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

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

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

Можно ли бэкапить Metabase без остановки сервиса?

Да, если application database на PostgreSQL — pg_dump снимает консистентный снимок на лету, без даунтайма. Для встроенной H2 безопаснее использовать штатный export.

Что произойдёт, если восстановить базу без MB_ENCRYPTION_SECRET_KEY?

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

Нужно ли бэкапить Redis, если он используется для кеша запросов?

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

Как часто нужно снимать бэкап application database?

Зависит от того, как часто аналитики создают новые вопросы и дашборды. Для активно используемого BI разумный ориентир — раз в сутки, плюс ручной снимок перед любым апгрейдом версии Metabase или миграцией на новый сервер.

Что делать, если восстанавливаю Metabase на сервер с другим hostname или IP?

Ничего специального — application database не хранит физический адрес самого себя, только адреса источников данных. Если менялся адрес самого Metabase (например, для внешних embedded-дашбордов или webhook-уведомлений), проверьте Site URL в настройках админки после запуска.

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

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

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