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

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

MAATRIX

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

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

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

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

Что бэкапить в Immich: база, библиотека и то, что можно не трогать

Immich хранит данные в двух принципиально разных местах, и путать их нельзя. Первое — база PostgreSQL: пользователи, альбомы, метаданные фото, результаты распознавания лиц и векторные embeddings для поиска по содержимому. Второе — каталог UPLOAD_LOCATION на диске, куда пишутся сами файлы: оригиналы, миниатюры, перекодированное видео.

Важный нюанс: контейнер базы данных в Immich — не ванильный Postgres, а сборка с расширением для векторного поиска (используется для CLIP-embeddings и поиска «найди фото, где закат на пляже»). Конкретный образ и тег меняются от релиза к релизу — актуальные значения смотрите в docker-compose.yml, который тянете с официального репозитория Immich под свою версию. Но суть не меняется: из-за нестандартного расширения бэкапировать «сырые» файлы каталога данных Postgres (DB_DATA_LOCATION) ненадёжно — версия расширения и формат внутренних файлов должны точно совпадать при восстановлении. Официально рекомендованный способ — логический дамп через pg_dumpall, он не зависит от бинарной структуры файлов на диске.

Что реально нужно копировать:

ДанныеГде лежатОбязательно бэкапитьВосстановимо без бэкапа
Пользователи, альбомы, лица, embeddingsPostgreSQL (pg_dumpall)ДаНет
Оригиналы фото и видеоUPLOAD_LOCATION/library, /uploadДаНет
Миниатюры (thumbs)UPLOAD_LOCATION/thumbsНетДа, регенерируются из оригиналов
Перекодированное видеоUPLOAD_LOCATION/encoded-videoНетДа, но заново грузит CPU на перекодирование
Кэш ML-моделейvolume model-cacheНетДа, скачивается заново при старте
Очередь задачRedisНетДа, теряется только текущая очередь джоб

Вывод простой: реальная ценность — это дамп базы и содержимое library/upload. Остальное — производные данные, которые Immich пересоберёт сам, потратив на это время и вычислительные ресурсы, но не потеряв ничего безвозвратно.

Дамп PostgreSQL с учётом векторного расширения

Найдите имя контейнера базы (обычно immich_postgres, если не меняли container_name в compose-файле) и переменные из вашего .env:

cd /opt/immich   # или где у вас лежит docker-compose.yml Immich
grep -E '^DB_' .env

Снять дамп можно на живой базе — pg_dumpall делает согласованный снапшот в рамках транзакции, останавливать Immich для этого не нужно:

mkdir -p /mnt/backup/immich
docker exec -t immich_postgres pg_dumpall \
  --clean --if-exists \
  --username="${DB_USERNAME:-postgres}" \
  | gzip > /mnt/backup/immich/db-$(date +%F).sql.gz

Флаги --clean --if-exists добавляют в дамп команды DROP ... IF EXISTS перед созданием объектов — это делает восстановление идемпотентным: можно накатить дамп на уже существующую (пустую) базу без ручной зачистки схемы. Проверить, что дамп не пустой и не оборвался:

zcat /mnt/backup/immich/db-$(date +%F).sql.gz | tail -5
# последняя строка нормального дампа — "-- PostgreSQL database dump complete"

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

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

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

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

Бэкап библиотеки фото и видео

Каталог UPLOAD_LOCATION — это тело вашей фотоколлекции, обычно самая тяжёлая часть бэкапа по объёму. Immich не переписывает уже загруженные оригиналы — новые файлы только добавляются, — поэтому инкрементальный бэкап работает без риска зацепить файл на середине записи.

Для дедупликации и шифрования удобно взять restic (подробная настройка — в статье про бэкап и восстановление restic):

export RESTIC_REPOSITORY=/mnt/backup-disk/immich-restic
export RESTIC_PASSWORD_FILE=/root/.restic-immich-pass
restic init   # один раз при первой настройке

restic backup "${UPLOAD_LOCATION}" \
  --tag immich-library \
  --exclude="${UPLOAD_LOCATION}/thumbs" \
  --exclude="${UPLOAD_LOCATION}/encoded-video"

Исключение thumbs и encoded-video из таблицы выше сознательное — это регенерируемые данные, и не включать их в бэкап значит экономить место и время на каждом прогоне. Если пересчёт миниатюр на вашей библиотеке занимает неприемлемо долго (актуально на больших коллекциях с ограниченным CPU) — включите их обратно, дедупликация restic всё равно ограничит прирост объёма.

Если под архив у вас выделен отдельный сервер (держать бэкап на том же диске, где основные данные, не защищает вообще ни от чего), настройте RESTIC_REPOSITORY через SFTP на второй сервер вместо локального пути; требования к такому серверу под архив разобраны в статье про VPS для бэкапов и архива.

Автоматизация: скрипт и systemd timer

Собираем дамп базы и бэкап библиотеки в один скрипт и вешаем на таймер — так же, как для любого другого бэкапа на сервере:

#!/usr/bin/env bash
# /usr/local/bin/immich-backup.sh
set -euo pipefail

cd /opt/immich
source .env

BACKUP_DIR=/mnt/backup/immich
mkdir -p "$BACKUP_DIR"

# 1. Дамп базы
docker exec -t immich_postgres pg_dumpall --clean --if-exists \
  --username="${DB_USERNAME:-postgres}" \
  | gzip > "$BACKUP_DIR/db-$(date +%F).sql.gz"

# храним дампы за последние 14 дней, старее — удаляем
find "$BACKUP_DIR" -name 'db-*.sql.gz' -mtime +14 -delete

# 2. Библиотека через restic
export RESTIC_REPOSITORY=/mnt/backup-disk/immich-restic
export RESTIC_PASSWORD_FILE=/root/.restic-immich-pass

restic backup "${UPLOAD_LOCATION}" \
  --tag immich-library \
  --exclude="${UPLOAD_LOCATION}/thumbs" \
  --exclude="${UPLOAD_LOCATION}/encoded-video"

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
chmod +x /usr/local/bin/immich-backup.sh

Systemd unit и таймер:

# /etc/systemd/system/immich-backup.service
[Unit]
Description=Immich backup (DB + library)

[Service]
Type=oneshot
ExecStart=/usr/local/bin/immich-backup.sh
# /etc/systemd/system/immich-backup.timer
[Unit]
Description=Daily Immich backup

[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now immich-backup.timer
systemctl list-timers | grep immich

Время 04:00 выбрано с запасом от ночных фоновых задач самого Immich (перекодирование видео, распознавание лиц) — если у вас они идут в другое окно, сдвиньте таймер, чтобы бэкап не соревновался с ними за диск и CPU. Уведомление об успехе или падении бэкапа стоит подключить отдельно через ExecStartPost — молчаливо упавший ночной бэкап обнаруживается обычно в худший момент, при попытке восстановления.

Восстановление на новом сервере

Сценарий «сервер умер, разворачиваем на новом» — ровно то, ради чего затевался весь бэкап. Порядок действий:

1. Поднимите базовое окружение. Установите Docker (см. установку Docker на Debian 12 или на AlmaLinux, если используете её), скопируйте на сервер docker-compose.yml и .env от прежней установки Immich — версию (IMMICH_VERSION) на первом шаге лучше взять ту же, что была на момент снятия дампа, а не последний релиз (причина — в разделе про грабли ниже).

2. Восстановите библиотеку из restic:

export RESTIC_REPOSITORY=/mnt/backup-disk/immich-restic
export RESTIC_PASSWORD_FILE=/root/.restic-immich-pass

mkdir -p "${UPLOAD_LOCATION}"
restic restore latest --target "${UPLOAD_LOCATION}" --path "${UPLOAD_LOCATION}"

3. Поднимите только базу данных (без основного сервера — восстанавливать дамп нужно на пустую, но уже проинициализированную БД):

docker compose up -d database
sleep 10   # дать Postgres время на инициализацию первого запуска

4. Накатите дамп:

gunzip -c /mnt/backup/immich/db-2026-08-30.sql.gz \
  | docker exec -i immich_postgres psql --username="${DB_USERNAME:-postgres}"

Флаги --clean --if-exists, добавленные при снятии дампа, тут и пригождаются — команда отработает даже если в свежей БД уже есть системные объекты, созданные при первом старте контейнера.

5. Запустите весь стек и проверьте:

docker compose up -d
docker compose logs -f immich-server

Откройте веб-интерфейс, войдите под своей учётной записью, проверьте, что альбомы и лица на месте. Если исключали thumbs из бэкапа — миниатюры перестроятся фоново при первом обращении к фото, это ожидаемо и не повод для паники.

Типичные грабли при восстановлении

  • Несовпадение версий Immich. Схема базы меняется от релиза к релизу, и дамп со старой версии не всегда корректно накатывается сразу на свежий образ. Безопасный порядок: поднять ту же версию (IMMICH_VERSION), что была на момент дампа, убедиться, что всё работает, и только потом штатно обновиться — миграции применит сам Immich при старте, а не вы вручную поверх чужого дампа.
  • Права на UPLOAD_LOCATION. После restic restore владелец файлов может не совпадать с тем, под кем работает контейнер сервера — при ошибках доступа к оригиналам проверьте chown каталога в соответствии с compose-файлом.
  • Соблазн скопировать DB_DATA_LOCATION вместо дампа. Из-за нестандартного расширения для векторного поиска это ненадёжный путь: совпадение версии образа на источнике и приёмнике не гарантировано, а pg_dumpall от такой зависимости свободен.
  • Кончилось место на диске прямо во время бэкапа. На больших библиотеках это обнаруживается не сразу — держите мониторинг свободного места отдельно от факта «скрипт завершился без ошибки», иначе об оборванном дампе вы узнаете только при попытке восстановления.
  • Бэкап никогда не проверяли восстановлением. Рабочий backup не гарантирует рабочий restore — стоит хотя бы раз в несколько месяцев поднимать восстановление на тестовом сервере, подробнее это разобрано в статье про восстановление базы данных из бэкапа на практике.

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

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

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

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

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

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

Нужно ли останавливать Immich перед бэкапом?

Нет. Дамп через pg_dumpall согласован в рамках транзакции и снимается на живой базе, а файлы UPLOAD_LOCATION не перезаписываются задним числом — можно бэкапить оба компонента без даунтайма.

Можно ли скопировать каталог DB_DATA_LOCATION вместо дампа, если хочется побыстрее?

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

Сколько места закладывать под бэкап библиотеки?

Ориентировочно от объёма самой библиотеки плюс запас под глубину истории restic (retention-политика из примера выше даёт умеренный прирост за счёт дедупликации, но точная цифра зависит от того, как часто пересохраняются похожие файлы) — на практике проще посмотреть restic stats после первой недели работы и скорректировать диск под сервер.

Что делать, если восстановили дамп, а Immich не стартует с ошибкой миграции?

Проверьте, что версия IMMICH_VERSION в .env совпадает (или совместима) с версией, на которой снимался дамп — восстановление на сильно более новый релиз без промежуточного шага может упереться в отсутствующие миграции.

Стоит ли держать бэкап Immich на том же сервере, где он работает?

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

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

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

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