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

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

MAATRIX

Heimdall — классический apps dashboard для домашней лаборатории: одна страница со всеми сервисами, иконками и ссылками, куда приятно заходить с телефона. Проблема та же, что и у любого «простого» self-hosted приложения — про бэкап вспоминают только после того, как контейнер не поднялся, а вместе с ним пропали 30 карточек сервисов, теги, цвета и месяцы ручной настройки. Ниже — что именно бэкапить в Heimdall, как это автоматизировать и как восстановиться без потери данных.

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

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

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

Что нужно бэкапить в Heimdall

В отличие от Homepage, который хранит всё в YAML-файлах, Heimdall — полноценное PHP-приложение (Laravel) с базой данных. По умолчанию база — SQLite-файл, а не MySQL или PostgreSQL, что упрощает бэкап: не нужен mysqldump, достаточно скопировать один файл.

При установке через официальный образ linuxserver/heimdall всё персистентное состояние лежит в одном примонтированном каталоге, обычно /config на хосте (у вас он может называться иначе — проверьте свой docker-compose.yml). Внутри этого каталога критичны:

  • SQLite-база — файл с расширением .sqlite внутри www/, где хранятся сами приложения-карточки, теги, пользователи и настройки. Найти его точное расположение в вашей установке проще всего командой ниже.
  • Загруженные иконки — если вы заливали свои PNG/SVG вместо иконок из встроенной библиотеки, они лежат в подкаталоге uploads/ внутри той же структуры.
  • SSL-сертификаты, если вы включали HTTPS через встроенный nginx — обычно не критично, их проще перевыпустить, чем восстанавливать.
  • Логи (log/) — бэкапить не нужно, это просто мусор для архива.

Точный путь к базе стоит один раз найти на своей установке, а не полагаться на путь из чужой статьи (в разных версиях образа он менялся):

docker exec heimdall find /config -iname "*.sqlite*" 2>/dev/null

Обычно команда выведет что-то вроде /config/www/heimdall/database.sqlite — этот путь и есть ваша главная точка бэкапа. Сохраните его для себя, дальше в статье будем ссылаться на него как на $DB_PATH.

Ручной бэкап конфигурации и базы данных

SQLite — файловая база, и теоретически её можно просто скопировать cp. Но у SQLite есть нюанс: если в момент копирования идёт запись (кто-то как раз добавляет карточку сервиса или Heimdall пишет в WAL-журнал), можно получить повреждённый файл. Правильный способ — либо остановить контейнер на секунду, либо снять снимок средствами самой SQLite.

Вариант 1 — через sqlite3 .backup без остановки контейнера (безопасно даже при активной записи):

docker exec heimdall sqlite3 /config/www/heimdall/database.sqlite \
  ".backup '/config/www/heimdall/database-backup.sqlite'"
docker cp heimdall:/config/www/heimdall/database-backup.sqlite \
  /opt/backups/heimdall/heimdall-db-$(date +%Y%m%d-%H%M%S).sqlite

Команда .backup — встроенный механизм SQLite, который корректно копирует базу даже во время записи, в отличие от голого cp.

Вариант 2 — полный архив каталога конфигурации (проще, но требует секундной остановки контейнера для гарантии консистентности):

mkdir -p /opt/backups/heimdall
docker stop heimdall
tar -czf /opt/backups/heimdall/heimdall-config-$(date +%Y%m%d-%H%M%S).tar.gz \
  -C /opt/heimdall config
docker start heimdall

Простой волюм-бэкап без остановки контейнера тоже работает в большинстве случаев — SQLite достаточно надёжна к чтению «на лету», риск повреждения невелик, но не нулевой. Если для вас критично не терять ни одной карточки, используйте вариант с .backup или короткую остановку. Общий подход к бэкапу Docker-томов (не только для Heimdall) разобран в статье бэкап Docker volume на VPS.

Проверить, что архив не пустой и база в нём валидна:

tar -tzf /opt/backups/heimdall/heimdall-config-*.tar.gz | head -10
sqlite3 /opt/backups/heimdall/heimdall-db-*.sqlite "PRAGMA integrity_check;"

Вторая команда должна вернуть ok — если видите что-то другое, бэкап повреждён и полагаться на него нельзя.

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

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

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

Автоматизация через cron

Ежедневный бэкап без ручного участия — это одна строка в crontab. Комбинируем безопасный SQLite-снимок с ротацией старых копий:

crontab -e
0 3 * * * docker exec heimdall sqlite3 /config/www/heimdall/database.sqlite ".backup '/config/www/heimdall/database-backup.sqlite'" && docker cp heimdall:/config/www/heimdall/database-backup.sqlite /opt/backups/heimdall/heimdall-db-$(date +\%Y\%m\%d).sqlite && find /opt/backups/heimdall -name '*.sqlite' -mtime +14 -delete

Это решает задачу «база лежит на том же диске, что и сервер» — то есть защищает от случайной порчи файла или ошибки в UI, но не от отказа самого диска или сервера целиком. Для этого копию нужно доставлять на другую машину или в объектное хранилище — например через rclone или rsync сразу после cron-джоба, либо через restic (см. ниже), который умеет писать сразу в удалённый репозиторий.

Если вы ещё не настраивали регулярные бэкапы на сервере вообще, у нас есть отдельный общий разбор — как настроить cron-задачи на VPS с частыми ошибками формата и таймзон.

Бэкап через restic

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

export RESTIC_PASSWORD='ваш-пароль-репозитория'
restic backup /opt/heimdall/config/www/heimdall \
  --repo /mnt/backup-storage/restic-repo \
  --tag heimdall \
  --exclude 'log/*'

Политика хранения снапшотов — например, 7 дневных, 4 недельных, 3 месячных:

restic forget --repo /mnt/backup-storage/restic-repo \
  --tag heimdall \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 3 \
  --prune

Если файл базы в момент снятия снапшота restic окажется в процессе записи, вы получите тот же риск, что и с обычным cp — restic не знает про формат SQLite и просто копирует байты файла. Для полной надёжности перед restic backup можно сначала снять .backup-копию через sqlite3 (как в разделе выше) и бэкапить уже её, а не «живой» файл базы.

Если restic на вашем сервере ещё не установлен, разбор с нуля есть в статье как установить и настроить restic на VPS — там же про инициализацию репозитория и первый бэкап. Похожий подход к бэкапу другого dashboard-приложения, только с YAML вместо SQLite, разобран в статье бэкап и восстановление Homepage — если сравниваете, какой дашборд проще поддерживать в долгую, пригодится.

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

Порядок действий зависит от того, восстанавливаете вы базу на том же сервере после сбоя или переносите Heimdall на новый.

Восстановление SQLite-базы из .backup-копии:

docker stop heimdall
docker cp /opt/backups/heimdall/heimdall-db-20260830.sqlite \
  heimdall:/config/www/heimdall/database.sqlite
docker start heimdall

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

Восстановление всего конфигурационного каталога из tar-архива:

cd /opt/heimdall
docker compose down
mv config config.broken-$(date +%Y%m%d)
tar -xzf /opt/backups/heimdall/heimdall-config-20260830.tar.gz
docker compose up -d

Восстановление из restic-репозитория:

export RESTIC_PASSWORD='ваш-пароль-репозитория'
restic restore latest --repo /mnt/backup-storage/restic-repo \
  --tag heimdall \
  --target /opt/heimdall-restored

Restic сохраняет полный исходный путь, поэтому файлы окажутся во вложенной структуре — скопируйте нужную папку на место и перезапустите контейнер:

cp -r /opt/heimdall-restored/opt/heimdall/config/www/heimdall/* \
  /opt/heimdall/config/www/heimdall/
docker compose restart heimdall

Перенос на новый сервер: после восстановления базы на новой машине проверьте владельца файлов — образ linuxserver/heimdall работает от непривилегированного пользователя внутри контейнера (PUID/PGID из переменных окружения), и файл базы, скопированный от root, может оказаться недоступен для записи. Поправить:

chown -R 1000:1000 /opt/heimdall/config

(замените 1000:1000 на реальные PUID/PGID из вашего docker-compose.yml, если они отличаются). Если Heimdall у вас смотрит наружу через reverse proxy, после переноса проверьте ещё и DNS-запись домена — по нашему опыту это вторая по частоте причина «восстановил, а не открывается», сразу после прав доступа. О настройке проксирования — в статье Traefik как reverse proxy для Docker.

Частые ошибки при бэкапе и восстановлении Heimdall

ОшибкаПоследствиеКак избежать
Копируют .sqlite-файл через cp во время записиПовреждённая база, ошибка при старте контейнераИспользовать sqlite3 .backup или останавливать контейнер
Бэкапят весь /config, включая log/Архив растёт без пользы, дольше восстанавливатьИсключать log/* явно
Не проверяют целостность бэкапаУзнают о повреждённом файле только в момент аварииsqlite3 file.sqlite "PRAGMA integrity_check;" после каждого снятия
Восстанавливают базу без остановки контейнераРассинхрон данных, дублирующиеся или пропавшие карточкиdocker stop/docker compose down перед подменой файла
После переноса на новый сервер не проверяют PUID/PGIDКонтейнер не может писать в базу, ошибки в логахchown -R на актуальные UID/GID сразу после восстановления
Бэкап без ротацииДиск с бэкапами заполняется за месяцыfind ... -mtime +N -delete или restic forget --prune

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

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

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

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

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

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

Можно ли перейти с SQLite на MySQL, чтобы упростить бэкап?

Да, Heimdall поддерживает MySQL/MariaDB как альтернативную базу через переменные окружения при первом запуске, но менять СУБД на уже работающей установке без миграции данных нельзя — это по сути новая база с нуля. Для домашнего дашборда с десятками карточек SQLite обычно достаточно.

Как часто делать бэкап Heimdall?

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

Бэкап через docker commit контейнера — это нормальная практика?

Нет, docker commit создаёт образ с зашитыми в него данными на момент снимка, раздувает дисковое пространство и не даёт нормально версионировать изменения. Бэкапьте директорию /config и файл базы отдельно, а образ приложения обновляйте штатно через docker compose pull && docker compose up -d.

После восстановления часть иконок не отображается — почему?

Если иконки бэкапились не полностью (например, скопировали только базу без каталога uploads/), ссылки на кастомные иконки в базе остаются, а самих файлов нет. Проверьте, что бэкап включал весь каталог www/heimdall, а не только .sqlite-файл.

Нужно ли бэкапить SSL-сертификаты Heimdall отдельно?

Обычно нет — если сертификаты выпущены Let's Encrypt через встроенный nginx или через внешний reverse proxy, их проще перевыпустить заново после восстановления, чем поддерживать в актуальном состоянии в архиве.

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

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

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