Как хранить фотоархив у себя, а не в Google или «Яндексе»

Преамбула

Недавно я задумался, а как мне не потерять все мои фото, видео и другие воспоминания, ведь всё хранится в Google и в случае если у них произойдёт сбой (что маловероятно, но всё таки возможно), или что-то поменяется и я не смогу платить подписку (это все мы испытали на себе), тогда сотни гигабайт фото моего сына от рождения будет потеряно.

Когда в 2022-м гугл перестал принимать платежи в россии, у моей жены заблокировался аккаунт, где было 200 ГБ, даже письмо не приходило, было крайне неприятно. Складывать фотки начали в Яндекс.Диск. Но параноя уже началась и теперь веры нет никому. С того момента я начал вынашивать план, как бы хранить фото у себя и наткнулся на пост в вастрик клубе.

Оказалось, что не я один такой, куча людей думают также, веры нет этим облакам и надо всё хранить у себя. Но перед тем как вы задумаетесь о таком же решении, нужно осознавать несколько вещей:

  1. Собственный хостинг - это в любом случае дороже, чем подписка на облако.
  2. Скорее всего это менее надёжно и нужно делать бэкапы.
  3. Это требует обслуживания, нельзя забить, нужно иногда проверять бэкапы и прочее.
  4. Лучше не начинать, если технических знаний и умений недостаточно.
  5. Собственный хостинг фото архива не исключает его в облаке, а дополняет.

В общем цель - это иметь максимальное количество резервных копий в независимых местах, максимально дёшево, в итоге я храню весь фото архив:

  • В Google Photo
  • В Яндекс.Диск
  • Локально у себя

Выбор железа

Пару лет назад я поукупал Raspberry PI 4 чтобы тестировать наш сервер для видеонаблюдения на ней, под это же дело покупал кейс и плату расширения для HDD X832 от geekworm. Вообще у них много интересного железа там. Если зазывать в Россию, то лучше из официального магазина на алиэкспресс. В общем пару месяцев я это использовал, а потом оно просто лежало и пылилось. И вот теперь кажется применение нашлось. Как вы поняли железо я выбрал 2 года назад, а сейчас осталось понять, как всё это упаковать.

Под всё это дело я купил WD Purple 8tb, собственно потому, что работать будет круглосуточно, но это не NAS, никаких RAID конфигураций. Просто 1 диск на нём будет и система и архив. Систему лучше ставить именно на диск, так как флешка даже в режиме RO через пару лет точно помрёт, проверенно.

Установка OS

Сразу же сложность, у Raspberry PI 4 micro HDMI, а меня нет переходника на micro HDMI или на SATA3, чтобы загрузить OS сразу на диск.

Решение к которому я пришёл:

  • Установить Desktop Raspberry PI OS на флешку, благо современный rpi-imager позволяет сразу включить SSH.
  • Подключиться по SSH с пробросом X
ssh -X pi@rpi.lan
  • На самой Raspberry PI снова запустить rpi-imager
  • Установить уже Lite Raspberry PI OS уже на HDD
  • Через rpi-imager выставить first boot USB

В целом тут ничего сложного, всё делается через GUI, насколько я знаю в Windows SSH клиентах типа pytty есть возможность подключаться с пробросом X, в Xshell помню точно есть.

Как хранить фотоархив у себя, а не в Google или «Яндексе»

В итоге выключаем систему, вытаскиваем флешку, включаем систему и загружаемся с HDD. Победа! Хотя подождите, диск на 8TB, а в df я вижу только 2. Ах да, rpi-imager форматирует диск в MBR, а что бы видеть больше 2TB, нам нужен уже GPT.

Часть 2.

И так теперь на живой системе нам надо проделать несколько опасных манипуляций с диском, перезагружиться и продолжить работать, на всё 1 попытка, если система не загрузится консоли нет, придётся всё начинать с нуля.

  1. Конвертируем gdisk MBR в GPT
  2. Открываем в fdisk и пересоздаём 2ю партицию. чтобы расширить диск
  3. Раширяем ФС при помощи resize2fs
  4. Уменьшаем tuna2fs количество резервируемого ext4 пространства
gdisk /dev/sda fdisk /dev/sda resize2fs /dev/sda2 tune2fs -m 0.01 /dev/sda2

Диск мы расширили, но не спешите перезагружаться, так как мы смениили тип главной таблицы разделов, естественно сменились PARTUUID разделов и система просто не смонтируется.

Узнаём новые PARTUUID

# blkid /dev/sda2: LABEL="rootfs" UUID="93c89e92-8f2e-4522-ad32-68faed883d2f" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="16ffc9f6-f0d2-0f49-a37f-3e7a24a02eb3" /dev/sda1: LABEL_FATBOOT="bootfs" LABEL="bootfs" UUID="44FC-6CF2" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="Microsoft basic data" PARTUUID="be3526d2-f501-4e92-8526-61c38d23f0e8"

Обновляем записи в /etc/fstab и в загрузчике /boot/firmware/cmdline.txt

# cat /etc/fstab proc /proc proc defaults 0 0 PARTUUID="be3526d2-f501-4e92-8526-61c38d23f0e8" /boot/firmware vfat defaults 0 2 PARTUUID="16ffc9f6-f0d2-0f49-a37f-3e7a24a02eb3" / ext4 defaults,noatime 0 1 # cat /boot/firmware/cmdline.txt console=serial0,115200 console=tty1 root=PARTUUID=16ffc9f6-f0d2-0f49-a37f-3e7a24a02eb3 rootfstype=ext4 fsck.repair=yes rootwait cfg80211.ieee80211_regdom=RS

Готово. Перезагружаемся и если всё завелось, значит всё в порядке.

Выбор софта для хранения фото

Давайте определимся с требованиями:

  • Всё должно работать исключительно локально
  • Софт желатьельно должен быть открытый, бесплатный, с большим сообществом, что бы не зависеть от выгораний разработчика
  • Должен быть хороший клиент под Android и iOS с автоматической загрузкой новых фото в фоне
  • Должен быть многопользовательский режим
  • Фото и видео должны храниться в оригинале и их должно быть легко бэкапить ещё куда-то

Как и автор поста в вастрик клубе, я остановился на Immich. Это очень приятный и зрелый проект, с активным сообществом. Разработчики сделали хорошую сравнительную таблицу своего решения со всеми конкурентами. Хотя изначально я тоже попробовал photoprism, но там нет многопользовательскости, проект частично закрытый, нет официальных клиентов под мобилки так далее.

Выглядит immich приятно и ооочень напоминает гугл фото, что естественно является огромным плюсом, не нужно привыкать к новым UX. Все требования выше выполяются, можно создавать общие альбомы, локально запускается нейронка с детекцией и распознанием лиц и прочие плюшки. Плюс проект активно развивается. Короче одни плюсы куда не плюнь.

Установка по сути в 2 клика:

В системных требованиях написано, что минимум RAM 4GB, а рекомендуется 6GB или выше. Но пока у меня и на 2GB всё крутится пректасно, на всякий случай сделал swap 8GB, так или иначе торопиться некуда, пусть стоит потеет. На крайний случай есть решение с выносом можуля с ML на внешнюю тачку, можно будет купить Bаnana или Orange или какие там нынче ещё есть пироги и положить её рядом.

Открываем доступ наружу

Железку я планировал поставить дома у роутера, естественно никакого белого IP у меня нет и никто не даст ни за какие коврижки. Мне нужен доступ к SSH сервера и HTTP к приложению. Естественно я буду использовать Tuna )) Это интересный опыт, когда ты сам становишься бытовым пользователем своего же продута.

Устанавливаем клиент по инструкции и настраиваем сервис для SSH доступа. Но так как статичные порты мы ещё не сделали, а ходить каждый раз в личный кабинет, что бы узнать порт для подключения мне лень, я набросал скрипт который ходит в API tuna, получает порт и подключается по SSH:

#!/bin/bash set -eu API_KEY="<ваш API ключ>" TCP_URL=$(curl -sSLX 'GET' 'https://api.tuna.am/v1/tunnels' \ -H 'accept: application/json' \ -H "Authentication: Bearer ${API_KEY}" | \ jq '.[] | select(.active==true) | select(.forwards_to=="127.0.0.1:22") | .public_url' -rc) HOST=$(echo -n ${TCP_URL} | awk -F: '{print $2}' | tr -d /) PORT=$(echo -n ${TCP_URL} | awk -F: '{print $NF}') echo "==> Connect to ${TCP_URL}" ssh -o StrictHostKeyChecking=no -p ${PORT} pi@${HOST}

Кладём скрипт в ~/.local/bin/rpi-ssh.sh и добавляем алиас в ~/.zshrc или ~/.bashrc

alias rpi="${HOME}/.local/bin/rpi-ssh.sh"

Естественно, ваши параметры могут отличаться, это просто пример, но в итоге всё выглядит так:

Как хранить фотоархив у себя, а не в Google или «Яндексе»

Получилась даже некая пассивная безопасность, так как порт при переподключениях будет меняться, это защитит нас от атак ботами на SSH.

Осталось открыть доступ к самому приложению. Тут тоже ничего сложного, добавляем в .env который мы скачали при установке immich переменную с токеном tuna

TUNA_TOKEN=tt_типчётокенcioc4kйцсмч

В docker-compose.yml добавляем наш сервис с tuna:

tuna: container_name: immich_tuna image: yuccastream/tuna:latest command: http immich-server:3001 --subdomain=immich --inspect=false env_file: - .env restart: always depends_on: - immich-server

Стартуем сервис и проверяем работу

docker compose up -d tuna docker compose logs --tail=5 tuna immich_tuna | INFO[11:46:51] Welcome to Tuna immich_tuna | INFO[11:46:52] Account: raspi (Paid till 05.04.2024) immich_tuna | INFO[11:46:52] Forwarding https://immich.ru.tuna.am -> immich-server:3001

Первую синхронизацию лучше проводить в локальной сети, подключаемся в приложении по условному http://192.168.0.15:2283/api и включаем синхронизацию в фоне. За ночь 100+ гигов загрузится очень быстро. Затем нажиматее выход и входите уже по публичному домену, условно https://immich.ru.tuna.am/api. Далее всё будет работать от куда угодно, а фото за день синхронизируются максимально быстро.

Вместо заключения

Всё работает, за ночь жена выгрузила весь буфер на телефоне, около 100 Гб фото и видео, далее я планирую скопировати всё, что есть из гугла и яндеска ну и купить какой нибудь storage-box в hetzner и туда складывать бэкапы тоже.

Долго не знал куда это постить, непонятно что это, толи статья, толи гайд, толи самопиар. В общем оставлю тут!

Спасибо всем кто читал и особенно тем кто дочитал ))

2121
37 комментариев

Купил себе мини сервер за 10к на Авито . Поставил туда Synology за 1 час и сливаю фотки через приложение с телефона в онлайне

5
Ответить

Вот видишь как хорошо, не надо всем вот этим заниматься) Видимо Synology тоже Гуглу не верят)

Ответить

10к это сервер.. а диски?

Ответить

Просто сбрасываю на на диски папку камера с трёх телефонов раз в пол года. Потом удаляю дубли программно. Железобетонный офлайн

1
Ответить

Но всё таки тоже не очень надёжно.
Железобетонно - распечатывать)

1
Ответить

Просто удаляю все фото с телефона раз в год, обычно перед Новым годом

1
Ответить

Вы только счётчики фотографируете ?)

1
Ответить