Храним фотки у себя

Evgenii Burmakin, 26.06.2023

Один из пунктов в моём Todo на 2023-й год звучит (звучал) как “Перенести фотки от Гугла куда-то ещё”. Такое важное и почётное место эта задача заняла сразу по целой куче причин. Однако, прежде чем озвучить их, давайте поймём, с чем предстоит работать.

С чем работаем

Я люблю фоткать, много и часто, не как фотограф, а как обыватель, на айфон. “Много и часто” — это значит, что когда я делаю селфач с друзьями, это сразу 5-8 кадров, потому что обязательно кто-нибудь моргнёт, получится ленивый глаз, или ещё что-нибудь. Результат понятный: 200+ гигабайт фоток с 2009 года на одном только Google Photos, который пережимает исходные файлы, и ещё около 150 гигабайт на Яндекс Диске с 2018, понятно, что какой-то процент изображений просто дублируется между двумя сервисами.

Почему и зачем

  1. Я уже давно хочу постепенно уйти от жёсткой привязки к крупным провайдерам. Гугл любит убивать давно работающие сервисы, плюс время от времени всплывают истории о (вроде как) беспричинных банах многолетних юзеров, которые в один момент теряют доступ к почте, фоткам и всем прочим сервисам Гугла. Шансы попасть под раздачу невелики, но рисковать не хочется. Яндекс же — изначально российская компания, и если несколько лет назад это была одна из немногих компаний в РФ, которым я мог бы доверять, то сегодня это уже не так. А значит файлики нужно забирать. И держать где-то у себя.
  2. Мне нравится возиться с домашним сервером. Впервые я этим заморочился сполгода назад, и идея заморочиться с домашним хранилищем для фоток идеально вписывается в сценарий использования хоумлаба. Плюс маленькая прокачка всяких докеров и околосерверных скиллов.
  3. Облака — это дорого. Ну то есть как: 100гб хранилища в Google One (это Drive, почта, Photos и что-то там ещё всё вместе) стоят всего 20 евро в год, 200гб — 30 евро, а дальше уже только 2тб за 100 евро. Учитывая, что я вплотную подхожу к верхнему порогу 20-еврового тарифа, цена будет только расти. Не забываем и про (призрачные) риски выхватить случайный бан: на этот случай нам нужно ещё одно облако. В моём случае это Яндекс Диск, который тоже стоит отдельных денег и который по-прежнему остаётся компанией из РФ со всеми сопутствующими бонусами и рисками.
  4. Бесплатная иллюзия контроля. Размещая фотки у себя, я избавляюсь от рисков, связанных с облачными хостерами и принимаю на себя пачку других, о которых (и об их нивелировании) поговорим ниже. Однако, ощущение чуточку большего контроля над окружающим миром бесценно само по себе.

Хранилище фоток в идеальном мире

Что нам требуется? Опять по пунктам:

  1. Селф-хостед софт
  2. Веб морда с хорошим интерфейсом для просмотра фоток на десктопе
  3. Мобильное приложение (в первую очередь, для аплоада фоток)
  4. Многопользовательсковость (я не один, у меня жена)
  5. Возможность бэкапить файлы куда-то наружу (мы же не думаем, что держать все фотки в одном месте хоть сколь-нибудь безопасно?)
  6. Опционально: умение работать с live-фотками с айфона
  7. Опционально: Реверс геокодинг, чтобы видеть где какая фотка была сделана на карте
  8. Опционально: Лайкание фоток
  9. Опционально: Архивирование фоток (скрытие из основной ленты без удаления)
  10. Опционально: Альбомчики (для меня вообще не обязательный пункт)
  11. Опционально: Рюши вроде сторей в духе “Год назад вы фоткали вот ето”

Итак, если не облака, то что? Когда я впервые задался вопросом содержания домашнего сервера, из опенсорсных решений выделялся, разве что, PhotoPrism. Я поставил его, поигрался, позагружал туда фотки, удобно. Но — совершенно нет многопользовательсковости. Подразумевается, что пользователь всего один, семьи у него нет, а потому и разделение фоток по неймспейсам личных пространств не нужно. По крайней мере, в бесплатном community edition. В целом справедливо, но если я хочу перестать платить за облака, то эээ… Я и за селфхостед софт платить не хочу? Считайте меня жадным, это бесплатно. В общем, юзер менеджмент есть только в версии за 6 евро в месяц. Плюс, у них был какой-то скандал с их комьюнити не так давно, где кто-то как-то некрасиво поступил, но в это я уже не вникал. Фотопризм не вариант.

Дальше мне в r/selfhosted попался Immich. И как-то, кажется, это сразу было попадание в десяточку. Он удовлетворяет всем описанным в пунктах выше требованиях, а ещё умеет распознавать лица и машин лернинг (кажется, пока не очень умело), визуально очень похож на Google Photos (жирнейший плюс для меня), требует не миллион ресурсов на сервере и умеет в поиск по фоткам (очень криво-косо пока что, но и ладно). А, и запускается в Портейнере/Докере/Докер Компоузом/через чёрта лысого, что так же понижает порог входа. В общем, то, что нужно.

А, и ещё нужно, чтобы всё это бэкапилось куда-то наружу. Если вдруг пожар унесёт наш домашний сервер на серверные небеса, наши фотки будут в безопасности. Или там, если просто диск крякнет.

План

С основным инструментом определились, как работает и выглядит всё остальное?

Примерно так:

  • На сервере крутится докер
  • В докере запускается Immich
  • Крон-таска на сервере раз в N часов (дней, недель?) бэкапит БД Immich и сами фотки в облако
  • ???
  • Вы прекрасны!
  • А, и ещё неплохо бы дополнительно бэкапить всё на внешний жёсткий диск. Вдруг серверный диск крякнет.

Воплощение

На практике оказалось, что Immich сам по себе позиционируется как бэкап-тулза, да ещё и в стадии активной разработки (разработчики просят не использовать софтину как единственное средство хранения фоток, но кто их слушает, верно?). Это значит, что, на текущий момент, в Иммихе нет штатного инструмента, который позволял бы по расписанию делать бэкапы базы и файлов куда-нибудь в условный S3. Поэтому бэкапчики придётся костылить самостоятельно.

Что, собственно, не проблема. Друг-системщик подсказал мне утилиту для управления файликами rclone, а я сам нашёл хранилище Backblaze B2 с S3-совместимым апи и более низкими ценами на хранение файлов.

Из чего теперь состоит наш человек-швейцарский нож?

Внутрянка:

  • Связка Docker + Portainer, потому что никто не любит постоянно пердолиться с терминалом
  • Immich для непосредственного хранения и просмотра файлов
  • https://github.com/garzj/google-photos-migrate для приведения фоток в божеский вид после Google Photos (метаданные, теги и так далее)
  • Rclone для синхронизации локальной файлопомойки с бакетом в B2 и внешний HDD/SSD
  • Ansible для того, чтобы хранить весь колхоз в виде перезапускаемых ямлов
  • И всё это крутится на домашнем сервере под управлением Ubuntu, который построил Джек

Внешка:

  • Backblaze B2
  • Внешний HDD/SSD для периодического локального бэкапа данных

Вроде всё? Ну да.

В общем, вчера я выкачал все фотки с Яндекс Диска, сгрузил четыре пятидесятигигабайтных архива из Google Photos, поэкспериментировал с Rclone, убедившись, что он делает всё, что мне необходимо, и процесс пошёл. Для ясности, все описанные ниже шаги зафиксированы в Ансибле, потому что если сделать всё руками и что-то сломается, я скорее забью и навсегда разочаруюсь в идее, чем найду время и силы чинить.

На локальный сервер установил свежий пустой Immich, создал пользователя, апи-ключ для импорта фоток толпой.

После скачивания файлов с Яндекс Диска шаманить с их метаданными не пришлось, потому что они там хранились в исходном виде без пережатия. Загрузил их на сервер и сразу же натравил на них тулзу для импорта фоток в Immich. Иммихь, после поглощения скормленных ему фоток, принялся их переваривать, скрипя фоновыми джобами, которые отвечают за генерацию thumbnails, извлечение метаданных, тегирование объектов на фотках, фейс рекогнишен, и ещё там какие-то. Это происходит без моего участия.

Тем временем с Гугл Фотос выкачались 200гб фоток. Загрузил их на сервер, распаковал из архивов в одну директорию и натравил на них https://github.com/garzj/google-photos-migrate, потому что, как я говорил выше, Гугл пережёвывает фотки на свой лад, а метаданные складывает в одноимённые джейсоны. Эта тулза как раз засовывает их обратно. После того, как засунет, можно будет скормить импорт-тулзе, как и яндексовый архив.

Иммихь крутится, метадата мутится, а значит самое время наладить бэкапы наружу. Запустил ансибл-скрипт, который поставил на сервер Rclone и научил его с помощью крон тасков два раза в сутки брать нужные файлы и сихронизировать их в целевой бакет на B2. Rclone sync не аплоадит существующие файлы, а лишь поддерживает файловую структуру и содержимое на бакете в том виде, в каком они существуют на исходном сервере, а значит этот процесс будет долгим только в первый раз, а дальше всё будет синкаться за секунды. А, и ещё ансибл прописывает крон таск для бэкапа базы данных самого Иммиха, которая будет загружаться в тот же бакет на B2. Таким образом, в случае чего, достаточно будет ресторнуть бэкап БД на новом инстансе Иммиха и ему не придётся жевать метатеги для всех файлов в фоновых задачах по новой.

Ну вот вроде и всё! Кажется, отличный план. Надёжный, как швейцарские часы.

Что ещё предстоит

Чего не хватает? Ну, я пока ещё не купил внешний диск для локального бэкапа. Это ещё предстоит сделать. Как только этот вопрос будет закрыт, в целом, я буду (кажется) удовлетворён схемой бэкапов. Но я в этом деле не эксперт, так что тут как раз настаёт время для конструктивных комментариев: как сделать систему более надёжной без лишнего пердолинга? Я в курсе про схему бэкапов 3-2-1, но заморачиваться с записью данных на плёнку, кажется, пока не готов. Не знаю, буду ли готов вообще, это уже паранойя.

В теории вместо внешнего харда можно было бы заморочиться с настройкой RAID1 или RAID10. На практике я пока этим заниматься не хочу, плюс если физически сервер будет уничтожен (скажем, сгорит квартира), внешний диск может и пострадает, но совершенно не обязательно. Его можно вообще на антресоль засунуть, или куда там понадёжнее можно придумать.

После того, как все данные будут импортированы, метаданные расставлены и в долине больше не останется бандитов, настанет время для того, чтобы медленно и постепенно удалять ненужные дубли и просто плохие фотки. Это совершенно не обязательный шаг (выхватил его из соответствующего видоса: How To Remember Your Life), но я дам ему шанс и планирую иногда тратить на это время.

Ещё через некоторое время было бы неплохо полностью вычистить фотки из облаков, где я хранил их раньше. Потому что облака стоят денег.

А если я хочу так же?

Все свои ансибл-скрипты я складываю в репозиторий https://github.com/Freika/homelab. Там не только про Иммихь, но если вы пришли именно за ним, то вас интересует файл immich.yml. Скопируйте inventory.txt.example в файл inventory.txt, замените все переменные на свои собственные, выполните команду make immich (можно посмотреть в Makefile) и дальше всё будет сделано за вас, simple as that.

А что по бабкам-то?

Разово:

  • Сервер (старая рабочая станция с Ибея) — 62 евро
  • HDD + SSD для сервера — ~100 евро
  • Донат автору Иммиха — 5 евро
  • Внешний HDD на 2TB — ~70 евро

Постоянно:

  • Хранилка для бэкапов Backblaze — ~5 баксов в месяц
  • Поддержание жизни в домашнем сервере — около 6 евро в месяц (на электричество)

Автору Immich сделал разовое пожертвование, возможно, сделаю его регулярным. Да, я знаю, что я говорил выше, что не хочу платить за селфхостед софт, разница в том, сам я хочу красить забор, или меня заставляют.

А по времени как?

Я вожусь с этим всем уже третий день. Большую часть времени всё делается без моего участия: скачиваются архивы экспорта из Google Photos, работает google-photos-migrate, импортируются фотки в сам Иммихь, загружаются бэкапы на B2. Я тем временем вот писал и редактировал этот пост. Если за всё это возьмётесь вы сами, наверное, можно будет управиться за полдня активного времени: поставить Иммихь, загрузить фотки, разобраться с приложенькой на телефон, наладить бэкапы, да и то есть ансибл-плейбук по ссылке немного выше.