Бэкап и восстановление PhotoPrism
PhotoPrism — self-hosted фотоархив с ИИ-тегированием (распознавание объектов, лиц, геопривязка), который многие ставят как альтернативу Google Photos или Immich. Проблема в том, что архив в PhotoPrism — это не один файл, а три разных компонента: сами фото, база данных с индексом и метаданными, и конфиг. Если бэкапить только «originals», после восстановления вы получите папку с фотографиями без альбомов, лиц и разметки — и придётся переиндексировать всё заново. Ниже — рабочая схема, что и как бэкапить, чтобы восстановиться за минуты, а не пересобирать архив с нуля.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что реально нужно бэкапить
PhotoPrism в стандартной docker-compose конфигурации хранит данные в трёх местах:
originals/— сами фотографии и видео. Это единственные данные, которые физически невосстановимы при потере: если пропали, ИИ-индекс их не воссоздаст.- база данных MariaDB (или встроенный SQLite, если вы не поднимали отдельный контейнер) — индекс, альбомы, метки лиц, лейблы, оценки, изменения, сделанные руками через веб-интерфейс. Технически архив можно переиндексировать заново, но альбомы и «обученные» лица при этом не восстановятся — PhotoPrism распознает объекты заново, но не знает, что лицо на фото — это именно ваша сестра, если вы её один раз подписали.
storage/— кэш миниатюр (regenerable, можно не бэкапить), конфиг (storage/config), и, если включены sidecar-файлы, YAML-описания метаданных рядом с оригиналами.
Отдельно стоит storage/sidecar (или путь, заданный в PHOTOPRISM_SIDECAR_PATH) — если вы включили PHOTOPRISM_SIDECAR_YAML=true, PhotoPrism дублирует правки метаданных (альбомы, теги, координаты) в YAML-файлы рядом с фото. Это де-факто человекочитаемый бэкап базы: даже если MariaDB потеряна, из sidecar можно восстановить большую часть ручных правок при переиндексации.
Итоговый список для бэкапа:
originals/— обязательно, полностью.- Дамп MariaDB (или файл SQLite, если без отдельной БД).
storage/sidecar/— если включён, крайне желательно.storage/config/— настройки, включая соль для паролей.docker-compose.ymlи.env— без них новый сервер придётся конфигурировать с нуля.
storage/cache и storage/temp в бэкап не включайте — это регенерируемые данные, которые только раздувают архив.
Встроенные команды backup/restore
У PhotoPrism есть свой CLI для бэкапа индекса и альбомов — это быстрее, чем ворочать сырой SQL-дамп, и работает даже если вы используете встроенный SQLite:
# бэкап индекса (база) и альбомов в YAML
docker compose exec photoprism photoprism backup -a -i
# результат обычно ложится в storage/backup/index.sql
# и в originals/.photoprism/ (album YAML)
Флаги могут отличаться между версиями образа — актуальный список смотрите через:
docker compose exec photoprism photoprism backup --help
Восстановление зеркально:
docker compose exec photoprism photoprism restore -a -i -f
-f (force) перезаписывает существующий индекс — используйте осторожно, на проде сначала снимите ещё один снэпшот. Важный нюанс: photoprism backup бэкапит индекс, а не файлы фотографий — это дополнение к бэкапу originals/, а не замена.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверБэкап MariaDB напрямую
Если держите PhotoPrism с отдельным MariaDB (а не встроенным SQLite — так делает большинство инсталляций с архивом больше пары тысяч снимков, потому что SQLite на больших индексах тормозит), дамп через mysqldump даёт более портируемый бэкап, чем формат photoprism backup:
docker compose exec mariadb sh -c \
'exec mysqldump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction photoprism' \
> photoprism-db-$(date +%F).sql
Флаг --single-transaction даёт консистентный снимок без блокировки таблиц и без остановки контейнера PhotoPrism — можно бэкапить на живом сервере, не прерывая доступ.
Восстановление на чистую БД:
docker compose exec -T mariadb sh -c \
'exec mysql -u root -p"$MARIADB_ROOT_PASSWORD" photoprism' \
< photoprism-db-2026-08-25.sql
Если бэкапите на встроенном SQLite (без контейнера MariaDB), файл базы обычно лежит в storage/database/index.db — его достаточно скопировать как обычный файл, но делайте это либо при остановленном PhotoPrism, либо утилитой, которая умеет консистентно копировать SQLite «на лету» (например, sqlite3 index.db ".backup backup.db" внутри контейнера), иначе рискуете получить повреждённый файл при копировании во время записи.
Автоматизация с restic на отдельный сервер
Хранить бэкап фотоархива на том же диске, где живёт сам архив, — это не бэкап, а иллюзия бэкапа: один упавший диск убивает и оригинал, и копию. Дальше — рабочий скрипт на restic, который снимает дамп БД, упаковывает originals и sidecar, и льёт всё на отдельный сервер по SFTP.
#!/usr/bin/env bash
set -euo pipefail
PP_DIR=/opt/photoprism
DUMP=/tmp/photoprism-db-$(date +%F).sql
export RESTIC_REPOSITORY="sftp:user@backup-host:/backups/photoprism"
export RESTIC_PASSWORD_FILE=/etc/restic/photoprism.key
# 1. консистентный дамп БД без остановки сервиса
docker compose -f "$PP_DIR/docker-compose.yml" exec mariadb sh -c \
'exec mysqldump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction photoprism' \
> "$DUMP"
# 2. снимок в restic: фото, sidecar, конфиг и свежий дамп
restic backup \
"$PP_DIR/originals" \
"$PP_DIR/storage/sidecar" \
"$PP_DIR/storage/config" \
"$DUMP" \
--tag photoprism
# 3. ротация: держим дневные снимки неделю, недельные — 2 месяца
restic forget --keep-daily 7 --keep-weekly 8 --prune
rm -f "$DUMP"
restic дедуплицирует блоки — при ежедневном бэкапе большого архива фото каждый следующий снимок «доливает» только изменения, а не копирует терабайты заново. Разверните такой сервер отдельно от продакшн-машины: у нас есть отдельный разбор, какой VPS брать под бэкапы и архив — обычно это тариф с упором на диск, а не на CPU. Про сам инструмент подробнее — в статье про бэкап и восстановление через restic.
Добавьте задачу в cron на самом сервере с PhotoPrism:
# каждую ночь в 03:15
15 3 * * * /opt/photoprism/backup.sh >> /var/log/photoprism-backup.log 2>&1
Восстановление на новом сервере с нуля
Сценарий: старый сервер недоступен, нужно поднять PhotoPrism заново из бэкапа.
- Разверните новый сервер и поставьте Docker с docker-compose (если ставили PhotoPrism впервые, у нас есть пошаговая установка PhotoPrism на Ubuntu 24.04).
- Восстановите файлы из restic-репозитория:
restic restore latest --target /opt/photoprism-restore \
--path /opt/photoprism/originals
Повторите для storage/sidecar, storage/config и файла дампа БД, либо восстановите весь снапшот целиком и разложите руками по нужным путям.
- Разложите восстановленные
originals/иstorage/по местам, которые ждёт docker-compose.yml (тот жеdocker-compose.yml, который тоже был в бэкапе — не пересоздавайте его вручную, чтобы не разойтись в путях и переменных окружения). - Поднимите контейнер MariaDB и залейте дамп до первого старта PhotoPrism:
docker compose up -d mariadb
sleep 15
docker compose exec -T mariadb sh -c \
'exec mysql -u root -p"$MARIADB_ROOT_PASSWORD" photoprism' \
< photoprism-db-2026-08-25.sql
docker compose up -d photoprism
- Проверьте, что PhotoPrism видит фото и не начал их заново индексировать «с нуля» (при полном восстановлении БД он должен просто подхватить существующий индекс). Если индекс не совпал с файлами (например, вы восстановили originals из более свежего снапшота, чем БД), запустите:
docker compose exec photoprism photoprism index
Это досканирует новые/изменившиеся файлы, не трогая существующую разметку.
Частые ошибки при бэкапе и восстановлении фотоархива
- Бэкапят только
originals/, забывая про БД. После восстановления получаете папку с фото без единого альбома и без разметки лиц — придётся индексировать заново и переобучать распознавание лиц вручную. - Дамп БД снимают без
--single-transactionна живом сервере — можно поймать несогласованный снимок, если в момент дампа кто-то как раз редактирует альбом или идёт фоновая индексация. - Не совпадают UID/GID при восстановлении. Официальный образ пишет файлы от определённого пользователя внутри контейнера; если на новом сервере volume смонтирован с другими правами, PhotoPrism может не увидеть восстановленные originals как «свои» — проверьте
PUID/PGIDи права на директории (chown -Rна хосте после restore). - Восстанавливают originals из более нового снапшота, чем БД (или наоборот) — рассинхрон между файлами и индексом. Берите originals и дамп БД из одного прогона бэкапа, не микшируйте снапшоты за разные дни.
- Хранят
.envтолько на работающем сервере. Если контейнер и.envпотеряны одновременно, восстановленный дамп некому расшифровывать в смысле доступа к БД. Держите.envв том же бэкапе — restic шифрует репозиторий целиком, этого достаточно. - Забывают протестировать восстановление. Бэкап, который ни разу не разворачивали на чистой машине, — это гипотеза, а не бэкап. Раз в квартал стоит поднимать тестовый контейнер и проверять, что дамп и originals реально разворачиваются.
Сколько ресурсов закладывать под бэкап и восстановление
Фотоархив с ИИ-тегированием — тяжёлая штука по диску и ощутимая по CPU/RAM в момент индексации, это стоит учитывать при выборе сервера:
| Параметр | На что влияет |
|---|---|
| Диск на originals | Растёт линейно с архивом: RAW-фото и видео с телефона — счёт на сотни гигабайт при паре лет накопления |
| Диск на storage/cache | Миниатюры и превью — обычно 10–30% от объёма originals, но не бэкапится (регенерируется) |
| RAM при индексации/переиндексации | ИИ-модели (объекты, лица) грузятся в память; на слабом VPS с 2 ГБ RAM индексация большого архива может идти медленно или падать по OOM |
| CPU при переиндексации | Классификация — CPU-bound задача; на восстановлении с нуля, если БД потеряна и индекс приходится строить заново, это может занять от часов до суток в зависимости от объёма архива и мощности сервера — ориентируйтесь по факту на своём железе, точных цифр без замера на конкретном CPU не дам |
| Диск на бэкап-сервере | Как минимум равен originals + дамп БД + запас на несколько версий (restic хранит только дельты, но полный первый снапшот весит как originals) |
Практический вывод: сам PhotoPrism можно держать на скромном VPS, если не бэкапить и не переиндексировать одновременно с активным использованием, но отдельный сервер под бэкапы стоит брать с диском в 1.5–2 раза больше текущего объёма originals — на рост архива и на историю снапшотов restic. У нас есть отдельный разбор по сайзингу — сколько ресурсов нужно VPS для бэкапов и архива.
Если рассматриваете PhotoPrism именно как замену Immich — учитывайте, что подход к бэкапу у обоих похож (файлы и БД бэкапятся раздельно), но структура каталогов и CLI-команды разные, так что скрипт под один инструмент напрямую под другой не переносится.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Нужно ли останавливать PhotoPrism перед бэкапом?
Нет, если бэкапите дамп БД через mysqldump --single-transaction и файлы через restic (который снимает консистентный снапшот файловой системы на момент запуска). Полная остановка контейнера имеет смысл только для максимально надёжного «холодного» бэкапа перед крупным обновлением версии.
Что делать, если потеряна только база, а originals целы?
Восстановите дамп БД (если есть) или запустите photoprism index — фото и метки будут переиндексированы, но ручные правки (названия альбомов, подписанные лица), сделанные после последнего бэкапа БД или sidecar-файлов, будут потеряны.
Можно ли бэкапить PhotoPrism на встроенном SQLite так же, как с MariaDB?
Частично — вместо mysqldump используйте sqlite3 storage/database/index.db ".backup /tmp/index-backup.db" внутри контейнера для консистентной копии, остальная схема (originals + sidecar + restic) не меняется.
Сколько версий бэкапа стоит хранить?
Для личного фотоархива обычно достаточно 7 дневных и 8 недельных снапшотов (как в примере restic выше) — этого хватает, чтобы откатиться на пару месяцев назад при обнаружении случайного удаления, не разово замеченного.
Что бэкапить в первую очередь, если места на бэкап-сервере не хватает на всё?
Приоритет: originals (невосстановимы) → дамп БД → sidecar. Кэш миниатюр (storage/cache) не бэкапьте вообще — это чистая экономия места без риска.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →