DevOps и Docker 16 мин чтения 2026-10-09

Приватная замена Google Photos: развертывание Immich v3 на VDS в Docker Compose, тюнинг под 6 ГБ RAM и бэкапы библиотеки

Практическое руководство по развертыванию Immich v3.3.1 на VDS в Docker Compose: подбор сервера под требования к RAM и микроархитектуре x86-64-v2, лимиты ресурсов контейнеров, HTTPS через Caddy или Nginx, автоматические дампы Postgres и шифрованные копии библиотеки в S3.

Алексей Иванов Проверено инженерами SysKit.ru

Личный фотоархив растёт быстрее любого сервера: за пять-семь лет семейной съёмки легко набегает 200–500 ГБ оригиналов, а вместе с ними — вопросы о том, где эти файлы хранятся, кто имеет к ним доступ и что будет, если облачный аккаунт заблокируют или тариф пересчитают. Именно на этой боли вырос Immich — открытая платформа для хранения и управления фото- и видеотекой, которую официальный репозиторий описывает как «high performance self-hosted photo and video management solution» под лицензией AGPL-3.0.

Масштаб доверия к проекту измеряется не маркетингом, а цифрами: на 9 октября 2026 года у репозитория 115 792 звезды и 7 152 форка, а актуальный стабильный релиз — Immich v3.3.1, опубликованный 8 октября 2026 года (без статуса pre-release). За сутки до написания статьи вышли исправления для совместного доступа к людям на фото и прокрутки на мобильных устройствах, а также новый индикатор, показывающий, с кем поделён тот или иной человек из распознанных.

Ниже — практический разбор развертывания Immich v3 на виртуальном сервере: не «нажмите docker compose up», а инженерная работа с требованиями к железу, лимитами контейнеров, реверс-прокси и резервным копированием библиотеки. Отдельно разберём два сбоя, на которые чаще всего натыкаются администраторы: Illegal instruction из-за микроархитектуры процессора и OOM Killer, убивающий Postgres.

1. Что даёт Immich v3 и кому он действительно нужен

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

Из коробки платформа закрывает четыре группы задач:

  • Хранение и синхронизация: оригиналы фото и видео, автобэкап с Android и iOS, догрузка существующей библиотеки, внешние библиотеки (External Libraries) для уже разложенных по папкам архивов.
  • Организация: таймлайн, альбомы, избранное, архивы, хранилище-шаблоны имён файлов (Storage Template) с миграцией уже загруженных ассетов.
  • Поиск на базе машинного обучения: умный поиск по содержимому кадра, распознавание и группировка лиц, OCR-распознавание текста на снимках. Все эти модели живут в отдельном контейнере immich-machine-learning.
  • Совместное использование: несколько учётных записей, партнёрский доступ, публичные ссылки на альбомы, а с версии v3.3.1 — явный индикатор того, с кем именно поделён распознанный человек.

⚠️ Важное предупреждение: три официальных ограничения

Первое: Immich не поддерживает работу на подпути вида example.com/immich — сервис обязан обслуживаться в корне домена или поддомена. Второе: официальная документация не рекомендует запускать Docker внутри LXC-контейнеров (OpenVZ/LXC-виртуализация) — нужна полноценная KVM-машина. Третье: сервер Immich совместим только с совпадающей мажорной версией мобильного приложения, поэтому клиенты обновляют раньше сервера.

Отдельно стоит понять экономику решения. Вы не платите за место в чужом облаке, но платите за диск, память и трафик на своём сервере. Прикидка простая: библиотека оригиналов плюс 10–20 % сверху на превью и транскоды — это официальная цифра из документации Immich, а не оценка «на глаз». К этому добавляется база данных Postgres размером 1–3 ГБ и автоматические дампы.

💡 Совет инженера

Перед арендой VDS посчитайте не «сколько фото», а сколько места займёт вся система: оригиналы + 10–20 % на превью и перекодированное видео + 1–3 ГБ на Postgres + место под 14 автоматических дампов базы (значение по умолчанию). На диске 40 ГБ библиотека на 200 ГБ не поместится, и это выяснится ровно на середине первой загрузки.

Если сейчас документы у вас живут отдельно от фотографий, посмотрите на смежный разбор — электронный архив документов на Paperless-ngx в Docker Compose: связка «Immich для медиа + Paperless-ngx для сканов» закрывает домашний архив целиком, а настраиваются оба сервиса по одной и той же логике.

2. Требования Immich v3 и подбор VDS: RAM, ядра, x86-64-v2 и диск

Самая частая ошибка при развертывании — арендовать сервер «как под обычный сайт», на 1–2 ГБ памяти. Immich — не сайт: внутрь входят четыре контейнера (сервер, машина машинного обучения, Postgres, Redis/Valkey), и каждый требует своей доли ресурсов. Ниже — официальные требования из документации Immich, обновлённой 8 октября 2026 года.

Ресурс Минимум Рекомендуется Комментарий
RAM 6 ГБ 8 ГБ На 4 ГБ запуск возможен только с отключёнными функциями машинного обучения
CPU 2 ядра 4 ядра Индексация и распознавание лиц упираются в ядра, а не в диск
Архитектура amd64 или arm64 x86-64-v2 Начиная с v3 контейнер ML на amd64 требует микроархитектуру не ниже x86-64-v2
ОС Linux 64-bit Ubuntu / Debian LTS Полноценная KVM-машина: Docker в LXC официально не рекомендован
Диск под БД локальный SSD локальный NVMe Файлы Postgres занимают 1–3 ГБ; сетевые хранилища не поддерживаются
ПО Docker + Compose v2 Docker Engine 25+ Команда — только docker compose; устаревший docker-compose v1 не поддерживается

Ключевое уточнение по памяти, которое легко пропустить: если вы ограничиваете контейнеры через лимиты Docker, базе данных требуется минимум 2 ГБ RAM — это прямое требование документации. То есть на сервере с 4 ГБ памяти под сам сервер Immich, ML-контейнер и операционную систему остаётся около двух гигабайт, и любой всплеск индексации приводит к срабатыванию OOM Killer. Восемь гигабайт — не «жирно», а рабочий минимум для библиотеки в сотни гигабайт.

Проверка x86-64-v2 до покупки сервера

Уровень x86-64-v2 требует от процессора набора инструкций, который появился в массовых CPU примерно с 2012 года. Если виртуальная машина отдаёт «урезанный» тип процессора, контейнер машинного обучения падает с ошибкой Illegal instruction, а последней версией Immich, работавшей на x86-64-v1, официально остаётся v2.7.5 — и она больше не поддерживается.

Проверить свой сервер можно без установки чего-либо, по флагам процессора:

# x86-64-v2 требует CMPXCHG16B (cx16), POPCNT и SSE4.2
for flag in cx16 popcnt sse4_2; do
  if grep -qw "$flag" /proc/cpuinfo; then
    echo "OK: $flag"
  else
    echo "НЕТ: $flag — процессор не поддерживает x86-64-v2"
  fi
done

Если хотя бы одного флага нет — Immich v3 на этом сервере не запустится. Решается либо сменой типа процессора в панели провайдера (KVM позволяет выставить режим с полным набором инструкций хоста), либо переходом на другую площадку. Проверить железо арендованного сервера целиком помогает lscpu, а доступность внешних портов и IP — утилиты определения IP-адреса и онлайн-сканера портов.

Сколько места занять: расчёт на реальной библиотеке

Возьмём типичный сценарий — 200 ГБ оригиналов фото и видео. Прибавляем 10–20 % на превью и перекодированные видео, получаем 220–240 ГБ, плюс база Postgres на 1–3 ГБ, плюс автоматические дампы. Итого под систему нужен диск от 300 ГБ, причём под базу данных — обязательно локальный SSD/NVMe.

Что размещаем Объём Где хранить
Оригиналы 200 ГБ UPLOAD_LOCATION/upload
Превью и транскоды +10–20 % (~30 ГБ) UPLOAD_LOCATION/thumbs, encoded-video
База Postgres 1–3 ГБ DB_DATA_LOCATION — только локальный SSD
Автодампы БД до 14 копий UPLOAD_LOCATION/backups

💡 Совет инженера

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

Хостинг для такой задачи выбирают по трём критериям: KVM-виртуализация, поддержка x86-64-v2 и NVMe-накопители. Как сравнивать тарифы и на что смотреть в описании провайдера, разобрано в материале как выбрать надёжный VDS для сайта в 2026 году, а проверить площадку по внешним признакам можно через проверку хостинга.

3. Подготовка Ubuntu 24.04 LTS: Docker Engine, отдельный диск, Swap и UFW

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

# Обновляем систему и индекс пакетов
sudo apt update && sudo apt upgrade -y

Установка Docker Engine из официального репозитория

Это не формальность. В документации Immich отдельно предупреждают: если использовать пакет docker.io из репозитория Ubuntu, команда запуска падает с ошибками вида unknown shorthand flag: 'd' in -d или open .env: permission denied — под этим именем поставляется старый Docker без актуального плагина Compose. Ставим Docker из официального репозитория разработчика, причём в актуальном формате подключения репозитория DEB822.

# 1. Официальный GPG-ключ Docker и базовые утилиты
sudo apt update
sudo apt install -y ca-certificates curl gnupg wget htop
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# 2. Подключение репозитория: создаём файл в актуальном формате DEB822
sudo nano /etc/apt/sources.list.d/docker.sources

Содержимое файла /etc/apt/sources.list.d/docker.sources для Ubuntu 24.04 LTS на архитектуре amd64:

Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc

💡 Совет инженера

Два поля стоит подставить под свою систему, а не копировать вслепую: Suites — кодовое имя дистрибутива (получить его можно командой . /etc/os-release && echo "$VERSION_CODENAME", для 24.04 LTS это noble) и Architectures — архитектура процессора (dpkg --print-architecture, обычно amd64). Раньше репозиторий подключали одной строкой с deb [...] в файле docker.list; формат DEB822, показанный выше, — текущий официальный способ.

# 3. Установка Engine, containerd и плагинов Compose/Buildx
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 4. Проверка версий
docker --version
docker compose version

Версия docker compose должна быть второго поколения (плагин, вызывается через пробел), а Engine — не ниже 25: официальный docker-compose.yml использует параметр start_interval в healthcheck базы, и на более старых движках запуск завершится ошибкой can't set healthcheck.start_interval as feature require Docker Engine v25 or later.

⚠️ Важное предупреждение: группа docker равна root

Добавление пользователя в группу docker даёт ему фактически права суперпользователя: через Docker можно смонтировать корневую файловую систему хоста внутрь контейнера. Если добавляете себя в группу — применяйте изменение через newgrp docker (или перелогиньтесь) и осознавайте уровень доступа. Для боевого сервера с фотоархивом разумнее выполнять команды через sudo docker compose, не расширяя права учётной записи.

Разметка дисков: библиотека отдельно, база отдельно

Определяем, какие устройства доступны, и монтируем дополнительный диск под библиотеку. База данных останется на системном NVMe — это прямое требование документации Immich: сетевые хранилища и медленные диски под DB_DATA_LOCATION не поддерживаются.

# Смотрим блочные устройства и файловые системы
lsblk -f

# Разметка дополнительного диска (пример: /dev/vdb) и его UUID
sudo mkfs.ext4 -L immich-data /dev/vdb
sudo blkid /dev/vdb

# Точки монтирования: 750 — владелец пишет, остальные не читают
sudo install -d -m 750 /mnt/immich-data
sudo install -d -m 750 /var/lib/immich

Далее добавляем запись в /etc/fstab, подставив собственный UUID из вывода blkid, и проверяем монтирование без перезагрузки:

# /etc/fstab — монтирование по UUID (подставьте свой идентификатор)
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /mnt/immich-data ext4 defaults,noatime 0 2

# Применяем без перезагрузки и проверяем результат
sudo systemctl daemon-reload
sudo mount -a
df -h /mnt/immich-data

💡 Совет инженера

Опция noatime в fstab отключает запись времени последнего доступа к файлам. Для фототеки, которую читают редко, а пишут постоянно, это заметно снижает лишние операции записи на диск и продлевает жизнь SSD.

Swap: страховка от OOM Killer

Immich — многоконтейнерное приложение, и пик потребления даёт не сервер, а индексация: генерация превью, умный поиск, распознавание лиц. При 8 ГБ памяти Swap нужен как амортизатор, а не как «дополнительная память». Создаём файл подкачки 4 ГБ с правами 600:

# Создание и активация Swap-файла на 4 ГБ
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Автозагрузка и умеренная агрессивность вытеснения
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system

# Проверка
swapon --show
free -h

Почему vm.swappiness=10, а не 60 по умолчанию: при агрессивном вытеснении ядро отправляет в Swap активно используемые страницы Postgres, и база начинает «тормозить» на ровном месте. Как правильно считать размер подкачки и когда вместо файла стоит использовать zRAM, подробно разобрано в статье правильная настройка Swap и zRAM на VDS.

Фаервол и ловушка Docker с обходом UFW

# Запрещаем входящие по умолчанию, оставляем только SSH до включения
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw enable
sudo ufw status verbose

⚠️ Важное предупреждение: UFW не защищает порты Docker

Docker управляет правилами iptables напрямую и вставляет свои цепочки раньше фильтров UFW. Порт, опубликованный в compose как 2283:2283, окажется доступен из интернета, даже если ufw status показывает запрет входящих. Именно поэтому в следующем разделе мы публикуем порт Immich только на локальном интерфейсе 127.0.0.1. Механика обхода и способы защиты разобраны в статье Docker обходит UFW на Linux.

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

4. Развертывание Immich v3.3.1: манифест Docker Compose, .env и лимиты ресурсов

Работаем в каталоге /opt/immich. Первый шаг — скачать официальные файлы именно той версии, которую мы фиксируем, а не «последнюю с ветки main»: документация Immich прямо предупреждает, что compose-файл из основной ветки может быть несовместим с текущим релизом.

sudo install -d -m 750 /opt/immich
cd /opt/immich

# Официальный манифест и шаблон переменных окружения для конкретного релиза
sudo wget -O docker-compose.yml https://github.com/immich-app/immich/releases/download/v3.3.1/docker-compose.yml
sudo wget -O .env https://github.com/immich-app/immich/releases/download/v3.3.1/example.env

Заполняем .env: пути, версия и пароль базы

Переменные UPLOAD_LOCATION и DB_DATA_LOCATION читает не сам контейнер, а Docker Compose при подстановке томов. Пароль базы генерируем криптостойко и без спецсимволов: документация Immich допускает в DB_PASSWORD только символы A–Z, a–z и 0–9, иначе Docker может некорректно разобрать значение.

# Криптостойкий пароль без спецсимволов (только hex-символы)
openssl rand -hex 32
# /opt/immich/.env
# Каталог с оригиналами, превью и дампами — на отдельном диске
UPLOAD_LOCATION=/mnt/immich-data/library

# Каталог базы Postgres — на локальном NVMe системного диска
DB_DATA_LOCATION=/var/lib/immich/postgres

# Часовой пояс: используется exiftool как fallback и для планировщика дампов
TZ=Europe/Moscow

# Фиксируем точную версию вместо метатега v3 — предсказуемые обновления
IMMICH_VERSION=v3.3.1

# Пароль базы: подставьте результат openssl rand -hex 32
DB_PASSWORD=ВСТАВЬТЕ_СГЕНЕРИРОВАННЫЙ_КЛЮЧ

# Значения ниже менять не требуется
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Production-манифест: закрываем порт и ограничиваем ресурсы

Ниже — официальный манифест версии v3.3.1 с двумя осознанными изменениями. Первое: порт публикуется только на 127.0.0.1, чтобы обойти правило iptables, которое Docker добавляет в обход UFW. Второе: каждому сервису заданы лимиты mem_limit и cpus — это сервисные ключи Compose: mem_limit ограничивает объём памяти контейнера (строка вида 2g), а cpus задаёт число выделяемых ядер и допускает дробные значения. Секция deploy в спецификации Compose помечена как опциональная и реализуется не всеми инструментами, поэтому для предсказуемого результата мы используем именно ключи уровня сервиса. Ограничение для базы в 2 ГБ — не произвольная цифра, а официальное требование Immich при использовании лимитов Docker.

# /opt/immich/docker-compose.yml
name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      # Было '2283:2283' — публикация на 0.0.0.0 в обход UFW.
      # Теперь порт слушает только loopback, наружу его отдаёт реверс-прокси.
      - '127.0.0.1:2283:2283'
    depends_on:
      - redis
      - database
    restart: always
    mem_limit: 2g
    cpus: 2
    healthcheck:
      disable: false

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
    mem_limit: 2g
    cpus: 2
    healthcheck:
      disable: false

  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:9@sha256:c123e3715db63d06d4ad6964884037aa0d5d4d703939b9929954112889708e1d
    healthcheck:
      test: redis-cli ping | grep -q PONG || exit 1
    restart: always
    mem_limit: 256m
    cpus: 1

  database:
    container_name: immich_postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_INITDB_ARGS: '--data-checksums'
      # База на SSD (значение по умолчанию); для HDD раскомментируйте строку ниже
      DB_STORAGE_TYPE: 'SSD'
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    shm_size: 128mb
    restart: always
    mem_limit: 2g
    cpus: 2
    healthcheck:
      disable: false

volumes:
  model-cache:

💡 Совет инженера

Образы базы и кэша в официальном манифесте закреплены по digest (@sha256:...), а не по плавающему тегу. Это защита от ситуации, когда пересборка контейнеров внезапно подтягивает другую версию СУБД. Сохраняйте эту практику: digest меняйте только осознанно, вместе с чтением release notes.

Проверяем конфигурацию и запускаем стек. Отдельно обратите внимание на итоговые лимиты: 2 ГБ серверу, 2 ГБ ML-контейнеру, 2 ГБ базе и 256 МБ кэшу — это 6,25 ГБ, что оставляет операционной системе на 8-гигабайтном сервере необходимый запас. Механику расчёта лимитов и защиту от каскадных падений контейнеров разбирает материал лимиты памяти и CPU в Docker Compose.

cd /opt/immich

# Проверка синтаксиса без запуска
sudo docker compose config --quiet

# Загрузка образов и старт в фоне
sudo docker compose pull
sudo docker compose up -d

# Статус контейнеров: healthcheck покажет состояние каждого сервиса
sudo docker compose ps

# Логи сервера на предмет ошибок миграций и ML
sudo docker compose logs --tail=100 immich-server

Первый вход: регистрация администратора

Порт закрыт снаружи, поэтому в веб-интерфейс заходим через SSH-туннель с рабочей машины — этот же приём пригодится, пока не настроен реверс-прокси с HTTPS:

# На локальной машине: пробрасываем порт 2283 на сервер
ssh -L 2283:127.0.0.1:2283 sysadmin@IP_ВАШЕГО_СЕРВЕРА

Теперь открываем http://localhost:2283 и нажимаем «Getting Started»: первый зарегистрированный пользователь автоматически становится администратором и получает право создавать другие учётные записи. Сразу после регистрации имеет смысл задать шаблон хранения файлов (Storage Template) — по умолчанию это Year/Year-Month-Day/Filename.Extension, и включение шаблона до массовой загрузки избавит от последующей миграции десятков тысяч файлов.

⚠️ Важное предупреждение: не трогайте файлы в библиотеке вручную

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

Если сервер Immich получает некорректный IP клиента в логах и на страницах статистики, в .env добавьте переменную IMMICH_TRUSTED_PROXIES со списком IP доверенных прокси через запятую. Учтите официальное предупреждение: изменение переменных окружения не применяется простым рестартом — контейнеры нужно пересоздать командой sudo docker compose up -d --force-recreate.

5. Reverse proxy и HTTPS: Caddy, Nginx и доступ только через VPN

Immich не умеет сам выпускать TLS-сертификаты, и это осознанное архитектурное решение: шифрованием занимается прокси перед ним. Документация формулирует требования к любому прокси однозначно — он обязан пробрасывать заголовки Host, X-Real-IP, X-Forwarded-Proto и X-Forwarded-For, а также разрешать загрузку крупных файлов. Иначе мобильное приложение будет отваливаться, а в интерфейсе появятся «серые» превью.

Вариант 1: Caddy с автоматическим выпуском сертификата

Самый короткий путь. Caddy сам получает и продлевает сертификаты Let's Encrypt, поэтому конфигурация сводится к трём строкам. Прокси ставим на хост и направляем на закрытый порт 127.0.0.1:2283:

# /etc/caddy/Caddyfile
photos.example.com {
    reverse_proxy 127.0.0.1:2283
}
# Проверка конфигурации и перезагрузка
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager

Caddy автоматически проксирует WebSocket-соединения (они нужны интерфейсу для живых обновлений) и не требует ручной настройки лимитов на размер тела запроса. Подробный разбор этого веб-сервера, включая HTTP/3 и работу с Docker, есть в отдельном руководстве — Caddy 2 вместо Nginx с автоматическим SSL.

Вариант 2: Nginx по официальному примеру

Nginx даёт больше контроля, но требует явно назвать таймауты и лимиты. Значения ниже взяты из официальной документации Immich: буферизация загрузок отключена, чтобы прокси не съедал память и не тормозил выгрузку, а тело запроса разрешено до 50000 МБ — иначе видео с телефона не загрузится.

server {
    listen 80;
    listen [::]:80;
    server_name photos.example.com;

    # Крупные загрузки: лимит и буферизация по официальной рекомендации
    client_max_body_size 50000M;
    proxy_request_buffering off;
    client_body_buffer_size 1024k;

    # Заголовки, обязательные для корректной работы Immich
    proxy_set_header Host              $host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # WebSocket и длительные загрузки видео
    proxy_http_version 1.1;
    proxy_redirect     off;
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
    send_timeout       600s;

    location / {
        proxy_pass http://127.0.0.1:2283;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

⚠️ Важное предупреждение: порядок выпуска сертификата

Не вписывайте пути к сертификату в конфигурацию вручную до его выпуска — тест конфигурации упадёт, потому что файлов ещё не существует. Правильный порядок: сначала создайте блок только на порту 80, проверьте его командой sudo nginx -t, затем выполните sudo certbot --nginx --redirect -d photos.example.com. Certbot сам добавит в конфиг директивы ssl_certificate с путями к выпущенным файлам и настроит перенаправление с HTTP на HTTPS: для команд run и install редирект включается по умолчанию, а флаг --redirect фиксирует его явно и не даёт настройке потеряться при последующих правках.

# 1. Проверяем блок только с HTTP
sudo nginx -t

# 2. Выпускаем сертификат и включаем редирект на HTTPS
sudo certbot --nginx --redirect -d photos.example.com

# 3. Повторная проверка конфигурации после правок Certbot
sudo nginx -t && sudo systemctl reload nginx

Перед выпуском сертификата убедитесь, что A-запись домена указывает на IP сервера и уже разошлась по резолверам — иначе Let's Encrypt не сможет пройти проверку. Проверить актуальные значения DNS удобно через DNS lookup онлайн, а итоговую цепочку сертификата и срок его действия — через проверку SSL-сертификата.

Вариант 3: вообще не открывать веб-порты

Для приватного фотоархива логично не публиковать сервис в интернете совсем. В этом случае 80 и 443 остаются закрытыми, а доступ идёт через оверлейную сеть: клиент подключается к Immich по внутреннему адресу http://100.x.x.x:2283. Единственный нюанс — веб-интерфейс будет отдаваться по HTTP, и встроенная политика безопасности Immich попытается апгрейдить запросы до HTTPS. Документация описывает решение: собственный файл конфигурации helmet с отключённым правилом upgrade-insecure-requests и переменная IMMICH_HELMET_FILE с путём к нему.

Как поднять собственную оверлейную сеть на WireGuard-совместимом координаторе, разобрано в статье свой Tailscale на VDS: развертывание Headscale. Там же — про доступ к базам данных и админкам без проброса портов наружу.

💡 Совет инженера

Что бы вы ни выбрали, перед публикацией домена прогоните внешнее сканирование: порт 2283 не должен отвечать с интернета, а открытыми обязаны остаться только 80/443 (или ни одного, если используете VPN). Проверить это можно утилитой проверки портов онлайн — запрос выполняется с внешнего узла, а не с самого сервера.

Отдельно стоит помнить о каверзе с проверкой домена: если прокси использует http-01 challenge, путь /.well-known/immich должен корректно доходить до сервиса Immich, иначе мобильное приложение столкнётся с ошибками подключения. В конфигурации Nginx это отдельная локация, закомментированная в официальном примере.

Рекомендуемые VDS-провайдеры

Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с

Выбор редакции
⚡

Timeweb Cloud — Быстрые NVMe VDS

Высокочастотные ядра ускоряют индексацию библиотеки и работу моделей машинного обучения, а NVMe-накопители обеспечивают быстрый отклик базы Postgres.

Конфигурация
4 vCPU 3.3 ГГц • 8 ГБ RAM • 80 ГБ NVMe • Трафик без лимита
Премиум Tier III
🔷

Selectel — Корпоративная надежность Tier III

Гарантированные ресурсы vCPU и отказоустойчивая инфраструктура в дата-центрах Tier III — подходят для семейного архива, который должен быть доступен круглосуточно.

Конфигурация
4 vCPU • 8 ГБ RAM • 80 ГБ NVMe • Дата-центры Tier III
Идеально для Docker
🟠

Beget — Простота и отказоустойчивость

Развертывание Docker в один клик, удобный терминал и бесплатные автоматические бэкапы сервера — удобная стартовая площадка для первого self-hosted фотоархива.

Конфигурация
4 vCPU • 8 ГБ RAM • 80 ГБ NVMe • Бесплатные бэкапы

6. Обслуживание и обновления: версии, Illegal instruction и OOM Killer

Immich обновляется часто, и порядок действий здесь строго регламентирован разработчиками. Перед каждым обновлением нужно прочитать release notes и учесть breaking changes — отдельная ветка обсуждений в репозитории собирает именно такие релизы. Дальше обновление сводится к двум командам в каталоге с манифестом:

cd /opt/immich

# 1. Правим IMMICH_VERSION в .env на новую версию
sudo nano .env

# 2. Загружаем новые образы и перезапускаем сервисы
sudo docker compose pull && sudo docker compose up -d

# 3. Удаляем устаревшие образы, освобождая место
sudo docker image prune

Политика версий: почему откат невозможен

Проект следует семантическому версионированию, и это важно для планирования. Все breaking changes, включая изменения API и схемы развертывания, допускаются только в мажорных релизах. При этом сервер Immich совместим лишь с совпадающей мажорной версией мобильного приложения — поэтому клиенты на телефонах обновляют раньше сервера. Патчи в старые ветки не бэкпортируются, а понижение версии не поддерживается даже в пределах одной минорной ветки.

Практический вывод: не отключайте фиксацию версии ради метатега v3, если сервер обслуживает семейный архив. Метатег удобен, но принесёт мажорное обновление автоматически, и вы узнаете о breaking changes из упавшего сервиса, а не из release notes. Метатеги, кстати, не следуют за release-кандидатами — это официально оговорено.

⚠️ Важное предупреждение: перенос старой инсталляции

Если вы разворачиваете Immich поверх базы, созданной на старом образе tensorchord/pgvecto-rs, потребуется миграция на расширение VectorChord с образом ghcr.io/immich-app/postgres. После такой миграции понижение Immich ниже 1.133.0 запрещено, а резервные копии, снятые после перехода, восстанавливаются только образом, содержащим VectorChord. Свежая установка, описанная выше, этой проблемы лишена.

Ошибка Illegal instruction: микроархитектура процессора

Симптом обманчив: сервер Immich работает, а контейнер машинного обучения уходит в постоянный перезапуск, в логах — Illegal instruction. Причина не в образе, а в процессоре виртуальной машины: начиная с v3 ML-контейнер на amd64 требует уровня x86-64-v2.

# Что показывает виртуалка про свой процессор
lscpu | grep -E 'Model name|Flags' | head -n 2

# Проверяем три обязательных флага x86-64-v2
for flag in cx16 popcnt sse4_2; do
  grep -qw "$flag" /proc/cpuinfo && echo "OK: $flag" || echo "НЕТ: $flag"
done

# Ошибки контейнера машинного обучения
sudo docker compose logs --tail=50 immich-machine-learning

Если флагов нет — вариантов два. Первый: сменить тип процессора виртуальной машины в панели провайдера на режим с полным набором инструкций хоста (в KVM это штатная операция, но зависит от политики хостера). Второй: переехать на другую площадку. Оставаться на v2.7.5 не стоит — эта версия официально не поддерживается и не получает исправлений безопасности.

OOM Killer убивает Postgres: как распознать и что делать

Вторая частая авария — «сервер жив, а фото не открываются». Первым обычно погибает контейнер базы: ядро выбирает процесс-«обжору» по счёту badness, и Postgres с большим RSS становится удобной жертвой. Признаки видны сразу в системном журнале:

# Ищем факты срабатывания OOM Killer
sudo dmesg -T | grep -i -E 'oom|killed process'

# Кто сколько памяти занимает прямо сейчас
sudo docker stats --no-stream

# Историю перезапусков контейнеров
sudo docker compose ps

Дальнейшие действия — в порядке приоритета. Сначала убедитесь, что лимиты mem_limit заданы каждому сервису: без них один контейнер может выесть всю память сервера. Затем проверьте, что база действительно получила свои 2 ГБ — официальное требование при использовании лимитов Docker. И только после этого снижайте нагрузку от фоновых задач: тяжёлые очереди (генерация превью, умный поиск, распознавание лиц) можно запускать вручную и порциями из раздела Administration → Job Queues, а не позволять им идти сплошным потоком сразу после загрузки тысяч файлов.

💡 Совет инженера

Не диагностируйте нехватку памяти «на глаз» по free -h в момент спокойствия. OOM Killer срабатывает на пике — во время индексации библиотеки. Настройте внешний мониторинг с алертами в Telegram (например, по разбору легковесного мониторинга серверов и Docker в Beszel) и смотрите на график потребления в момент первой массовой загрузки фото.

Если сервер обслуживает сайт рядом с Immich, полезно заранее проверить, кто именно съедает диск и память: разбор типичных пожирателей места есть в статье закончилось место на диске VDS, а инструменты внешней проверки доступности и SSL-сроков собраны в материале про круглосуточный мониторинг доступности сайтов и сертификатов.

7. Бэкапы: официальный порядок, дампы Postgres и копия в S3

В отличие от документов и заметок, фотоархив нельзя «перегенерировать». При этом Immich устроен так, что база данных хранит пути к файлам и все метаданные: альбомы, лица, историю, пользователей. Из этого следуют два независимых объекта резервного копирования — база и файловое хранилище, и потеря любого из них делает архив нерабочим.

Что платформа делает сама

Immich автоматически создаёт дампы базы для аварийного восстановления: они лежат в UPLOAD_LOCATION/backups, а расписание и срок хранения настраиваются в Administration → Settings → Database Dump Settings. По умолчанию система хранит последние 14 копий и создаёт дамп ежедневно в 2:00. Ручной дамп можно инициировать из Administration → Job Queues, выбрав задачу создания дампа базы.

⚠️ Важное предупреждение: дамп базы — это не бэкап архива

Автоматические дампы содержат только метаданные и не включают фотографии и видео. Их обязательно нужно использовать вместе с копией файлов из UPLOAD_LOCATION. И наоборот: копия файлов без базы превращается в набор нечитаемых каталогов с хеш-именами.

Ручной дамп базы: команда из документации

Официальная команда снимает логический дамп через pg_dump внутри контейнера и сразу сжимает его. Пароль в аргументах не передаётся — соединение идёт по локальному сокету внутри контейнера базы, поэтому секрет не попадёт в историю команд или в вывод ps aux:

# Официальный вариант дампа.
# immich и postgres — значения по умолчанию для DB_DATABASE_NAME и DB_USERNAME:
# подставьте свои, если вы их меняли в .env
docker exec -t immich_postgres pg_dump --clean --if-exists \
  --dbname=immich --username=postgres | gzip > "/mnt/immich-data/manual-dumps/immich_$(date +%F).sql.gz"

Порядок копирования: сначала база, потом файлы

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

Критичными для восстановления являются три каталога: UPLOAD_LOCATION/library, UPLOAD_LOCATION/upload и UPLOAD_LOCATION/profile. Каталоги thumbs и encoded-video можно не копировать — но после восстановления придётся заново прогнать задачи генерации превью и транскодирования для всех ассетов.

Автоматизация: скрипт с отправкой в S3

Ниже — рабочий сценарий для cron или systemd-таймера. Он снимает дамп базы, затем отправляет и библиотеку, и дампы в S3-хранилище через Restic: инструмент шифрует данные на клиенте и дедуплицирует их, поэтому повторные копии фототеки занимают минимум места. Пароль репозитория и ключи доступа хранятся в файлах с правами 600, а не в командной строке.

# /etc/restic/immich.env — права 600, владелец root
# export AWS_ACCESS_KEY_ID="..."
# export AWS_SECRET_ACCESS_KEY="..."
# export RESTIC_REPOSITORY="s3:https://s3.storage.selcloud.ru/immich-backup"
# export RESTIC_PASSWORD_FILE="/etc/restic/immich.pass"
#!/usr/bin/env bash
# /usr/local/bin/immich-backup.sh — резервное копирование Immich
set -euo pipefail

UPLOAD_LOCATION="/mnt/immich-data/library"
DUMP_DIR="/mnt/immich-data/manual-dumps"
DB_NAME="immich"
DB_USER="postgres"
DUMP_RETENTION_DAYS=7

# Секреты и параметры репозитория Restic
source /etc/restic/immich.env

install -d -m 750 "$DUMP_DIR"
STAMP="$(date +%F_%H-%M)"

# Шаг 1: база данных — строго первой
docker exec -t immich_postgres pg_dump --clean --if-exists \
  --dbname="$DB_NAME" --username="$DB_USER" | gzip > "$DUMP_DIR/db_${STAMP}.sql.gz"

# Шаг 2: файловая часть и дампы уезжают в S3
# Для экономии места regenerable-каталоги можно исключить:
#   --exclude "$UPLOAD_LOCATION/thumbs" --exclude "$UPLOAD_LOCATION/encoded-video"
restic backup "$UPLOAD_LOCATION" "$DUMP_DIR" --tag immich

# Шаг 3: политика хранения — 7 дней, 4 недели, 3 месяца
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 3 --prune

# Шаг 4: локальная ротация дампов
find "$DUMP_DIR" -type f -name '*.sql.gz' -mtime +"$DUMP_RETENTION_DAYS" -delete

echo "Immich backup completed: $STAMP"
# Права на исполнение и запуск по расписанию (пример: ежедневно в 03:30)
sudo chmod 750 /usr/local/bin/immich-backup.sh
echo '30 3 * * * root /usr/local/bin/immich-backup.sh >> /var/log/immich-backup.log 2>&1' | sudo tee /etc/cron.d/immich-backup

Готовые шаблоны, которые пригодятся при развитии этой схемы: скрипт бэкапа PostgreSQL в S3 для отдельного сервера СУБД, конфигурация Rclone для S3 и облачных дисков — если удобнее синхронизировать каталоги, и скрипт умной ротации бэкапов с правилом «7 дней / 4 недели / 3 месяца». Общая логика шифрованных копий контейнеров разобрана в статье автоматические шифрованные бэкапы VDS и Docker на S3.

Восстановление: два пути и одна ловушка

Восстановление из веб-интерфейса — рекомендуемый способ: в Administration → Maintenance откройте раздел восстановления базы, выберите нужный дамп и подтвердите. Система сама создаст точку отката перед операцией, а при сбое вернётся к ней. Учтите: восстановление полностью заменяет текущую базу выбранной копией.

Восстановление из командной строки требует чистой установки: Immich не должен запускаться ни разу с момента создания контейнеров, иначе Postgres выдаст конфликты вида «relation already exists» или нарушение внешних ключей. Если сервер уже стартовал, каталог базы DB_DATA_LOCATION придётся очистить. В ряде сценариев помогает документированная переменная DB_SKIP_MIGRATIONS=true — она запрещает серверу запускать миграции, пока вы восстанавливаете базу, но после восстановления её нужно убрать и перезапустить сервисы.

💡 Совет инженера

Раз в квартал проверяйте не наличие бэкапа, а факт восстановления: разверните Immich на тестовой виртуалке, восстановите дамп и файлы, затем сверьте целостность хранилища на странице Administration → System Integrity. Для Restic полезна команда restic check --read-data-subset=5% — она выборочно перечитывает данные из репозитория и ловит повреждения, которые не видны при обычном restic snapshots.

8. Машинное обучение на CPU, тюнинг базы и безопасность периметра

Самый прожорливый сервис в Immich — контейнер машинного обучения. Он выполняет умный поиск по содержимому кадра, распознавание лиц и OCR-обработку текста на снимках. На обычном VDS графического ускорителя нет, поэтому все модели работают на CPU, и настройка сводится к аккуратному управлению потоками и временем жизни моделей в памяти.

Переменная По умолчанию Зачем менять
MACHINE_LEARNING_MODEL_TTL 300 с Время простоя до выгрузки модели из памяти; значение ≤ 0 отключает выгрузку
MACHINE_LEARNING_REQUEST_THREADS число ядер CPU Первое, что рекомендуют настраивать при подборе параллелизма
MACHINE_LEARNING_MODEL_INTER_OP_THREADS 1 Число параллельных операций модели
MACHINE_LEARNING_MODEL_INTRA_OP_THREADS 2 Потоки внутри одной операции
MACHINE_LEARNING_WORKERS 1 Каждый процесс дублирует модели в памяти — увеличивать не рекомендуется
MACHINE_LEARNING_MODEL_ARENA true Предварительный резерв памяти против фрагментации; на грани по RAM стоит отключить

Отдельная тонкость — предзагрузка моделей. Текстовая CLIP-модель обязательна для умного поиска, остальные подгружаются по мере обращения. Документация предупреждает: первые поиски могут быть медленными, потому что фоновые задачи вызывают загрузку дополнительных моделей в память и блокируют остальные запросы до завершения. Если памяти достаточно, модели можно предзагрузить переменными MACHINE_LEARNING_PRELOAD__CLIP__VISUAL, MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION__DETECTION и аналогичными; если памяти в обрез — наоборот, лучше не форсировать загрузку.

⚠️ Важное предупреждение: режим 4 ГБ и отключение ML

Официальная документация допускает работу Immich на 4 ГБ памяти, но только с отключёнными функциями машинного обучения. Практически это означает, что контейнер immich-machine-learning не запускается: загрузка и хранение фото, альбомы, мобильный бэкап и общий доступ работают, а умный поиск по содержимому, распознавание лиц и OCR — нет. Если вы уже поднимали ML-контейнер, разумный компромисс — уменьшить время жизни моделей через MACHINE_LEARNING_MODEL_TTL.

Аппаратное ускорение на VDS, как правило, недоступно: официальный манифест предлагает отдельные варианты образов и файлы hwaccel.transcoding.yml / hwaccel.ml.yml для NVIDIA (CUDA/NVENC), Intel QuickSync, VAAPI, ROCm и ARM-NN. Все они требуют проброса реального устройства в контейнер, чего на типовой виртуалке нет. Не тратьте время на попытки включить аппаратный транскодинг «на всякий случай» — на CPU-инстансе это не заработает.

База данных: что действительно нужно настраивать

С версии v3 официальный образ ghcr.io/immich-app/postgres уже содержит внутри себя healthcheck и дополнительный тюнинг — разработчики прямо пишут об этом в разделе обновлений. Поэтому не нужно вручную дописывать параметры Postgres в манифест: достаточно указать тип накопителя.

    environment:
      # SSD (значение по умолчанию) или HDD
      DB_STORAGE_TYPE: 'SSD'

Эта переменная выбирает один из двух профилей конфигурации — postgresql.ssd.conf или postgresql.hdd.conf, которые управляют в первую очередь параметром effective_io_concurrency. Для SSD выставляется конкурентный ввод-вывод, для HDD — последовательный. Практический вывод для VDS: держите базу на NVMe и оставляйте значение SSD; если база оказалась на сетевом диске или HDD, производительность просядет, а сетевые хранилища под DB_DATA_LOCATION официально не поддерживаются вовсе.

Если вы используете внешний, отдельный сервер Postgres (сценарий standalone), настройки нужно считать самостоятельно — готовые профили для 8 ГБ собраны в конфигураторе тюнинг PostgreSQL под 8 ГБ RAM. Подчеркну: для штатного docker-развёртывания Immich это не требуется, образ уже настроен.

Безопасность: четыре шага после установки

Первый шаг — закрыть регистрацию. Сразу после создания администратора задайте в .env переменную IMMICH_ALLOW_SETUP=false и пересоздайте контейнеры. Она отключает публичные эндпоинты /auth/admin-sign-up и /admin/database-backups/start-restore: никто со стороны не сможет создать учётную запись или запустить восстановление базы. Помните, что для восстановления из веб-интерфейса переменную придётся временно вернуть в true.

Второй шаг — вынести пароль базы из файла окружения. Immich поддерживает чтение секретов из файлов: переменные DB_PASSWORD_FILE и REDIS_PASSWORD_FILE, а также каталог CREDENTIALS_DIRECTORY для Docker Secrets и systemd-credentials. Это позволяет держать ключ в файле с правами 600 и не хранить его открытым текстом в .env.

Третий шаг — контроль периметра. Порт 2283 привязан к 127.0.0.1, наружу смотрят только 80/443, либо не смотрит ничего при доступе через оверлейную сеть. SSH-доступ закрывается по ключам, а от брутфорса ставятся Fail2ban или CrowdSec — методики разобраны в статьях про настройку Fail2ban на Ubuntu 24.04 и защиту VDS через CrowdSec в Docker Compose.

Четвёртый шаг — не «плыть» по версиям. Зафиксированная версия в IMMICH_VERSION и обновление только после чтения release notes — это не перфекционизм, а защита от ситуации, когда ночное автообновление приносит breaking change и сервер, обслуживающий семейный архив, не поднимается.

9. Чек-лист администратора и типичные ошибки

Собираем всё воедино. Ниже — восемь сбоев, которые встречаются чаще всего при развертывании Immich на виртуальном сервере, и способы их устранения.

Симптом Причина Решение
unknown shorthand flag: 'd' Установлен пакет docker.io из репозитория Ubuntu без актуального плагина Compose Переустановить Docker из официального репозитория разработчика
require Docker Engine v25 or later Слишком старый Docker Engine для параметра healthcheck Обновить Engine до 25+ либо убрать start_interval из манифеста
Illegal instruction в логах ML Процессор виртуальной машины ниже уровня x86-64-v2 Сменить тип процессора в панели провайдера или площадку
Postgres перезапускается, фото не открываются Сработал OOM Killer из-за отсутствия лимитов или нехватки RAM базе Задать mem_limit, выделить базе от 2 ГБ, добавить Swap
Мобильное приложение не подключается Сервис опубликован на подпути (/immich) или неверно проброшены заголовки прокси Публиковать в корне домена, пробрасывать X-Forwarded-*
После восстановления часть ассетов «битая» Копии базы и файлов снимались в неверном порядке или не полностью База — первой, файлы — второй; сверять состояние в System Integrity
Файлы на диске есть, в интерфейсе их нет Файлы скопированы в каталоги библиотеки вручную Загружать через интерфейс или подключать как External Library
Изменения в .env не применяются Переменные окружения читаются только при создании контейнера Пересоздать сервисы: docker compose up -d --force-recreate

📋 Чек-лист перед публикацией фотоархива

  • Сервер на KVM, от 8 ГБ RAM, процессор с поддержкой x86-64-v2, NVMe-диски.
  • Docker Engine 25+ и плагин Compose v2 установлены из официального репозитория.
  • UPLOAD_LOCATION — на отдельном диске, DB_DATA_LOCATION — на локальном NVMe.
  • Порт 2283 опубликован только на 127.0.0.1; наружу смотрят 80/443 либо ничего.
  • Каждому сервису заданы mem_limit и cpus, базе выделено не менее 2 ГБ.
  • Создан Swap 4 ГБ и задан vm.swappiness=10.
  • Версия зафиксирована в IMMICH_VERSION, обновления — только после чтения release notes.
  • Автоматические дампы базы включены, офсайт-копия снимается Restic, восстановление проверено.
  • После регистрации администратора установлено IMMICH_ALLOW_SETUP=false.
  • Проверены внешние порты и срок SSL-сертификата, настроены алерты мониторинга.

Immich v3 — редкий пример self-hosted проекта, который действительно закрывает потребительский сценарий, а не требует постоянного администрирования. Плата за это — дисциплина в трёх вещах: память (не меньше 6, лучше 8 ГБ), хранилище (база только на локальном SSD) и копии (дамп базы плюс файлы, с регулярной проверкой восстановления). Если эти три условия выполнены, сервер quietly работает годами, а фототека принадлежит вам, а не чужому аккаунту.

Для самопроверки после развертывания используйте бесплатные утилиты SysKit: сканирование портов подтвердит, что 2283 закрыт снаружи, проверка SSL покажет срок сертификата, DNS lookup — актуальность A-записи, а определение IP пригодится при настройке белых списков и VPN.

Разверните фотоархив на собственном сервере

Для Immich нужен сервер с 8 ГБ RAM, четырьмя ядрами и быстрым NVMe-диском — именно такой запас обеспечивает комфортную индексацию библиотеки и работу машинного обучения без OOM Killer.

Перейти и выбрать конфигурацию

Вопросы и ответы (FAQ)

Популярные вопросы вебмастеров и сисадминов по данной теме

Сколько оперативной памяти нужно для Immich на VDS?
Официальные требования Immich — минимум 6 ГБ RAM и 2 ядра, рекомендуемые значения — 8 ГБ и 4 ядра. На сервере с 4 ГБ запуск возможен только с отключёнными функциями машинного обучения, к тому же при использовании лимитов Docker базе данных требуется не менее 2 ГБ памяти. Для библиотеки в сотни гигабайт практический минимум — 8 ГБ RAM и локальный NVMe-диск под базу Postgres.
Контейнер машинного обучения падает с ошибкой Illegal instruction — что делать?
Начиная с Immich v3 контейнер машинного обучения на архитектуре amd64 требует микроархитектурный уровень x86-64-v2 (наборы инструкций CMPXCHG16B, POPCNT, SSE4.2). Проверьте флаги командой grep для cx16, popcnt и sse4_2 в /proc/cpuinfo: если хотя бы один отсутствует, виртуальная машина отдаёт урезанный тип процессора. Решение — сменить тип CPU в панели провайдера (KVM позволяет включить полный набор инструкций хоста) либо перейти на другую площадку. Последняя версия Immich, работавшая на x86-64-v1, — v2.7.5, и она больше не поддерживается.
Можно ли поставить Immich на VDS с 2–4 ГБ RAM?
На 2 ГБ развернуть актуальную версию Immich нельзя: только под базу данных при лимитах Docker требуется 2 ГБ, не считая сервера, ML-контейнера, Redis и операционной системы. На 4 ГБ запуск формально возможен, но лишь с отключённым контейнером машинного обучения, то есть без умного поиска по содержимому, распознавания лиц и OCR. При этом любой пик индексации будет приводить к срабатыванию OOM Killer.
Чем Immich отличается от Nextcloud Photos и PhotoPrism?
Immich изначально проектировался как сервис управления фото- и видеотекой, а не как файловое облако: у него мобильное приложение с автобэкапом, таймлайн, альбомы, партнёрский доступ и отдельный контейнер машинного обучения для умного поиска, распознавания лиц и OCR. Nextcloud — универсальная файловая платформа, где галерея лишь один из модулей, а PhotoPrism делает акцент на анализе и классификации снимков. Важное ограничение Immich: сервис не поддерживается на подпути вида example.com/immich — только корень домена или отдельный поддомен.

Читайте также в блоге SysKit

Смежные руководства и полезные технические статьи