January 24, 2022

Моё домашнее сетевое хранилище из raspberry pi 4b

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

P.S. Время от времени пробую сделать с малинкой что-нибудь новое и дополняю статью.

Установка ОС

Есть готовая штука - raspberry pi imager, в которой можно выбрать желаемую ОС и залить её на sd-карту. В случае с малинкой на 8 гб оперативной памяти стоит обратить внимание на битность ОС. Якобы видеодрайвера в 64битной ОС работают плохо, но в дальнейшем мне они и не нужны. Я выбрал 64-битную версию Ubuntu server.

Можно установить ОС, не подключая монитор/клавиатуру/мышь. Чтобы она подключилась к сети, где-то в файлике на sd-карточке с ОС придётся прописать имя и пароль от wifi сети. Но ещё лучше (и на мой взгляд проще) подключить сеть через кабель к роутеру. В малинке гигабитный порт, для нужд домашнего хранилища самое то. Вышеописанные шаги с паролем не нужны, зато неплохо бы иметь доступ на роутер, чтобы узнать, по какому адресу доступна малинка.

Либо можно просканировать локальную сеть и так узнать адрес:

sudo nmap -sn 192.168.1.0/24

При самом первом запуске ОС грузится несколько минут, а я поначалу думал что что-то делаю не так. Вся дальнейшая работа и настройка делается через ssh

Внешний жёсткий диск

Я купил внешний жёсткий диск на 4Тб: HDD WD Elements Desktop WDBWLG0040HBK-EESN. Из особенностей - у него есть отдельный провод для питания от розетки и он не должен тащить энергию из малинки. Из минусов - в розетку придётся втыкать два девайса. У малинки синие разъёмы - usb 3.0, диск лучше втыкать в них.

Дальше начинаются приключения: raspberry pi imager при установке ОС размечает сд-карточку в MBR. Можно вместо карточки подключить жёсткий диск, но MBR позволит использовать только первые 2 Тб диска. А ещё хочется отказаться от sd карточки. Почему-то полностью переселить ОС на диск c GPT разметкой у меня не получилось, ОС не грузилась. В качестве полумеры я оставил загрузочный раздел на sd карточке и раздел с ОС перенёс на диск. Количество записей на карточку будет минимальным, и в случае потери я смогу вставить новую карточку памяти с загрузчиком и работать дальше.

Самое странное, что в сдругим жёстким диском toshiba на 2 гб с gpt внезапно загрузиться получилось. Я потратил около дня, но так и не понял, почему с одного диска грузится, а с другого - нет.

Можно взять раздел с ОС прямо с сд карточки (зря что ли на неё ОС ставили и настраивали) и скопировать на диск. Дальше понадобится узнать айдишники для разделов.

sudo blkid

Примерное описание тут: https://linuxtut.com/en/7af17f1272ca0c558d47/

Эти айдишники надо будет обновить в двух местах:

  1. В загрузчике boot/cmdline.txt указывает, откуда грузить ОС.
  2. В самой ОС в еtc/fstab монтируются и загрузчик, и раздел с ОС

Как я потом узнал - не обязательно использовать PARTUUID, можно вместо него указать PARTLABEL. Название раздела можно сделать любое, и мне это показалось более удобным. Но надо проследить, чтобы не было двух разделов с одинаковым названием.

В малинке целых 2 usb порта, поэтому можно включить рядышком второй диск и сделать софтовый RAID1. На двух дисках будут лежать идентичные копии данных, чтение теоретически может ускориться в два раза, запись будет со скоростью самого медленного и некоторыми приколами дисков с черепичной записью. К сожалению, о современных дисках производители эту информацию не особо публикуют, в одной "модели" может оказаться как одно, так и другое, и я RAID делать не стал. В планах организовать резервное копирование с домашнего ПК на малинку - тогда отказ одного из дисков или устройств не будет фатальным.

Применение

  1. sshfs для доступа из Линукса для тех, кто не осилил нормальную настройку самбы. (это я)
  2. Samba для доступа к папкам из локальной сети не только из линукса
  3. QBittorrent с возможностью управлять им из браузера
  4. 24/7 крутить своего телеграм бота. (это тоже я)
  5. Хранить git-репозитории
  6. Подключить второй массив и организовать raid
  7. Настроить резервное копирование с помощью rsync и cron
  8. Раздобыть вторую малинку и организовать загрузку по сети, вообще без sd- карты
  9. Добавить пассивное охлаждение
  10. Настроить LUKS шифрование для дисков

Скорость копирования по проводу через sshfs получилась 44-47 мегабайт в секунду. Почти полгигабита! У меня есть подозрение, что сеть на малинке быстрее, а это тормозит жёсткий диск или роутер, но пруфов не будет.

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

Ниже будет упрощённый пересказ того, что я узнал по этой ссылке: https://obu4alka.ru/ustanovka-qbittorrent-na-ubuntu-server-20-04-lts.html

Кстати, qbittorrent в браузере выглядит практически так же, как и приложение. И ещё он качает/раздаёт круглые сутки, так что можно оживить полузабытые раздачи.

В ubuntu есть systemd, которая запускает сервисы при старте ОС. Чтобы бот и торрент тоже запускались, сделаем текстовые файлики:

etc/systemd/system/qbittorrent-nox.service

[Unit]
Description=qBittorrent Command Line Client
After=network.target

[Service]
Type=forking
User=qbittorrent-nox
Group=qbittorrent-nox
UMask=007
ExecStart=/usr/bin/qbittorrent-nox -d --webui-port=8080
Restart=on-failure

[Install]
WantedBy=multi-user.target

и ещё один для моего бота:

[Unit]
Description = Runs my bot

Wants=network-online.target
After=network-online.target nss-lookup.target

[Service]
Type=simple
ExecStart=/home/ubuntu/bot/run.sh

[Install]
WantedBy=multi-user.target

В случае qbittorrent я создал отдельного пользователя, но если честно не особо понял смысл. Ну да, так вроде безопаснее. А потом самба не cможет открыть файл, т.к. у неё нет прав на чтение и вас ждут красота и изучение того как в линуксе работают пользователи, группы и разрешения.

В настройках qbittorrent (прямо в веб-интерфейсе) есть смысл поменять дефолтную папку для хранения торрентов, а так же залезть во вкладку webUI и убрать там галочку "Use UPnP / NAT-PMP to forward the port from my router", чтобы запретить вход в веб-интерфейс из сети снаружи роутера. Ещё там есть опция "Bypass authentication for clients on localhost", её наоборот удобнее включить для доступа из локальной сети без пароля.

Самба

В windows 10 отключили старую версию протокола smb, который позволял заходить без авторизации. Но с самбой всё как-то криво складывается, я сделал readonly шару и забил, потому что из линукса достаточно sshfs.

Для того, чтобы самба переходила по символьным ссылкам, придётся ещё какие-то опции указывать. Их тут нет. /etc/samba/smb.conf

[share]
  path = /mnt/data/share/
  read only = yes
  guest ok = yes
  guest only = yes

sshfs

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

alias mount-pi8="sshfs -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3 [email protected]:/ /home/me/Desktop/pi8"
alias umount-pi8="umount /home/me/Desktop/pi8"

Единственное - несмотря на параметры, оно как-то криво работает при покидании домашней сети. Ноутбук был не рад, пришлось перезагружать. По тем же причинам в автозапуск такое ставить не надо. Руками каждый раз монтировать - чуточку лень. Возможно, я всё-таки донастрою самбу или ещё что-то.

В остальном - шикарно, скорость работы близка к скорости жёсткого диска (возможно, не современного, а десятилетней давности, но всё же).

Хранение git-репозиториев

Я не стал использовать что-то типа gitlab и пошёл по максимально простому пути. В git сервер и клиент равноправны, на клиенте хранится своя копия данных. Между ними нет большой разницы, и я под сервером подразумеваю круглосуточно работающий ПК, и предполагаю что клиент запускается время от времени и закидывает на сервер свои изменения.

Адресов для скачивания/заливания репозитория может быть несколько. Обычно он один и называется origin. Но никто не запретит добавить несколько адресов, выкачать ветку с одного и потом её влить по другому адресу. И даже в совершенно другой репозиторий так можно, лишь бы имена веток не пересекались. Гибкость впечатляет, хоть про неё и не все знают.

Если есть ssh доступ к серверу, то добавить туда репозиторий очень просто:

На сервере: создать папку, в ней вызвать

git init --bare

На клиенте:

git remote add pi8 ssh://user@ip/path-to-repo
git push pi8 master

В идеале ещё можно создать отдельного пользователя для git и т.п., но для локального домашнего применения не вижу смысла.

Подробнее можно прочитать тут: https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server

RAID массив

В итоге я отказался от этой идеи.
С помощью mdadm можно сделать raid1 массив, в котором данные будут лежать в двух копиях. Одна на одном диске и другая на другом. Т.к. диски обычно неравных размеров, лучше вместо указания дисков (типа /dev/sda) использовать разделы: например /dev/sda1. Само собой, разделы должны быть на разных дисках. В случае отказа одного из дисков массив с данными продолжит работать как ни в чём ни бывало, пока не откажет второй диск. В общем, за статусом raid массива надо будет следить (и мне кажется, это неудобно).

Вдобавок, я сделал раздел с raid только для важных данных, и при отказе основного диска ОС похерится и малинка всё равно не запустится. Я подумал над этим безобразием и решил вместо этого сделать бэкапы.

Бэкапы

В отличие от raid массива, у бэкапов есть очень полезное свойство - при случайном удалении файлов их можно будет восстановить.

Я подумал над возможными вариантами:

  • есть специальное ПО типа https://ru.wikipedia.org/wiki/Bacula. Инкрементальные бэкапы хранятся в каком-то бинарном формате, само ПО надо ставить и настраивать.
  • rsync + cron. Внезапно, rsync умеет делать инкрементальные бэкапы. Чтобы не хранить один файл по многу раз, используюся жёсткие ссылки. С точки зрения меня как пользователя получатся папки типа backup1, backup2, и т.д, в каждой из которых лежат все файлы на момент копирования.

На мой взгляд, с rsync самый удобный вариант - я смогу вставить диск с бэкапами в любой комп и вытащить данные обратно.

Я вдохновлялся вот этой статьёй: https://linuxconfig.org/how-to-create-incremental-backups-using-rsync-on-linux, но сделал немножко по-другому:

readonly DATETIME="$(date '+%Y-%m-%d_%H:%M:%S')"
readonly LOG_FILE="/mnt/backup/logs/backup_safedata_${DATETIME}.txt"

printf "start at ${DATETIME}\n" >> $LOG_FILE

rsync -av --delete /mnt/safedata --link-dest ../latest --exclude "lost+found" /mnt/backup/safedata/${DATETIME} >> $LOG_FILE

df >> $LOG_FILE
echo "finished at $(date '+%Y-%m-%d_%H:%M:%S')" >> $LOG_FILE

cd /mnt/backup/safedata
rm latest
ln -s ${DATETIME} latest

python3 -c '
import os
import shutil
listdir = os.listdir(".")
files = sorted([f for f in listdir if f.startswith("20")])
to_preserve = set(files[-31:])
monthly = {f[:7]: f for f in reversed(files)}
to_preserve.update(monthly.values())
for f in sorted(to_preserve):
	print(f"keep '{f}'")
for f in set(files) - to_preserve:
    print(f"remove '{f}'")
    shutil.rmtree(f)
' >> $LOG_FILE

latest - мягкая ссылка на последний бэкап. В --link-dest путь должен быть абсолютный или относительный для папки с бэкапом, поэтому надо выскочить на директорию вверх: ../latest

если ссылки нет, то rsync всё ещё работает.

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

скрипт на питоне хранит последние 30 версий бэкапа и первую версию каждого месяца, остальные удаляет.

Для отладки есть полезные опции --dry-run для запуска без реальных изменений, а так же можно опцию --verbose указать дважды и получить более подробный вывод: -vv

Опция -a раскрывается в кучу настроек, которые пытаются перетащить время, пользователя файла, права доступа и т.п. Я попробовал запускать rsync между компом и малинкой и несмотря на --link-dest создавались копии файлов. Я потратил кучу времени на то, чтобы понять, что все эти опции мешают и в итоге между машинами копировал с опциями -rl --size-only

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

C помощью cron можно будет настроить бэкапы на каждый день или каждую неделю:

crontab -e

и там написать

20 4 * * * /mnt/backup/backup.sh

Чтобы каждую ночь в 4:20 делать бэкап.

Загрузка по сети*

*Задание со звёздочкой, будут приключения.

Заливать образ на флешку, вставлять в малинку, ждать пока загрузится - не самое весёлое занятие. После того, как перевая малинка стала работающим 24/7 полноценным сервером, я раздобыл вторую и решил попробовать загрузку по сети.

Глобально это состоит из двух шагов:

  1. включить на клиентской малинке загрузку по сети
  2. настроить на сервере dhcp и nfs, чтобы они работали

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

Список команд и т.п. несложный, но в процессе я нашёл кучу подводных камней, и настройка заняла у меня целый вечер.

https://www.raspberrypi.com/documentation/computers/remote-access.html#network-boot-your-raspberry-pi

Вот ссылка на документацию, но делать надо далеко не всё, что в ней написано.

Настройка клиента

На 4B, загрузку включать надо, причём процесс отличается от предыдущих версий.

Во-первых, понадобится поставить именно raspbian os. В принципе, можно обойтись и без подключения мышки-клавиатуры, если в rpi Imager нажать ctrl+shift+x (или какое-то ещё неочевидное сочетание клавиш), оказаться в настройках и там указать ключ для ssh. Экран я советую всё-таки подключить, он потом пригодится.

Запускаем штуку для настройки (прям из консоли)

sudo raspi-config

В ней в менюшках надо выбрать Advanced Options, Boot Order, Network Bootи в ней выбрать загрузку по сети (что странно - с загрузкой по сети вариант ровно один - малинка попытается загрузиться с sd карты, если не получится - то по сети).

Чтобы изменения применились, придётся перезагрузиться.

И потом командой

vcgencmd bootloader_config

можно посмотреть, что в BOOT_ORDER. В идеале там должно быть 0xf21. Тут можно посмотреть подробнее, что же число значит:

https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-4-bootloader-configuration

Я так понял, они справа налево идут.

После этого малинку можно выключить, выдернуть из неё sd-карту и снова включить. Выше я советовал включить экран - малинка на нём покажет текстом свой ip адрес и потихоньку растущее количество неудачных попыток загрузки по сети.

Настройка сервера

Дальше инструкции с официального сайта следовать не обязательно.

Во-первых, можно просто взять и на на домашнем роутере во вкладочке с настройками DHCP указать статические ip адреса для сервера (давно уже так сделал) и для клиента (сделал сейчас).

Во вторых, у меня клиент - raspbian os, а сервер ubuntu. На сайте происходит кунг-фу по включению той же самой sd-карты в сервер, загрузке с неё и дальнейшей модификации для того, чтобы клиент и сервер различались. Спасибо, но я воздержусь.

Итак, можно смело листать сайт до инструкции

sudo apt install tcpdump dnsmasq
sudo systemctl enable dnsmasq
sudo tcpdump -i eth0 port bootpc

Но dnsmasq ставить пока не надо.

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

С dnsmasq меня ждал сюрприз. Это в одном лице и dns сервер, и нужные нам dhcp и tftp сервера. В ubuntu уже есть свой dns-резолвер, systemd-resolved, и он, как нетрудно догадаться, тоже dns сервер, который слушает порт 53 и не даёт слушать его другим.

После установки dnsmasq полезет на 53 порт и не сможет - тот уже занят. Всё что надо сделать - залезть в /etc/dnsmasq.conf и указать там port=0, чтобы dns-составляющая не запускалась и не мешалась.

https://askubuntu.com/questions/191226/dnsmasq-failed-to-create-listening-socket-for-port-53-address-already-in-use

Я вместо этого воспользовался первым нагугленным советом и отключил systemd-resolved. В итоге dns работать перестал, я узнал, что команде sudo без dns работается плохо и потом возвращал всё обратно.

так вот, в dnsmasq.conf должно в итоге быть

port=0
dhcp-range=192.168.1.255,proxy
log-dhcp
enable-tftp
tftp-root=/tftpboot
pxe-service=0,"Raspberry Pi Boot"

tftp-root - путь к папке с загрузчиком на сервере

как скопировать системный раздел на сервер

В оригинальной статье они обходятся одной sd-картой, но я по понятным причинам включил sd-карту в ноутбук и задумался, как же скопировать её на сервер. Суть проблемы в том, что

rsync from to

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

Можно написать так:

sudo rsync from to

Тогда получится скопировать файлы с владельцем root, но не получится их записать по двум причинам:

  1. у рута своя папка .ssh и там может не быть ключа для ssh
  2. на системе, куда копируем, rsync работает не из под-рута

Красота и удобство. Указать root@ip:/path у меня тоже не получилось. Первая проблема решается копированием ~/.ssh/id_rsa, вторая - хитрой опцией. Для хитрой опции требуется, чтобы на другой машине команда sudo не спрашивала пароль. Рабочая команда выглядит так:

sudo rsync --progress -ax -e "ssh" --rsync-path="sudo rsync" rootfs/ [email protected]:/nfs/client1

Таким незамысловатым образом можно скопировать загрузчик в /nfs/nfsboot, а системный раздел в /nfs/client1

Идею и команду взял отсюда: https://superuser.com/questions/605425/rsync-root-files-between-systems-without-specifying-password

После этого надо будет в nfsboot/cmdline.txt заменить указание на root: у меня получилось так:

console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.1.142:/nfs/client1,vers=4.1,proto=tcp rw ip=dhcp rootwait

и поправить etc/fstab

192.168.1.142:/nfs/tftpboot	/boot	nfs	defaults,vers=4.1,proto=tcp 0 0

То, что есть только boot без корневой системы - нормально, так и должно быть

Кроме того, надо ещё включить rpcbind, настроить nfs-kernel-server и в /etc/exports указать пути для nfs:

/nfs/client1 *(rw,sync,no_subtree_check,no_root_squash)
/nfs/tftpboot *(rw,sync,no_subtree_check,no_root_squash)

В результате малинка без SD-карты загружается по сети из файлов в папке. При желании ту папку можно будет копировать, хранить несколько разных версий ОС и т.п.

Пассивное охлаждение

Температуру можно узнать так:

vcgencmd measure_temp

У меня она была 64 градуса (с нагрузкой из описанного выше софта), после - 57. Я купил корпус Qumo Aluminum RS001, который заодно является радиатором. Охлаждение пассивное, вентилятора нет и ломаться нечему. И шуметь тоже. Сам корпус, кажется, сделан из аллюминия. Смотрится красиво и солидно. В комплекте шли два маленьких кусочка термопрокладки, болтики и шестигранный ключик - в общём, всё необходимое.

Эффектом немного разочарован, думал будет градусов 10-15 разницы, а получилось около 7. Сам корпус ощутимо горячий во всех местах

LUKS шифрование раздела

Опциональная часть, надо чётко понимать, нужно ли шифрование. Цель - чтобы содержимое диска было невозможно прочитать при включении в посторонний пк.

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

Шифрование спасает только от сценария, когда постороний забирает диск и пытается прочитать с него данные. Всё, ничего больше.

Я где-то видел, чтобы на малине как-то хитро шифровали прям диск с системой, но я так извращаться не буду. В малинке негде хранить пароль, и я хочу, чтобы она могла сама включиться без моего участия. Шифрую только отдельный раздел с данными.

Итак, если шифрование всё-таки нужно, начнём:

Скорее всего, cryptsetup уже установлен, если нет, ставим:

sudo apt install cryptsetup

Особенности малинки - нет хардварной поддержки aes, скорость шифровки и дешифровки будет медленная, советуют вместо него использовать adiantum.

Проверить скорость шифрования (без записи на диск, всё в RAM):

cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       386643 iterations per second for 256-bit key
PBKDF2-sha256     630912 iterations per second for 256-bit key
PBKDF2-sha512     510007 iterations per second for 256-bit key
PBKDF2-ripemd160  324034 iterations per second for 256-bit key
PBKDF2-whirlpool  142935 iterations per second for 256-bit key
argon2i       4 iterations, 333516 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id      4 iterations, 335222 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
#     Algorithm |       Key |      Encryption |      Decryption
        aes-cbc        128b        85.6 MiB/s        98.5 MiB/s
    serpent-cbc        128b        42.7 MiB/s        44.4 MiB/s
    twofish-cbc        128b        63.3 MiB/s        69.1 MiB/s
        aes-cbc        256b        76.0 MiB/s        77.5 MiB/s
    serpent-cbc        256b        43.8 MiB/s        44.4 MiB/s
    twofish-cbc        256b        68.1 MiB/s        69.2 MiB/s
        aes-xts        256b        84.4 MiB/s       101.8 MiB/s
    serpent-xts        256b        43.1 MiB/s        44.8 MiB/s
    twofish-xts        256b        67.9 MiB/s        70.7 MiB/s
        aes-xts        512b        78.6 MiB/s        79.8 MiB/s
    serpent-xts        512b        44.9 MiB/s        44.7 MiB/s
    twofish-xts        512b        70.5 MiB/s        70.6 MiB/s

И померять aes-adiantum, который должен быть быстрее

cryptsetup benchmark -c xchacha12,aes-adiantum
# Tests are approximate using memory only (no storage IO).
#            Algorithm |       Key |      Encryption |      Decryption
xchacha12,aes-adiantum        256b       188.1 MiB/s       189.2 MiB/s


cryptsetup benchmark -c xchacha20,aes-adiantum
# Tests are approximate using memory only (no storage IO).
#            Algorithm |       Key |      Encryption |      Decryption
xchacha20,aes-adiantum        256b       161.0 MiB/s       162.2 MiB/s

Ссылки, которыми я руководствовался:

https://gist.github.com/palopezv/792b9f0100484186c3f74cbee7b07630

https://wiki.davidl.me/index.php?title=LUKS&mobileaction=toggle_view_desktop

Я выбрал xchacha20, т.к. разница в скорости не критичная, а оно вроде как надёжнее.

xchacha20 отличается в xchacha12 количеством раундов шифрования - 20 вместо 12.

Где почитать: https://www.reddit.com/r/cryptography/comments/p3dflu/fulldiskencryption_xchacha12_vs_xchacha20/

Создадим раздел:

sudo cryptsetup luksFormat --type=luks2 --sector-size=4096 -c xchacha20,aes-adiantum-plain64 -s 256 -h sha512 --use-urandom /dev/sdXX

Тут вместо sdXX написать реальный раздел как он показывается в lsblk

Дальше был забавный момент - после всего программа требует написать YES большими буковками. Просто чтобы убедиться, что человек внимательно посмотрел на команду и случайно не похерит нужный раздел.

Дальше надо подключить раздел и отформатировать

sudo cryptsetup open /dev/sdXX NAME
sudo mkfs.ext4 /dev/mapper/NAME

Примонтировать раздел:

# Open the encrypted drive
sudo cryptsetup open /dev/sdXX NAME
# Mount your partition
mount -t ext4 /dev/mapper/NAME MOUNT_LOCATION

Размонтировать:

# Unmount your partition
umount MOUNT_LOCATION
# Close the decrypted drive
cryptsetup close NAME

Выводы

Если хочется только домашнее хранилище - проще и дешевле подключить диск напрямую к роутеру (некоторые роутеры так умеют). Но мне хотелось иметь полноценный сервер, хоть и маленький. Своей цели я достиг и очень доволен.