Бэкап и восстановление Immich
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, он не зависит от бинарной структуры файлов на диске.
Что реально нужно копировать:
| Данные | Где лежат | Обязательно бэкапить | Восстановимо без бэкапа |
|---|---|---|---|
| Пользователи, альбомы, лица, embeddings | PostgreSQL (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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →