Добрый день Хабр. На написание этой статьи меня сподвигло закрытие довольно известных в 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 не зависит от операционной системы, но некоторые сервисы так или иначе завязаны на дистрибутив, так что если вам захочется повторить данную конфигурацию — имейте это в виду.
Для организации файлов была выбрана следующая структура директорий:
Сам процесс установки описывать не стоит, так как он зависит от того дистрибутива который вы выберете, единственный нюанс в том, что поскольку было бы неплохо работать с файлами не беспокоясь о разрешениях доступа предоставим нашему пользователю доступ с помощью setfacl
Итак, какие требования мы можем выставить к подобному медиасерверу, с учетом того что присутствует широкий ряд техники под Mac OS X, iOS, Windows, и Android:
— Хранилище для TimeMachine + общий ресурс для Mac OS X
— Общий ресурс для Windows
— Торрент клиент
— Мониторинг обновляющихся торрентов
— Персональное облачное хранилище
— Медиасервер
Начнем по порядку.
Установка весьма тривиальна, как впрочем и все описанное далее.
С помощью этой команды мы устанавливаем open source реализации AppleTalk протокола и Bonjour. Теперь осталось только экспортировать директорию /data/Media как доступный общий ресурс, и директорию /data/TimeMachine как доступную для TimeMachine backup.
Для этого отредактируем файл /etc/netatalk/AppleVolumes.default добавив в конце
Для ограничения доступного для TimeMachine места добавлена опция
Для ограничения доступа для конкретного пользователя добавлена опция
Поскольку в моей сети присутствует Windows мне нужна также и Samba. Здесь все сверх просто, благо руководств по использованию Samba в сети очень много. Тем не менее для полноты статьи:
И содержимое smb.conf
Эти требования было решено объединить в одну часть, так как все это реализовано на базе docker compose, и по сути представляют собой один файл благодаря которому все можно стартовать одной командой. Установку docker и docker-compose я пожалуй опущу, так как они не представляют собой ничего сложного и достаточно описаны на сайте docker.
Начнем с выбранного программного обеспечения:
В качестве торрент клиента будем использовать относительно легковесный Transmission.
Для мониторинга обновляющихся торрентов было выбрано на тестирование два решения специализирующихся на русскоязычном сегменте сети, а именно TorrentMonitor и Monitorrent. Сейчас они оба работают на моем медиасервере, и в результате останется тот что покажет себя наиболее оптимальным образом. Кстати, авторы обоих решений присутствуют на Хабре.
В качестве персонального дропбокса будем использовать ownCloud. Я не уверен что это именно то решение которое подойдет мне на все сто процентов, но на данном этапе оно меня устраивает. В качестве альтернативы можно использовать NextCloud, Pydio или Seafile. На самом деле выбор гораздо шире и на рынке представлено довольно много достойных альтернатив.
В качестве медиасервера будем использовать Plex. Также была апробирована альтернатива под названием Emby, но мне она не пришлась по душе.
Для всего вышеперечисленного уже присутствуют готовые образы docker, единственное что мне не понравился образ TorrentMonitor, так что было решено написать свой.
Сам репозиторий лежит здесь
UPD: Мой пулл реквест в nawa/torrentmonitor был смерджен, поэтому статья обновлена.
Итак, образы готовы, напишем docker-compose.yml
UPD2: Для тех у кого не работает DLNA можно заккоментировать секцию ports и раскомментировать network_mode: host
Теперь необходимо создать структуру директорий для хранения метаданных и медиаданных:
И для полного удобства создадим systemd сервис
Теперь выполним:
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.
Установка проста:
Ну и для удобства переименования напишем пару алиасов:
Теперь, например для работы с сериалом можно использовать команду:
Если результат работы нас не устраивает, можем модифицировать условия поиска с помощью опций --q и --filter. Если же результат работы нас устроит — выполняем команду:
В результате файлы нашего сериала окажутся в директории /data/Media/TV Shows/Series Name. Ну и если мы работаем с онгоингом или хотим продолжить раздачу можно выполнить команду:
В результате в директории /data/Media/TV Shows/Series Name окажутся хардлинки.
В общем такой вот тривиальный способ как быстро и безболезненно сделать свой медиасервер.
Итак решение принято, начнем.
Железо
Критерии выбора были достаточно простыми: компактность, нормальная работа с 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 = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
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"]
Сам репозиторий лежит здесь
UPD: Мой пулл реквест в nawa/torrentmonitor был смерджен, поэтому статья обновлена.
Итак, образы готовы, напишем docker-compose.yml
UPD2: Для тех у кого не работает DLNA можно заккоментировать секцию ports и раскомментировать network_mode: host
/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
# If you need DLNA you need to comment ports section and use host network mode.
#network_mode: host
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: nawa/torrentmonitor
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
Нужно выбрать «Storage & database» --> «Configure the database» --> «MySQL/MariaDB»
Database user: root
Database password: P@ssw0rd
Database name: любое
Database host: mysql
Пароли по умолчанию
TorrentMonitor: torrentmonitor
Monitorrent: monitorrent
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
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'
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 окажутся хардлинки.
В общем такой вот тривиальный способ как быстро и безболезненно сделать свой медиасервер.