# Подготовка диска под медиахранилище (tvvm) Runbook: разметка, форматирование и монтирование диска `sdb` (700G) под хранилище TeleWave. Выполняется **один раз** на сервере `tvvm` перед запуском фичи медиа. Все команды — от root (`sudo -i` или с `sudo` перед каждой). > ⚠️ Команды разметки **уничтожают данные** на целевом диске. Диск `sdb` сейчас пустой (нет > разделов), но каждый шаг ниже содержит проверку — не пропускайте их. Итог: раздел `sdb1` (ext4) смонтирован в `/srv/telewave/media`, внутри созданы рабочие каталоги, запись из контейнера (работает под непривилегированным uid 1654) возможна. --- ## 0. Проверить, что это тот самый диск ```bash lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS,FSTYPE /dev/sdb ``` Ожидается: `sdb` размером `700G`, тип `disk`, **без разделов и без точек монтирования**. Убедитесь дополнительно, что на диске нет файловой системы и подписей: ```bash sudo wipefs -n /dev/sdb # -n = «сухой прогон», ничего не меняет ``` Если вывод пустой — диск чист, продолжаем. Если что-то нашлось (следы старой ФС/RAID) — **остановитесь** и разберитесь, что это, прежде чем идти дальше. --- ## 1. Создать таблицу разделов и один раздел GPT + один раздел на весь диск: ```bash sudo parted -s /dev/sdb mklabel gpt sudo parted -s -a optimal /dev/sdb mkpart primary ext4 0% 100% sudo partprobe /dev/sdb lsblk /dev/sdb ``` Должен появиться `sdb1` размером ~700G. --- ## 2. Отформатировать в ext4 `-m 1` уменьшает резерв под root с 5% до 1% (на диске данных резерв в 35 ГБ не нужен), `-L` даёт метку тома: ```bash sudo mkfs.ext4 -m 1 -L telewave-media /dev/sdb1 ``` --- ## 3. Создать точку монтирования ```bash sudo mkdir -p /srv/telewave/media ``` --- ## 4. Прописать в /etc/fstab (монтирование по UUID) Монтируем по UUID, а не по имени `sdb1` — имя может измениться при добавлении дисков. Узнать UUID: ```bash sudo blkid /dev/sdb1 ``` Скопируйте значение `UUID="..."` и добавьте строку в `/etc/fstab` (подставьте свой UUID): ``` UUID=ВАШ-UUID /srv/telewave/media ext4 defaults,noatime,nofail,x-systemd.device-timeout=10 0 2 ``` Пояснения к опциям: - `noatime` — не обновлять время доступа при чтении сегментов; заметно снижает лишние записи при раздаче видео. - `nofail` — если диск не подключился, система всё равно загрузится (приложение просто не сможет писать, а не «висит» на загрузке). - `x-systemd.device-timeout=10` — не ждать диск дольше 10с при старте. Проверить, что fstab корректен, и смонтировать: ```bash sudo systemctl daemon-reload sudo mount -a findmnt /srv/telewave/media ``` `findmnt` должен показать смонтированный `ext4` на `/dev/sdb1`. **Ошибка на этом шаге лучше, чем на следующей перезагрузке** — если `mount -a` ругается, чините fstab сейчас. --- ## 5. Рабочие каталоги и права Создать структуру, ожидаемую приложением: ```bash sudo mkdir -p /srv/telewave/media/{inbox,manual,uploads,originals,assets} ``` **Владелец.** Контейнер работает под непривилегированным пользователем `app` образа aspnet — **uid/gid 1654** (`USER $APP_UID` в Dockerfile). Bind-mount пробрасывает права хоста внутрь как есть, никакого маппинга uid не происходит: контейнер увидит ровно те номера, что стоят на хосте. Значит, владельцем хранилища должен быть 1654. Имени `app` на хосте нет — заводим группу с этим gid, чтобы права были читаемыми в `ls` и чтобы в неё можно было добавить себя: ```bash sudo groupadd -g 1654 telewave # «уже существует» — не ошибка, идём дальше sudo usermod -aG telewave "$USER" # чтобы класть файлы в inbox/manual под собой ``` > Членство в группе применяется **только к новым сессиям**: перелогиньтесь (или `newgrp telewave`), > иначе следующая команда отработает, а записать файл вы всё равно не сможете. Проверка — `id` > должен показать `telewave` в списке групп. Теперь владелец и базовые права: ```bash sudo chown -R 1654:1654 /srv/telewave/media sudo chmod -R 750 /srv/telewave/media ``` Два каталога наполняете вы, а не приложение: - `inbox/` — разбирается сканером автоматически: файл с допустимым расширением и стабильным размером регистрируется сам и уходит в обработку; - `manual/` — **ручной разбор**: сканер сюда не заглядывает. Файлы видны в админке (Медиа → «Из папки manual»), выбираются галочками и сразу привязываются к шоу. Импортированные файлы уходят из каталога так же, как из `inbox/`. Их открываем группе на запись, плюс setgid (`2` в начале режима) — чтобы файлы, положенные вами по SFTP/rsync, наследовали группу `telewave`, а не вашу личную, и приложение их видело: ```bash sudo chmod 2775 /srv/telewave/media/inbox /srv/telewave/media/manual ``` Забрать **файл** из этих каталогов приложение сможет в любом случае: удаление зависит от прав на каталог (владелец — 1654), а не на сам файл, поэтому чужой umask у ваших загрузок импорту не мешает. А вот **вложенные папки** — мешают, и одним `chmod` это не закрыть. В `manual/` обычно кладут не файлы, а каталог раздачи целиком. Владельцем такого каталога станете вы, режим ему выставит umask клиента (у SFTP это обычно 755), и группе достанется `r-x` — приложение не сможет ни вынести файл в `originals/` при импорте, ни подчистить спутники и опустевший каталог. Права на новое внутри задаются дефолтными ACL — они действуют независимо от того, каким клиентом и с каким umask файлы приехали: ```bash sudo apt install -y acl sudo setfacl -R -m g:telewave:rwx -m d:g:telewave:rwx \ /srv/telewave/media/inbox /srv/telewave/media/manual ``` Проверить — `getfacl /srv/telewave/media/manual`: нужны строки `group:telewave:rwx` и `default:group:telewave:rwx`. Без ACL альтернатива только клиентская (принудительные права `775` на загрузку в WinSCP, umask 002 у rsync) — держится на настройке каждого, кто заливает файлы, и ломается при первой же загрузке другим инструментом. **Обновление существующей установки.** Если хранилище было заведено раньше, когда контейнер работал под root, — те же команды и есть вся миграция: выполните их на остановленном контейнере (`docker compose down`), затем поднимайте новый образ. До смены владельца приложение стартует, но любая запись в `/media` будет падать с `Permission denied`. --- ## 6. Проброс в контейнер (bind mount) В `docker-compose.yml`, в сервис `app`, добавить том (этого пока **нет** в репозитории — появится вместе с реализацией фичи, здесь для справки): ```yaml services: app: # ... существующая конфигурация ... volumes: - /srv/telewave/media:/media mem_limit: 3g ``` И переменные окружения в `.env` (см. `docs/media-storage-and-streaming.md`): ``` Storage__RootPath=/media ``` Выбран **bind mount**: диск смонтирован в ОС через fstab (шаги 1–5) и виден всегда, независимо от Docker — это важно, потому что файлы в `inbox/` кладутся вручную по SFTP/rsync, в том числе когда контейнер остановлен. > **Альтернатива — named volume, монтируемый самим Docker** (не используем, для справки). Позволяет > пропустить шаги 3–5, но диск тогда доступен только при запущенном контейнере, а подкаталоги всё > равно надо создавать заранее. Пример: > > ```yaml > services: > app: > volumes: > - media:/media > mem_limit: 3g > volumes: > media: > driver: local > driver_opts: > type: ext4 > device: /dev/disk/by-uuid/ВАШ-UUID > o: noatime > ``` > > Разметка и `mkfs.ext4` (шаги 1–2) обязательны в любом случае. --- ## 7. Проверка записи из контейнера После добавления тома и пересборки образа убедиться, что контейнер работает под нужным uid и пишет на диск: ```bash docker compose exec app id # ожидается uid=1654 gid=1654 docker compose exec app sh -c 'touch /media/.wtest && ls -l /media/.wtest && rm /media/.wtest' ``` И что вы сами можете класть файлы вручную (под своим пользователем, не через sudo), а приложение — убирать созданное вами, в том числе внутри вложенных каталогов: ```bash touch /srv/telewave/media/inbox/.wtest && rm /srv/telewave/media/inbox/.wtest mkdir -p /srv/telewave/media/manual/.wtest && docker compose exec app sh -c 'rmdir /media/manual/.wtest' ``` Все команды должны отработать без ошибок доступа. `Permission denied` в первой — не сделан `chown -R 1654:1654` из шага 5; во второй — вы не в группе `telewave` либо не перелогинились после `usermod` (в SFTP-клиенте — не переподключили сессию); в третьей — не выставлены дефолтные ACL, и приложение не достаёт файлы из ваших подкаталогов. На этом подготовка хоста завершена — дальнейшее (создание `MediaAsset`, нарезка ffmpeg) делает уже само приложение. --- ## 8. Что дальше смотреть в админке Заполненность диска видна в разделе **Админка → Хранилище**: сколько занято на томе целиком, сколько из этого приходится на TeleWave, и на что именно оно ушло — сегменты программ и заставок, исходники, inbox, изображения. Отдельной строкой считается «прочее под корнем»: если там не ноль, значит на томе лежит что-то, чего приложение не создавало. Цифра считается обходом дерева и потому кэшируется на пять минут; кнопка «Пересчитать» заставляет пересчитать сразу. Когда свободного места остаётся меньше `Storage:MinFreeSpaceBytes`, страница показывает предупреждение — с этого порога сервер начинает отклонять загрузку новых файлов. --- ## Приложение: если диск нужно расширить в будущем Если VM отдаст диску больше места (например `sdb` вырастет с 700G), после увеличения на стороне гипервизора: ```bash sudo growpart /dev/sdb 1 # расширить раздел на весь диск sudo resize2fs /dev/sdb1 # расширить ext4 (можно на смонтированном) df -h /srv/telewave/media ```