← все статьи

NAS, день шестнадцатый: домашний ящик, который сам за собой следит

Шестнадцатый день с первого выпуска NAS — нашего домашнего хранилища. Дома стоит ящик с шестью дисками и TrueNAS. Он хранил, но ничего не рассказывал: что с дисками, куда ушло место, дошли ли копии.

Фото семьи жили в iCloud, старые архивы — по флешкам, бэкапы наших проектов — только у облачных провайдеров. Хотелось одну панель, которая хранит всё это и сама говорит, когда что-то не так. За две недели она выросла в то, чем мы пользуемся каждый день.


Панель NAS, экран «Фото»: медиатека по дням, Live-снимки и ролики, переход к месяцу
Медиатека в панели: по дням, как на телефоне

Чистый Debian — или рядом с TrueNAS

Целевая форма NAS — чистый Debian поверх готового пула ZFS. Ящик сам раздаёт папки в сети через свою Samba: люди, пароли и права — в панели, а не в конфигах. Служба пула поднимается раньше докера: отпирает пул ключом, монтирует и только потом пускает панель. Иначе панель, поднявшаяся первой, завела бы каталоги данных на системном диске, и пул потом туда бы не смонтировался.

Наш собственный ящик пока живёт во второй форме — рядом с TrueNAS. NAS не забирает у него ни пул, ни папки в сети, а всё своё держит в одном наборе данных — базу, секреты, файлы бакетов. Пул отпирает и монтирует TrueNAS, а папки SMB панель показывает только на чтение: кто читает, кто пишет, кто сейчас подключён. Так можно попробовать NAS, не ломая то, что уже работает, и переехать на чистый Debian потом.

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

Бакеты с входом S3

Хранилище объектов, совместимое с S3: файл на диске и строка в базе. Совместимость проверяем настоящими клиентами — boto3, aws cli, rclone.

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

Медиатека

Снимки с iPhone в фоне выгружает своё приложение на Flutter с ядром на Rust. Перенос из iCloud забрал 95 203 файла — и не изменил в iCloud ничего.

Старые фото с камер ложатся импортом: дата из EXIF, дубли — по sha256 во всей медиатеке, RAW и JPEG одного кадра склеиваются в один снимок. Источник импорт не трогает никогда.


Экран «Импорт снимков»: отчёт по папке старой камеры — годы, даты не из EXIF, уже лежащие в медиатеке
Сначала отчёт: сколько файлов, каких лет, что уже есть — и только потом импорт

Удалённое уходит в «Недавно удалённые» на 30 дней и возвращается теми же ключами. Поворот и обрезка с наклоном не трогают оригинал: ящик собирает копию рядом, а вернуть исходник — одна кнопка.


Правка снимка: рамка обрезки, наклон −4°, пропорции 4:3
Правка снимка: наклон по градусу и пропорции — оригинал цел

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

Диски

Раз в пять минут сборщик снимает пул, SMART и то, что знает TrueNAS. Панель объясняет словами и даёт команду, а тревогу шлёт пушем.


Экран «Диски»: пул Data, идущая проверка пула 37% и тревога по кабелю диска
Проверка пула — полосой, тревога по кабелю — словами

У дисков Seagate ящик сверяет часы SMART с журналом FARM: сброшенный счётчик выдаёт диск, который старше, чем выглядит.

Третье место для бэкапов

Ящик стоит дома за NAT, и серверы проектов до него не достают. Поэтому туннель открывает сам ящик: на сервере он виден обычным S3-адресом, а ключ ящика там умеет только этот проброс — без входа и без команд.

Четыре боевых проекта шлют сюда шифрованные копии — рядом с облачными, а не вместо них.

Живьём

Процессор, ядра, память, сеть, температуры, нагрузка на диски — по сокету раз в 2–3 секунды, режим Live на любом графике. Пул и системный диск — порознь.


Экран температур: процессор, NVMe и шесть дисков пула за сутки
Температуры за сутки: процессор, NVMe и диски пула

Обновление кнопкой

Ящик сам проверяет, не вышла ли новая версия: раз в несколько часов сверяется с GitHub, а когда открыт экран «Обновление» — сразу. Если вышла, у пункта меню появляется уведомление о новой версии.

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


Экран «Обновление»: стоит v0.51.0, на GitHub v0.53.1, список изменений трёх версий и кнопка «Обновить до v0.53.1»
Что придёт — словами, по версиям. Одна кнопка

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

За 16 дней — 82 выпуска, у каждого проверки на стенде настоящими клиентами. Установку с нуля, перезагрузки и отказ диска прогнали в виртуальной машине с RAIDZ2 из шести дисков.

Что дальше

В следующих записях — истории этой недели подробнее: почему ящик, который ничего не делает, пишет на диски больше 50 ГБ в сутки, как перенести 95 тысяч снимков из iCloud, ничего там не тронув, и что проверять, когда сервер получил коленом.

Своё железо — тоже система
Начните с брифа: четыре вопроса и честный ответ, подходим ли мы друг другу.
Пройти бриф