Еще один домашний медиасервер на базе Docker

в 11:13, , рубрики: docker, docker-compose, linux, mediaserver, plex, torrent, Ubuntu, хранение данных, хранилища данных

Добрый день Хабр. На написание этой статьи меня сподвигло закрытие довольно известных в UA-IX ресурсов ex.ua и fs.to. Поскольку доблестные правоохранители не озаботились предоставлением какой-либо достойной альтернативы, было принято решение взять процесс в свои руки, к тому же давно хотелось организовать домашнее хранилище/файлопомойку не зависящее от внешних провайдеров. В процессе реализации было перепробовано довольно много разных систем, но в итоге все выстроилось именно так, а не иначе. Мнение субъективное, реализация доступная. Сама статья рассчитана на новичков которым необходимо просто работающее решение, или на тех кто задумался о своем медиасервере, но еще не определился с реализацией.

Итак решение принято, начнем.

Железо

Критерии выбора были достаточно простыми: компактность, нормальная работа с WiFi, тишина. После изучения рынка железа, выбор которого сейчас дает самые широкие возможности, осталось несколько кандидатов. А именно — HP MicroServer G8, ASUS VivoMini VC65R, и само собой Rapsberry Pi 3.

После изучения доступного софта для создания медиасервера было решено было остановиться на ASUS VivoMini VC65R, так как Rapsberry, который базируется на ARM, не поддерживает транскодинг, а доступные варианты MicroServer были укомплектованы достаточно старым Celeron G1610T, который мог не обеспечить достаточной производительности. Итак, был приобретен VC65R и 4хSamsung ST1500LM006 1.5TB.

Операционная система

С одной стороны — на рынке присутствует довольно большое количество специализированных дистрибутивов, как то FreeNAS, NAS4Free, OpenMediaVault, Rockstor. С другой — хотелось бы полностью контролировать систему, и по возможности не использовать ненужные сервисы. Так что выбор остановился на Ubuntu Server 16.04 LTS. В целом — получившаяся конфигурация благодаря Docker не зависит от операционной системы, но некоторые сервисы так или иначе завязаны на дистрибутив, так что если вам захочется повторить данную конфигурацию — имейте это в виду.

Для организации файлов была выбрана следующая структура директорий:

/data — отдельный logical volume для хранения медиа данных и бекапов
/data/Media — медиаданные
/data/TimeMachine — бекапы TimeMachine
/opt/mediacenter — отдельный logical volume для хранения данных сервисов

Сам процесс установки описывать не стоит, так как он зависит от того дистрибутива который вы выберете, единственный нюанс в том, что поскольку было бы неплохо работать с файлами не беспокоясь о разрешениях доступа предоставим нашему пользователю доступ с помощью setfacl

apt-get install acl
setfacl -Rm u:<username>:rwx /data
setfacl -Rm d:u:<username>:rwx /data
setfacl -Rm u:<username>:rwx /opt/mediacenter
setfacl -Rm d:u:<username>:rwx /opt/mediacenter

Программное обеспечение

Итак, какие требования мы можем выставить к подобному медиасерверу, с учетом того что присутствует широкий ряд техники под Mac OS X, iOS, Windows, и Android:

— Хранилище для TimeMachine + общий ресурс для Mac OS X
— Общий ресурс для Windows
— Торрент клиент
— Мониторинг обновляющихся торрентов
— Персональное облачное хранилище
— Медиасервер

Начнем по порядку.

Хранилище для TimeMachine + общий ресурс для Mac OS X

Установка весьма тривиальна, как впрочем и все описанное далее.

apt-get install netatalk avahi-daemon

С помощью этой команды мы устанавливаем open source реализации AppleTalk протокола и Bonjour. Теперь осталось только экспортировать директорию /data/Media как доступный общий ресурс, и директорию /data/TimeMachine как доступную для TimeMachine backup.

Для этого отредактируем файл /etc/netatalk/AppleVolumes.default добавив в конце

/data/TimeMachine "TimeMachine" cnidscheme:dbd options:tm,upriv,usedots volsizelimit:300000 allow:<username>
/data/Media "Media" cnidscheme:dbd options:upriv,usedots dperm:0776 fperm:0666 allow:<username>

Для ограничения доступного для TimeMachine места добавлена опция

volsizelimit:300000

Для ограничения доступа для конкретного пользователя добавлена опция

allow:<username>

Общий ресурс для Windows

Поскольку в моей сети присутствует Windows мне нужна также и Samba. Здесь все сверх просто, благо руководств по использованию Samba в сети очень много. Тем не менее для полноты статьи:

apt-get install samba smbclient

И содержимое smb.conf

/etc/samba/smb.conf

[global]
   workgroup = WORKGROUP
   server string = Media server
   netbios name = media
   dns proxy = no
   log file = /var/log/samba/log.%m
   max log size = 1000
   panic action = /usr/share/samba/panic-action %d
   server role = standalone server
   passdb backend = tdbsam
   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Entersnews*spassword:* %nn *Retypesnews*spassword:* %nn *passwordsupdatedssuccessfully* .
   pam password change = yes
   map to guest = bad user
   usershare allow guests = no
   security = user
   unix extensions = no
   wide links = yes
   follow symlinks = yes
   load printers = no
   show add printer wizard = no
   printcap name = /dev/null
   disable spoolss = yes
   hide dot files = yes
   server signing = auto
   name resolve order = bcast host
   max protocol = SMB2_10

[Media]
   path = /data/Media
   valid users = <username>
   guest ok = no
   writable = yes
   browsable = yes
   hide files = /lost+found/Network Trash Folder/Temporary Items/.Apple*/.DS*/

Торрент клиент и Мониторинг обновляющихся торрентов и Персональное облачное хранилище и Медиасервер

Эти требования было решено объединить в одну часть, так как все это реализовано на базе docker compose, и по сути представляют собой один файл благодаря которому все можно стартовать одной командой. Установку docker и docker-compose я пожалуй опущу, так как они не представляют собой ничего сложного и достаточно описаны на сайте docker.

Начнем с выбранного программного обеспечения:

В качестве торрент клиента будем использовать относительно легковесный Transmission.

Для мониторинга обновляющихся торрентов было выбрано на тестирование два решения специализирующихся на русскоязычном сегменте сети, а именно TorrentMonitor и Monitorrent. Сейчас они оба работают на моем медиасервере, и в результате останется тот что покажет себя наиболее оптимальным образом. Кстати, авторы обоих решений присутствуют на Хабре.

В качестве персонального дропбокса будем использовать ownCloud. Я не уверен что это именно то решение которое подойдет мне на все сто процентов, но на данном этапе оно меня устраивает. В качестве альтернативы можно использовать NextCloud, Pydio или Seafile. На самом деле выбор гораздо шире и на рынке представлено довольно много достойных альтернатив.

В качестве медиасервера будем использовать Plex. Также была апробирована альтернатива под названием Emby, но мне она не пришлась по душе.

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

Dockerfile

#------------------------------------------------------------------------------
# Set the base image for subsequent instructions:
#------------------------------------------------------------------------------

FROM alpine:3.4
MAINTAINER Andrey Aleksandrov <alex.demion@gmail.com>

#------------------------------------------------------------------------------
# Install:
#------------------------------------------------------------------------------

RUN apk update 
    && apk upgrade 
    && apk --no-cache add --update -t deps wget unzip sqlite 
    && apk --no-cache add nginx php5-common php5-cli php5-fpm php5-curl php5-sqlite3 php5-pdo_sqlite php5-iconv php5-json php5-ctype php5-zip 
    && wget -q http://korphome.ru/torrent_monitor/tm-latest.zip -O /tmp/tm-latest.zip 
    && unzip /tmp/tm-latest.zip -d /tmp/ 
    && mkdir -p /data/htdocs/db /run/nginx 
    && mv /tmp/TorrentMonitor-master/* /data/htdocs 
    && cat /data/htdocs/db_schema/sqlite.sql | sqlite3 /data/htdocs/db_schema/tm.sqlite 
    && apk del --purge deps; rm -rf /tmp/* /var/cache/apk/*

#------------------------------------------------------------------------------
# Populate root file system:
#------------------------------------------------------------------------------

ADD rootfs /

#------------------------------------------------------------------------------
# Expose ports and entrypoint:
#------------------------------------------------------------------------------
VOLUME ["/data/htdocs/db", "/data/htdocs/torrents"]
WORKDIR /
EXPOSE 80
ENTRYPOINT ["/init"]

Сам репозиторий лежит здесь

Итак, образы готовы, напишем docker-compose.yml

/opt/mediacenter/docker-compose.yml


version: '2'
services:
# Plex media server
  plex:
    container_name: plex
    hostname: plex
    image: plexinc/pms-docker:plexpass
    restart: unless-stopped
    ports:
      - 32400:32400/tcp
      - 33400:33400/tcp
      - 3005:3005/tcp
      - 8324:8324/tcp
      - 32469:32469/tcp
      - 1900:1900/udp
      - 32410:32410/udp
      - 32412:32412/udp
      - 32413:32413/udp
      - 32414:32414/udp
    environment:
      - TZ=Europe/Kiev
      - ADVERTISE_IP=http://<YOUR ADDRESS>:32400/
      - PLEX_UID=1000
      - PLEX_GID=1000
    volumes:
      - /opt/mediacenter/plex-config:/config
      - /opt/mediacenter/plex-transcode:/transcode
      - /data/Media:/Media

# Monitoring of torrent sites for update
  torrentmonitor:
    container_name: torrentmonitor
    hostname: torrentmonitor
    image: aldemion/torrentmonitor-alpine
    ports:
      - 8080:80/tcp
    volumes:
      - /opt/mediacenter/torrentmonitor-torrents:/data/htdocs/torrents
      - /opt/mediacenter/torrentmonitor-db:/data/htdocs/db
    links:
      - transmission

  monitorrent:
    container_name: monitorrent
    hostname: monitorrent
    image: werwolfby/alpine-monitorrent
    ports:
      - 6687:6687/tcp
    volumes:
      - /opt/mediacenter/monitorrent-db:/db
    environment:
      - MONITORRENT_DB_PATH=/db/monitorrent.db
    links:
      - transmission

# Torrent client
  transmission:
    container_name: transmission
    hostname: transmission
    image: linuxserver/transmission
    ports:
      - 9091:9091/tcp
      - 51413:51413/tcp
      - 51413:51413/udp
    volumes:
      - /opt/mediacenter/transmission-config:/config
      - /data/Media/Downloads:/downloads
      - /data/Media/Torrents:/watch
    environment:
      - PGID=1000
      - PUID=1000
      - TZ=Europe/Kiev

# Personal file share
  owncloud:
    container_name: owncloud
    hostname: owncloud
    image: owncloud
    ports:
      - 8081:80/tcp
    volumes:
      - /opt/mediacenter/owncloud-config:/var/www/html/config
      - /opt/mediacenter/owncloud-apps:/var/www/html/apps
      - /data/Media/ownCloud:/var/www/html/data
      - /data/Media/:/Media
    links:
      - mysql

# Database server
  mysql:
    container_name: mysql
    hostname: mysql
    image: mariadb
    environment:
      - MYSQL_ROOT_PASSWORD=<mysql password>
    volumes:
      - /opt/mediacenter/mariadb-data:/var/lib/mysql

Дополнительные действия

При первом запуске ownCloud потребуется ряд действий для создания базы данных.
Нужно выбрать «Storage & database» --> «Configure the database» --> «MySQL/MariaDB»
Database user: root
Database password: P@ssw0rd
Database name: любое
Database host: mysql

Пароли по умолчанию

TorrentMonitor: torrentmonitor
Monitorrent: monitorrent

Немного пояснений по спорным вопросам.

Директория /opt/mediacenter/torrentmonitor-torrents вынесена в отдельный маунтпоинт а не слинкована с /data/Media/Torrents так как нам необходимо избежать дубликатов торрентов. Transmission настроен на мониторинг директории /data/Media/Torrents, соответственно все .torrent файлы попавшие в эту директорию будут им обработаны. Поскольку нам необходимо чтобы TorrentMonitor работал с Transmission через RPC нам не нужно сохранение .torrent файлов в ту директорию где Transmission их обработает.

Теперь необходимо создать структуру директорий для хранения метаданных и медиаданных:

mkdir -p /opt/mediacenter/{mariadb-data,monitorrent-db,owncloud-apps,owncloud-config,plex-config,plex-transcode,torrentmonitor-db,torrentmonitor-torrents,transmission-config}
mkdir -p /data/Media/{Anime,Books,Documents,Downloads,Games,Home Videos,Movies,Music,ownCloud,Photos,Torrents,TV Shows}

И для полного удобства создадим systemd сервис

/etc/systemd/system/mediacenter.service

[Unit]
Description=Mediacenter Service
After=docker.service
Requires=docker.service

[Service]
ExecStartPre=-/usr/local/bin/docker-compose -f /opt/mediacenter/docker-compose.yml down
ExecStart=/usr/local/bin/docker-compose -f /opt/mediacenter/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /opt/mediacenter/docker-compose.yml stop

[Install]
WantedBy=multi-user.target

Теперь выполним:

systemctl daemon-reload
systemctl enable mediacenter
systemctl start mediacenter

Docker compose выкачает образы с docker hub и запустит наши сервисы. Теперь они будут доступны по адресам:

Plex: http://<YOUR_IP>:32400
Transmission: http://<YOUR_IP>:9091
TorrentMonitor: http://<YOUR_IP>:8080
Monitorrent: http://<YOUR_IP>:6687
ownCloud: http://<YOUR_IP>:8081

Ну что же, вроде все запустилось и работает. Теперь можно начать тестирование, например сохранить .torrent файл в директорию Torrents. Transmission должен начать закачку, и в скором времени выкачанные файлы появятся в директории Downloads/complete.

Теперь остался последний шаг, облегчить медиасерверу работу по распознаванию скачанных фильмов/сериалов/музыки. Для этого используем отличный продукт под названием FileBot который умеет переименовывать файлы базируясь на информации из открытых источников вроде TheTVDB.

Установка проста:

apt-get install openjdk-8-jdk mediainfo openjfx
wget -O filebot_4.7.5_amd64.deb http://downloads.sourceforge.net/project/filebot/filebot/FileBot_4.7.5/filebot_4.7.5_amd64.deb?r=http%3A%2F%2Fwww.filebot.net%2F&ts=1482609251&use_mirror=heanet
dpkg -i filebot_4.7.5_amd64.deb

Ну и для удобства переименования напишем пару алиасов:

~/.bash_aliases

alias anime-test='filebot --action test --conflict skip --format "{plex}" --db AniDB -r -non-strict --output /data/Media -rename'
alias series-test='filebot --action test --conflict skip --format "{plex}" --db TheTVDB -r -non-strict --output /data/Media -rename'
alias movie-test='filebot --action test --conflict skip --format "{plex}" --db TheMovieDB -r -non-strict --output /data/Media -rename'
alias music-test='filebot --action test --conflict skip --format "{plex}" --db AcoustID -r -non-strict --output /data/Media -rename'
alias anime-hardlink='filebot --action hardlink --conflict skip --format "{plex}" --db AniDB -r -non-strict --output /data/Media -rename'
alias series-hardlink='filebot --action hardlink --conflict skip --format "{plex}" --db TheTVDB -r -non-strict --output /data/Media -rename'
alias movie-hardlink='filebot --action hardlink --conflict skip --format "{plex}" --db TheMovieDB -r -non-strict --output /data/Media -rename'
alias anime-move='filebot --action move --conflict skip --format "{plex}" --db AniDB -r -non-strict --output /data/Media -rename'
alias series-move='filebot --action move --conflict skip --format "{plex}" --db TheTVDB -r -non-strict --output /data/Media -rename'
alias movie-move='filebot --action move --conflict skip --format "{plex}" --db TheMovieDB -r -non-strict --output /data/Media -rename'
alias music-move='filebot --action move --conflict skip --format "{plex}" --db AcoustID -r -non-strict --output /data/Media -rename'

Теперь, например для работы с сериалом можно использовать команду:

series-test <PATH_TO_SERIES_DIR>

Если результат работы нас не устраивает, можем модифицировать условия поиска с помощью опций --q и --filter. Если же результат работы нас устроит — выполняем команду:

series-move <PATH_TO_SERIES_DIR>

В результате файлы нашего сериала окажутся в директории /data/Media/TV Shows/Series Name. Ну и если мы работаем с онгоингом или хотим продолжить раздачу можно выполнить команду:

series-hardlink <PATH_TO_SERIES_DIR>

В результате в директории /data/Media/TV Shows/Series Name окажутся хардлинки.

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

Автор: AlDemion

Источник

Поделиться

* - обязательные к заполнению поля