Резервное копирование и восстановление
Две разные вещи для двух разных неприятностей.
| Зашифрованный пакет | Локальная резервная копия по расписанию | |
|---|---|---|
| Что в ней | Конфигурация: мониторы и их учётные данные, правила, каналы, страницы статуса, учётные записи, токены. | Вся база данных одним файлом, плюс secret.key. |
| Куда попадает | Куда вы её положите — она зашифрована выбранной вами парольной фразой. | /data/backups/, внутри того же тома. |
| От чего спасает | Потеря сервера, переезд на новое оборудование, чистая установка. | Изменение, о котором вы жалеете через десять минут, неудачное обновление. |
| Чего в ней нет | История метрик, состояние и история оповещений, журнал аудита, сессии. | История метрик (vm/). |
Ни то, ни другое не заменяет архив всего тома, если вам нужны и графики; об этом в конце страницы.
Зашифрованный пакет
Заголовок раздела «Зашифрованный пакет»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 incurl -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":"…"}'
# Exportcurl -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 applyjq -n --slurpfile b backup.json \ '{bundle: $b[0], passphrase: "three words are enough", apply: false}' > restore.jsoncurl -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 stopdocker 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 stopdocker 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. Миграции выполняются при запуске.
Если что-то пойдёт не так, восстановите локальную копию и запустите предыдущий тег образа.