Резервное копирование и восстановление¶
Две разные вещи для двух разных неприятностей.
| Зашифрованный пакет | Локальная резервная копия по расписанию | |
|---|---|---|
| Что в ней | Конфигурация: мониторы и их учётные данные, правила, каналы, страницы статуса, учётные записи, токены. | Вся база данных одним файлом, плюс secret.key. |
| Куда попадает | Куда вы её положите — она зашифрована выбранной вами парольной фразой. | /data/backups/, внутри того же тома. |
| От чего спасает | Потеря сервера, переезд на новое оборудование, чистая установка. | Изменение, о котором вы жалеете через десять минут, неудачное обновление. |
| Чего в ней нет | История метрик, состояние и история оповещений, журнал аудита, сессии. | История метрик (vm/). |
Ни то, ни другое не заменяет архив всего тома, если вам нужны и графики; об этом в конце страницы.
/data/secret.key — это то, что расшифровывает учётные данные ваших мониторов
Сообщества SNMP, токены Proxmox, пароли SMTP и URL heartbeat
хранятся в зашифрованном виде с ключом, производным от секрета экземпляра. При первом запуске
DumbMonit записывает его в /data/secret.key (или читает из
DUMBMONIT_SECRET, если вы его задали).
Копия базы данных без этого файла восстанавливает экземпляр, который не может ни с чем разговаривать. Сервер замечает это и отказывается запускаться с явным сообщением, вместо того чтобы падать на каждой пробе, — но учётные данные потеряны, и каждый монитор придётся вводить заново.
Зашифрованный пакет — единственное исключение: его секреты перешифрованы вашей парольной фразой, поэтому он восстанавливается на свежий экземпляр с его собственным, совершенно новым секретом.
Зашифрованный пакет¶
Settings → Backup → Download the bundle. Выберите парольную фразу не короче 16 символов — трёх слов достаточно — и подтвердите её. Скачиваемый файл — это обычный JSON с зашифрованным телом:
{
"format": "dumbmonit-backup",
"version": 1,
"created_at": "2026-09-22 19:04:11",
"source_version": "0.1.0-alpha.3",
"summary": { "targets": 12, "channels": 2, "rules": 41 },
"kdf": { "algorithm": "argon2id", "salt": "…", "m_cost": 32768, "t_cost": 3, "p_cost": 1 },
"cipher": "aes-256-gcm",
"payload": "…"
}
Заголовок остаётся читаемым, чтобы вы могли понять, что это за файл, ещё до ввода чего-либо.
Всё остальное — включая адреса — находится внутри payload, зашифрованное
AES-256-GCM ключом, производным от вашей парольной фразы через Argon2id. Восстановления
нет: пакет с утерянной парольной фразой утерян.
Пакет содержит все учётные данные этого экземпляра
Любой, у кого есть файл и парольная фраза, может прочитать пароль каждого монитора, который вы добавили. Храните его там же, где храните пароли.
Что в нём¶
| Раздел | Содержимое |
|---|---|
targets |
Мониторы: имя, тип, адрес, интервал, опции, родитель, ретранслирующий агент и учётные данные. |
rules |
Правила оповещений, включая встроенные, которые вы перенастроили или отключили. |
rule_overrides |
Пороги и исключения для отдельных мониторов. |
channels |
Каналы уведомлений, их настройки, их политика для канала и их секреты. |
notify_policy |
Глобальная политика уведомлений (группировка, почасовой лимит, flapping, публичный URL). |
silences |
Окна обслуживания. |
status_pages |
Публичные страницы статуса и сервисы, перечисленные на каждой. |
incidents |
Инциденты и объявления об обслуживании с их обновлениями. |
users |
Учётные записи: имя пользователя, отображаемое имя, роль, связь с SSO, включена или нет. |
agent_tokens |
Токены регистрации агентов, в виде хешей. Установленные агенты продолжают отправлять данные после восстановления. |
api_tokens |
Токены API, в виде хешей. Существующие токены продолжают работать. |
push_monitors |
Токены heartbeat, чтобы URL, которые уже вызывают ваши задания cron, остались прежними. |
Мониторы сопоставляются по типу + адресу, что также является уникальным ключом таблицы: повторный импорт того же пакета никогда не создаёт вторую копию чего-либо.
Пароли учётных записей¶
По умолчанию учётные записи экспортируются без хеша пароля, секрета TOTP и кодов восстановления. Восстановленные учётные записи существуют с правильным именем и ролью, но никто не может войти под ними, пока администратор не задаст пароль — или пока они не войдут через SSO, которому ничего из пакета не нужно.
Включите Include account passwords and 2FA secrets, когда вы переносите экземпляр, а не копируете его конфигурацию. Хеш Argon2 в файле, который путешествует, можно атаковать офлайн сколько угодно долго; значение по умолчанию — безопасное.
Чего в нём нет¶
История метрик (она живёт в VictoriaMetrics, а не в базе данных), состояние и история оповещений, базовые линии аномалий, журнал аудита, открытые сессии, регистрация и время последнего контакта агентов, а также кеши проб панелей Proxmox и Synology. Это наблюдения, а не настройки: они возвращаются сами.
И не секрет экземпляра. В этом суть: пакет несёт свои
секреты перешифрованными вашей парольной фразой именно для того, чтобы его можно было восстановить
там, где secret.key никогда не видели.
Восстановление на свежий экземпляр¶
- Запустите новый контейнер и создайте первую учётную запись администратора на
/setupс кодом установки, напечатанным в его логах. Эта учётная запись ваша; восстановление её не тронет. - Settings → Backup → Restore a bundle. Выберите файл, введите парольную фразу и нажмите Check this backup.
- Прочитайте отчёт. В нём по разделам сказано, что будет создано, что будет обновлено, так как отличается от того, что уже есть, и что уже идентично, — плюс примечание для всего, что не удалось разместить, например правила, указывавшего на монитор, которого нет в пакете.
- Нажмите Restore for real.
Три правила, которые восстановление никогда не нарушает:
- Ничто никогда не удаляется. Восстановление делает так, чтобы существовало то, что описывает пакет; всё, что есть в экземпляре сверх этого, остаётся.
- Ничто никогда не дублируется. Каждый элемент сопоставляется по естественному ключу —
тип + адрес для монитора,
uidдля правила, имя для канала, slug для страницы статуса. Повторное восстановление того же пакета сообщает, что всё уже идентично, и ничего не записывает. - Существующие учётные записи не трогаются. Учётная запись, имя пользователя которой уже есть, пропускается и никогда не перезаписывается: файл не должен иметь возможности изменить роль или пароль администратора, выполняющего восстановление.
Пробный прогон — это не имитация восстановления, это и есть восстановление, выполненное внутри транзакции, которая в конце откатывается. Отчёт не может ошибаться в том, что сделало бы применение.
Пакет, записанный более новым DumbMonit, отклоняется с фразой, которая так и говорит, — сначала обновитесь, потом восстанавливайте. Пакет, который был изменён или у которого неверная парольная фраза, тоже отклоняется: AES-GCM не отличает одно от другого, и сообщение тоже.
Из командной строки¶
Оба маршрута требуют сессию администратора, а не токен API: токен живёт в скрипте, а скрипту незачем экспортировать все учётные данные экземпляра.
# Sign in
curl -s -c jar -X POST https://localhost:8080/api/auth/login \
-H 'content-type: application/json' -H 'X-Requested-With: DumbMonit' \
-d '{"username":"admin","password":"…"}'
# Export
curl -s -b jar -X POST https://localhost:8080/api/backup \
-H 'content-type: application/json' -H 'X-Requested-With: DumbMonit' \
-d '{"passphrase":"three words are enough"}' -o backup.json
# Dry run, then apply
jq -n --slurpfile b backup.json \
'{bundle: $b[0], passphrase: "three words are enough", apply: false}' > restore.json
curl -s -b jar -X POST https://localhost:8080/api/backup/restore \
-H 'content-type: application/json' -H 'X-Requested-With: DumbMonit' \
-d @restore.json | jq
Локальные резервные копии по расписанию¶
DumbMonit по расписанию записывает копию собственной базы данных, по умолчанию раз в
день, храня последние семь, в /data/backups/:
/data/backups/dumbmonit-20260922-030000.db
/data/backups/dumbmonit-20260922-030000.key
Файл .db создаётся с помощью SQLite VACUUM INTO: это онлайн-копия, согласованная,
записанная пока сервер продолжает работать, а не копирование файла, которое могло бы застать
базу данных посреди записи. sqlite3 открывает её как есть, без журнала для воспроизведения.
Файл .key рядом — это копия secret.key; вместе эта пара достаточна
для восстановления экземпляра.
Они лежат в том же томе, что и база данных, поэтому они отменяют ошибку, но не потерянный диск. Копируйте их с машины, если вам нужно больше.
Настройки¶
| Переменная | По умолчанию | Назначение |
|---|---|---|
DUMBMONIT_BACKUP_ENABLED |
1 |
0, false, no или off, чтобы прекратить запись резервных копий по расписанию. |
DUMBMONIT_BACKUP_DIR |
<data dir>/backups |
Куда они записываются. Укажите второй том, чтобы пережить потерю первого. |
DUMBMONIT_BACKUP_INTERVAL_HOURS |
24 |
Часов между двумя копиями. Первая создаётся через один интервал после запуска, а не при запуске. |
DUMBMONIT_BACKUP_KEEP |
7 |
Сколько хранится. Самые старые удаляются вместе с их .key. |
Ничего другого в каталоге никогда не затрагивается: ротируются только файлы с именами
dumbmonit-<timestamp>.db и их .key.
Когда секрет экземпляра берётся из DUMBMONIT_SECRET, файла для копирования нет
и он не записывается — храните это значение в менеджере паролей. Раздел
Backup сообщает, в каком из двух случаев вы находитесь.
Как узнать, что она выполнилась¶
Каждый запуск публикует три ряда:
| Метрика | Значение |
|---|---|
dumbmonit_instance_backup_last_success_seconds |
Unix-время последней успешной резервной копии. Неудачная попытка никогда его не обновляет. |
dumbmonit_instance_backup_last_status |
1, если последняя попытка удалась, 0, если нет. |
dumbmonit_instance_backup_size_bytes |
Размер последнего записанного файла. |
Встроенное правило DumbMonit backup did not run
(instance_backup_missing) срабатывает, когда последний успех старше двух дней —
одна пропущенная ночь может быть перезапуском, две — уже проблема. Ряд
существует только после записи первой копии, поэтому экземпляру с отключённым
расписанием об этом никогда не напоминают.
Settings → Backup показывает то же самое без MetricsQL: последний запуск и его успешность, хранимые файлы и их размер, а также Back up now, чтобы записать копию немедленно.
Восстановление из копии¶
Остановите стек, верните файл под именем базы данных и восстановите ключ рядом с ней:
docker compose stop
docker run --rm -v dumbmonit-data:/data alpine sh -c '
cp /data/backups/dumbmonit-20260922-030000.db /data/dumbmonit.db &&
cp /data/backups/dumbmonit-20260922-030000.key /data/secret.key &&
rm -f /data/dumbmonit.db-wal /data/dumbmonit.db-shm'
docker compose start
Удаление файлов -wal и -shm важно: они принадлежат базе данных, которую вы
только что заменили, и SQLite попытался бы применить их к новой.
Чтобы прочитать резервную копию без восстановления, скопируйте её наружу и откройте с помощью sqlite3:
docker run --rm -v dumbmonit-data:/data -v "$PWD:/out" alpine \
cp /data/backups/dumbmonit-20260922-030000.db /out/
sqlite3 dumbmonit-20260922-030000.db 'SELECT name, kind, address FROM targets;'
Учётные данные в этом файле остаются нечитаемыми без соответствующего secret.key.
Архивирование всего тома¶
Единственный способ сохранить и графики. Один именованный том, dumbmonit-data,
содержит всё: базу данных, секрет, локальные резервные копии и данные
VictoriaMetrics.
docker compose stop
docker run --rm -v dumbmonit-data:/data -v "$PWD:/backup" alpine \
tar czf /backup/dumbmonit-data.tgz -C /data .
docker compose start
Для восстановления создайте том, распакуйте в него архив таким же образом, затем
docker compose up -d.
Если важно место, --exclude=./vm делает архив небольшим: база данных и
секрет — это настройка, vm/ — только история.
Что сделать перед обновлением¶
- Settings → Backup → Back up now — тридцать секунд, и в копию входит секрет.
- Скачайте также пакет, если обновление крупное или если вы переезжаете на другую машину.
docker compose pull && docker compose up -d. Миграции выполняются при запуске.
Если что-то пойдёт не так, восстановите локальную копию и запустите предыдущий тег образа.