Immich: ставим фототеку на свой сервер | Виталий Воробьев
VorobeoffAIВиталий Воробьев

Immich: ставим фототеку на свой сервер

Immich — open-source фототека на Docker: распознавание лиц, CLIP-поиск, мобильный бэкап, внешние библиотеки, бэкапы и восстановление.

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

Код открыт под AGPL v3. Разворачивается в контейнерах на любом хосте: VPS, мини-ПК, домашний NAS — без разницы. Поднятие занимает четверть часа. А вот первичная обработка архива — миниатюры, кластеризация лиц, построение векторов — идёт часами, и это нормально.

Важно: Immich — не единственное хранилище. Резервные копии по правилу 3-2-1 обязательны. Не стирайте исходники, пока не убедитесь, что восстановление из резервной копии работает.

Что такое Immich

Immich — серверная фототека с веб-интерфейсом и нативными приложениями для iOS и Android. Архитектура — набор контейнеров: ядро-сервер, модуль машинного обучения, кэш на Redis или Valkey и база Postgres с расширением VectorChord для семантического поиска.

VectorChord — расширение Postgres, которое умеет хранить и сравнивать векторы: числовые представления изображений, построенные нейросетью. Близость векторов в этом пространстве означает смысловое сходство, и это даёт поиск по содержимому кадра, а не по именам файлов.

Интерфейс фототеки Immich версии 3.0
Интерфейс фототеки Immich версии 3.0
ЗадачаОблачные сервисыImmich
Оригиналы
Квота тарифа, сжатие при экономии
Полные копии на вашем диске, лимит — объём железа
Цена
Подписка, растущая с объёмом
Разово на железо плюс электричество
Распознавание лиц
На серверах провайдера
Локально, в контейнере ML
Семантический поиск
Встроенный
CLIP-модель на выбор, поддержка разных языков
Приватность
Данные и метаданные у провайдера
Всё остаётся на вашем сервере
Стабильность
Промышленный сервис
Активная разработка, случаются ломающие релизы

Аудитория: те, кому важно держать фото-архив под контролем и кто не боится Docker Compose. Сложного администрирования не нужно, но базовое понимание томов, переменных окружения и резервного копирования обязательно.

Зачем нужно

  • Автобэкап с телефона — приложение в фоне отправляет новые кадры на сервер, выбор альбомов на усмотрение
  • Таймлайн и альбомы — хронологическая лента, подборки, избранное, архив
  • Распознавание лиц — группировка по людям, поиск по одному или нескольким лицам
  • Контекстный поиск — запросы по смыслу кадра, без привязки к названиям и метаданным
  • OCR — распознавание текста на изображениях: скриншоты, документы, вывески ищутся по содержанию
  • Карта и геопоиск — города, регионы, страны через обратное геокодирование
  • Несколько пользователей — изолированные библиотеки, общие альбомы, партнёрский доступ
  • Внешние библиотеки — индексация папок, уже лежащих на диске, без копирования внутрь сервера
Мобильный интерфейс Immich для просмотра и резервного копирования фотографий
Мобильный интерфейс Immich для просмотра и резервного копирования фотографий

Как устроен поиск

Поиск работает целиком в Postgres. Метаданные и векторы CLIP хранятся в одной базе, векторную часть обслуживает VectorChord. CLIP — нейросеть, которая переводит картинку и текстовый запрос в векторы общего пространства: чем ближе координаты, тем выше релевантность. Это и даёт запросы вроде «закат на пляже» или «собака в парке» — без тегов и описаний.

Поверх свободного поиска — фильтры: по людям, альбомам, имени или расширению файла, исходной папке, описанию, тексту на картинке, локации, тегам, камере и объективу, периоду, типу медиа, рейтингу.

Модель выбирается в Administration, дальше Settings, Machine Learning Settings, Smart Search. Дефолтная модель быстрая, но более крупные варианты выдают точнее ранжирование.

СценарийКакие модели рассматривать
Только английские запросы
ViT-B-16-SigLIP2__webli — сбалансированный выбор: порядка 3 ГБ памяти, около 5,8 мс на запрос, 84,86% recall по тестам документации
Ограниченное железо
ViT-B-32-SigLIP2-256__webli — быстрее (около 3,3 мс), recall ~82%
Преимущественно русский
Семейство nllb, вариант nllb-clip-base-siglip__v1 — тяжелее (порядка 4,7 ГБ, около 15 мс), язык запроса берётся из настроек пользователя
Смешанные языки
Модели xlm и siglip2 — воспринимают запрос вне зависимости от языка интерфейса

Совет: после смены модели запустите переиндексацию — страница задач, кнопка All рядом со Smart Search. Иначе старые векторы останутся несовместимыми, и в логах появятся ошибки.

Требования к железу

ПараметрМинимумРекомендация
ОС
Linux или Unix-подобная система
Linux на bare metal или в VM
RAM
6 ГБ (4 ГБ без машинного обучения)
8 ГБ
CPU
2 ядра
4 ядра
Архитектура
amd64 или arm64
Для amd64 — x86-64-v2 и выше
Файловая система
EXT4, ZFS, APFS
Локальный SSD под Postgres
Docker
Docker Engine и плагин Compose
Команда docker compose (не docker-compose)

На превью и транскоды закладывайте 10–20% поверх объёма библиотеки. База обычно разрастается до 1–3 ГБ.

Внимание: путь DB_DATA_LOCATION — только локальный диск. Сетевое хранилище, NTFS, exFAT или монтирование из /mnt в WSL испортят базу. В Windows и WSL переходите на именованный том: DB_DATA_LOCATION=pgdata и добавьте pgdata: в секцию volumes.

Docker внутри LXC-контейнера разработчики не рекомендуют. Последняя версия для процессоров x86-64-v1 — v2.7.5, поддержки больше нет.

Установка через Docker Compose

Шаг 1. Заготовка каталога

mkdir ./immich-app
cd ./immich-app
wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env

Шаг 2. Переменные окружения

ПеременнаяДефолтНа что обратить внимание
UPLOAD_LOCATION
./library
Медиатека. Перенесите на большой диск или массив, если нужно
DB_DATA_LOCATION
./postgres
Только локальный SSD, никогда — сетевое хранилище
TZ
закомментирована
Раскомментируйте и поставьте свой часовой пояс
IMMICH_VERSION
v3
Закрепите конкретную версию для предсказуемых обновлений
DB_PASSWORD
postgres
Смените. Только латиница и цифры
DB_USERNAME, DB_DATABASE_NAME
postgres, immich
Можно не менять

Шаг 3. Запуск

docker compose up -d

Веб-интерфейс поднимается на порту 2283. Первый, кто вошёл, получает права администратора.

Внимание: частые ошибки при старте — unknown shorthand flag ‘d’ означает устаревший docker-compose вместо плагина Compose; permission denied при чтении.env — проблема с правами; can’t set healthcheck.start_interval — нужен Docker Engine 25+ или закомментируйте start_interval в секции database.

После установки

Структура хранения файлов

Storage template задаёт, как оригиналы раскладываются по папкам. Дефолт — Year/Year-Month-Day/Filename.Extension, меняется в Administration, Settings, Storage Template. Настройте до массовой загрузки: после смены шаблона запускается задача Storage Template Migration, и на готовой библиотеке она работает долго.

Аппаратное ускорение

На мини-ПК и NAS процессор становится узким горлышком в двух местах: видеотранскодинг и машинное обучение. Перекодирование можно ускорить через NVENC (NVIDIA), Quick Sync (Intel), VAAPI (AMD, Intel, NVIDIA) и RKMPP (Rockchip). Но это не одна галочка: рядом с compose-файлом кладётся hwaccel.transcoding.yml из дистрибутива, в сервисе immich-server раскомментируется секция extends, параметр cpu меняется на нужный бэкенд — и только потом ускорение включается в настройках.

Для ускорения машинного обучения в документации выделен отдельный раздел — Hardware-Accelerated Machine Learning.

Внимание: аппаратное ускорение — только Linux и Windows через WSL2. Quick Sync в WSL2 не работает, Raspberry Pi не поддерживается. По умолчанию ускоряется кодирование; декодирование включается отдельно.

Практические сценарии

Перенос архива с телефона

  • Установите мобильное приложение и впишите адрес сервера
  • Войдите под своей учётной записью
  • Включите бэкап, отметьте альбомы для выгрузки
  • Оставьте телефон на зарядке в Wi-Fi, пока первая загрузка не закончится
  • Проверьте счётчик оставшихся файлов в разделе бэкапа

Индексация существующего архива на диске

Если фото уже разложены по папкам на NAS, не копируйте их в медиатеку. Примонтируйте каталог в docker-compose.yml и добавьте как внешнюю библиотеку в Administration, External Libraries: сервер проиндексирует файлы, не трогая их на месте.

Что важно знать заранее:

  • Монтируйте каталоги с флагом:ro — иначе Immich сможет удалить исходники из веб-интерфейса.
  • Путь в настройках библиотеки — тот, который видит контейнер, а не хост.
  • Библиотека привязана к одному пользователю, сменить владельца после создания нельзя.
  • Шаблоны исключений отсекают лишнее: /Raw/ для raw-кадров, /@eaDir/ для служебных папок Synology.
  • Метаданные, добавленные в Immich (альбомы, описания), хранятся в базе, не в файлах — при перемещении файла они теряются.
  • Файл, удалённый с диска, при пересканировании попадает в корзину и исчезает через 30 дней.
  • Автослежение за файловой системой — экспериментальная функция, на сетевых дисках не работает. Рассчитывайте на ночное пересканирование.
  • Просмотр по папкам включается отдельно: Account Settings, Features, Folders.

Совместный доступ

Общие альбомы — для разовых событий. Партнёрский доступ — для постоянного обмена между членами семьи. Каждый пользователь получает изолированную библиотеку на общем сервере.

Обновление

Зафиксируйте версию в IMMICH_VERSION, изучайте примечания к каждому релизу и обновляйте контейнеры после создания свежего дампа базы. Темп разработки высокий, ломающие изменения встречаются.

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

С версии 2.5.0 Immich снимает дампы базы самостоятельно: они лежат в UPLOAD_LOCATION/backups, по дефолту создаются каждую ночь в 2:00, хранятся последние 14. Расписание и срок хранения меняются в Administration, Settings, Backup. Разовый дамп запускается через Administration, Job Queues, Create job, Create Database Dump.

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

Что копировать

ПапкаКритичностьСодержание
UPLOAD_LOCATION/upload
Обязательно
Оригиналы из браузера, приложения и CLI
UPLOAD_LOCATION/library
Обязательно
Оригиналы при включённом storage template
UPLOAD_LOCATION/profile
Обязательно
Аватары пользователей
UPLOAD_LOCATION/backups
Обязательно
Автоматические дампы базы
thumbs, encoded-video
Желательно
Превью и транскоды. Пересоздаются задачами, но на большом архиве — часы

Порядок снятия копии

Идеальный вариант — остановить immich-server на время бэкапа: база и файлы гарантированно согласованы. Если остановка недопустима — сначала дамп базы, потом файлы. Худший сценарий: на диске окажутся файлы, которых нет в дампе, — их можно дозалить вручную. Обратный порядок даёт битые ассеты: база ссылается на то, чего нет в копии.

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

Стандартный путь — через веб-интерфейс: Administration, Maintenance, Restore database backup. Выбираете дамп из списка или грузите.sql.gz. Перед операцией Immich создаёт точку отката и при неудаче откатывается обратно. На чистой установке та же функция доступна на экране приветствия, кнопка Restore from backup — предварительно верните папки данных в новый UPLOAD_LOCATION.

Ручное восстановление через psql требует, чтобы сервер ни разу не запускался, или переменной DB_SKIP_MIGRATIONS=true. Дампы старше версии 2.5.0 восстанавливаются по инструкции для соответствующей версии.

Проверка результата

Что проверитьКак
Контейнеры живы
docker compose ps — все сервисы running или healthy
Очереди обработки
Страница задач: миниатюры, метаданные, Smart Search дошли до нуля
Машинное обучение
Логи ML-контейнера чисты, лица сгруппированы, запрос по смыслу выдаёт релевантные кадры
Мобильный бэкап
Счётчик несинхронизированных файлов — ноль, новые снимки появляются в таймлайне
Восстановление
Дамп и копия файлов разворачиваются на чистой инсталляции, где сервер не запускался

Важно: копирование DB_DATA_LOCATION на работающем сервере — не бэкап. Рабочая копия — дамп из UPLOAD_LOCATION/backups плюс файлы медиатеки.

Поднять фототеку у себя — задача на вечер. Эксплуатация — это дисциплина: база на локальном SSD, версия закреплена, дамп и файлы копируются вместе, восстановление проверено. Без этого open-source не спасает.

Ограничения

Технические границы, которые определяют, где Immich стабилен, а где — нет.

ПунктПояснение

Postgres только на локальном диске — Сетевое хранилище, NTFS, exFAT, монтирование из /mnt в WSL — испортят базу.

В Windows и WSL переходите на именованный том: DB_DATA_LOCATION=pgdata, запись pgdata: в секции volumes. База растёт с библиотекой, обычно 1–3 ГБ.

Аппаратное ускорение не везде — GPU-транскодинг — только Linux и Windows через WSL2.

Quick Sync в WSL2 недоступен, Raspberry Pi не поддерживается. По умолчанию ускоряется кодирование; декодирование включается отдельно.

Первичная индексация долгая — Миниатюры, лица и векторы для большого архива считаются часами.

Ботleneck — процессор и выбранная CLIP-модель: тяжёлая модель на слабом железе затягивает очереди на дни.

Ломающие изменения в релизах — Темп разработки высокий.

Обновление может поменять структуру базы или формат конфигурации. Фиксируйте IMMICH_VERSION и читайте релиз-перед обновлением.

Дамп без файлов бесполезен — В дампе — метаданные и пути, не фотографии.

Бэкап — дамп плюс копия файлов из UPLOAD_LOCATION. Копирование DB_DATA_LOCATION на работающем сервере бэкапом не является.

Docker в LXC не рекомендуется — Разработчики предупреждают: Docker в LXC может работать, но поддержки нет.

Для amd64 последняя версия с x86-64-v1 — v2.7.5, и она не поддерживается.

Антипаттерны

Неверные ходы, которые ведут к потере данных или нестабильности.

ПунктПояснение

Удалить оригиналы сразу после загрузки — Проект прямо предупреждает: не используйте Immich как единственное хранилище.

Дождитесь проверенного восстановления и держите вторую копию по правилу 3-2-1.

База на сетевом диске — Повреждение данных и падения.

Только локальный SSD или именованный том Docker.

Тег latest вместо версии — Обновление приезжает без вашего ведома и может сломать совместимость.

Зафиксируйте конкретную версию в IMMICH_VERSION.

Сервер открыт в интернет — Личный архив на неподготовленном хосте — мишень.

Закройте доступ через VPN или обратный прокси с HTTPS и аутентификацией.

Пароль базы из примера — Дефолтный пароль известен всем.

Смените DB_PASSWORD до первого запуска.

Тяжёлая CLIP-модель на слабом железе — Очереди не заканчиваются, поиск тормозит.

Выберите модель поменьше, сверьтесь с таблицами памяти и времени в документации.

Чеклист

Что проверить, прежде чем считать развёртывание готовым.

ПунктПояснение

Хост готов — RAM от 6 ГБ, CPU от 2 ядер, amd64 или arm64.

Для amd64 — x86-64-v2+. Диск под медиатеку с запасом 10–20% под превью и транскоды.

Docker установлен — Docker Engine с плагином Compose (docker compose, не docker-compose).

Engine 25+.

Переменные заполнены — UPLOAD_LOCATION, DB_DATA_LOCATION, TZ, IMMICH_VERSION, DB_PASSWORD.

Пароль сменён, версия зафиксирована.

Сервер отвечает на 2283 — Администратор создан, веб-интерфейс открыт.

docker compose ps — сервисы running или healthy.

Storage template настроен заранее — Шаблон хранения задан до массовой загрузки.

Смена на готовой библиотеке запускает долгую миграцию.

Переиндексация запущена после смены.

Внешние библиотеки с:ro — Архив на диске подключён с флагом:ro и exclusion patterns.

Путь указан так, как его видит контейнер.

Бэкап настроен — Расписание дампов проверено.

Папки upload, library, profile, backups копируются вне сервера. Восстановление протестировано на чистой установке.

Доступ извне закрыт — Сервер не торчит в интернет напрямую.

VPN или прокси с HTTPS.

Ссылки

Продолжить тему

Материалы, которые связаны с этим разбором

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

Открыть материалы по теме ↗

Обсудить задачу

Есть задача, которую хотите усилить с помощью ИИ?

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

Для первого сообщения достаточно пары абзацев — готовое техническое задание не требуется.