
Another home media server based on Docker
Good afternoon, Habr. To write this article, I was prompted by the closure of the rather well-known ex.ua and fs.to resources in UA-IX. Since the valiant law enforcement officers did not bother to provide any worthy alternative, it was decided to take the process into their own hands, besides, I had long wanted to organize a home storage / file storage independent of external providers. In the process of implementation, quite a lot of different systems were tried, but in the end everything was built just like that, and not otherwise. The opinion is subjective, the implementation is affordable. The article itself is designed for beginners who just need a working solution, or for those who are thinking about their media server, but have not yet decided on the implementation.
So the decision is made, let's begin.
The selection criteria were quite simple: compact, normal operation with WiFi, silence. After studying the iron market, the choice of which now gives the widest opportunities, several candidates remained. Namely, the HP MicroServer G8, ASUS VivoMini VC65R, and Rapsberry Pi 3 itself.
After studying the available software for creating a media server, it was decided to stop at the ASUS VivoMini VC65R, since Rapsberry, which is based on ARM, does not support transcoding, but the available options MicroServer was equipped with a fairly old Celeron G1610T, which might not provide enough performance. So, VC65R and 4x Samsung ST1500LM006 1.5TB were acquired.
On the one hand, there are a rather large number of specialized distributions on the market, such as FreeNAS, NAS4Free, OpenMediaVault, Rockstor. On the other hand, I would like to fully control the system, and, if possible, not use unnecessary services. So the choice was limited to Ubuntu Server 16.04 LTS. In general, the resulting configuration thanks to Docker does not depend on the operating system, but some services are somehow tied to the distribution, so if you want to repeat this configuration, keep this in mind.
To organize the files, the following directory structure was selected:
The installation process itself is not worth describing, since it depends on the distribution you choose, the only caveat is that since it would be nice to work with files without worrying about access permissions, we will give our user access using setfacl
So, what requirements can we set for such a media server, given the fact that there is a wide range of equipment for Mac OS X, iOS, Windows, and Android:
- Storage for TimeMachine + share for Mac OS X
- Share for Windows
- Torrent client
- Monitoring of updated torrents
- Personal cloud storage
- Media server
Let's start in order.
Installation is very trivial, as well as everything described below.
With this command, we install open source implementations of the AppleTalk protocol and Bonjour. Now all that remains is to export the / data / Media directory as an available shared resource, and the / data / TimeMachine directory as available for TimeMachine backup.
To do this, edit the file /etc/netatalk/AppleVolumes.default adding at the end
An option has been added to limit the space available for TimeMachine.
An option has been added to restrict access for a specific user.
Since there is Windows on my network, I also need Samba. Everything is super simple here, there are a lot of guides for using Samba on the network. However, to complete the article:
And the contents of smb.conf
It was decided to combine these requirements into one part, since all this is implemented on the basis of docker compose, and in fact they are one file thanks to which everything can be started with one command. I’ll probably omit the installation of docker and docker-compose, since they are not complicated and are described quite well on the docker website.
Let's start with the selected software:
As a torrent client, we will use a relatively lightweight Transmission.
To monitor updated torrents, two solutions specializing in the Russian-language segment of the network were selected for testing, namely TorrentMonitor and Monitorrent. Now they both work on my media server, and as a result, the one that will show itself in the most optimal way will remain. By the way, the authors of both solutions are present on Habré.
We will use our ownCloud as a personal dropbox. I'm not sure that this is exactly the solution that will suit me one hundred percent, but at this stage it suits me. Alternatively, you can use NextCloud, Pydio, or Seafile. In fact, the choice is much wider and there are quite a few worthy alternatives on the market.
We will use Plex as a media server. An alternative called Emby was also tested, but I didn’t like it.
For all of the above, ready-made docker images are already present, the only thing I did not like was the image of TorrentMonitor, so it was decided to write my own.
The repository itself is here
UPD: My pull request to nawa / torrentmonitor was stink, so the article was updated.
So, the images are ready, let's write docker-compose.yml
UPD2: For those who do not have DLNA, you can comment out the ports section and uncomment network_mode: host
Now you need to create a directory structure for storing metadata and media data:
And for complete convenience, create a systemd service
Now do:
Docker compose will download images from the docker hub and launch our services. Now they will be available at:
Plex : http: //: 32400
Transmission : http: //: 9091
TorrentMonitor : http: //: 8080
Monitorrent : http: //: 6687
ownCloud : http: //: 8081
Well, it seems everything has started and works. Now you can start testing, for example, save the .torrent file to the Torrents directory. Transmission should start the download, and soon the downloaded files will appear in the Downloads / complete directory.
Now the last step remains, to facilitate the work of the media server in recognizing downloaded movies / TV shows / music. To do this, we use an excellent product called FileBot which can rename files based on information from open sources like TheTVDB.
Installation is simple:
Well, for the convenience of renaming, we write a couple of aliases:
Now, for example, to work with the series, you can use the command:
If the result of the work does not suit us, we can modify the search conditions using the --q and --filter options. If the result of work suits us, we execute the command:
As a result, the files of our series will be in the directory / data / Media / TV Shows / Series Name. Well, if we work with ongaming or want to continue distribution, you can run the command:
As a result, the hardlinks appear in the / data / Media / TV Shows / Series Name directory.
In general, such a trivial way to quickly and painlessly make your own media server.
So the decision is made, let's begin.
Iron
The selection criteria were quite simple: compact, normal operation with WiFi, silence. After studying the iron market, the choice of which now gives the widest opportunities, several candidates remained. Namely, the HP MicroServer G8, ASUS VivoMini VC65R, and Rapsberry Pi 3 itself.
After studying the available software for creating a media server, it was decided to stop at the ASUS VivoMini VC65R, since Rapsberry, which is based on ARM, does not support transcoding, but the available options MicroServer was equipped with a fairly old Celeron G1610T, which might not provide enough performance. So, VC65R and 4x Samsung ST1500LM006 1.5TB were acquired.
operating system
On the one hand, there are a rather large number of specialized distributions on the market, such as FreeNAS, NAS4Free, OpenMediaVault, Rockstor. On the other hand, I would like to fully control the system, and, if possible, not use unnecessary services. So the choice was limited to Ubuntu Server 16.04 LTS. In general, the resulting configuration thanks to Docker does not depend on the operating system, but some services are somehow tied to the distribution, so if you want to repeat this configuration, keep this in mind.
To organize the files, the following directory structure was selected:
/ data - a separate logical volume for storing media data and backups
/ data / Media - media data
/ data / TimeMachine - backups TimeMachine
/ opt / mediacenter - a separate logical volume for storing service data
The installation process itself is not worth describing, since it depends on the distribution you choose, the only caveat is that since it would be nice to work with files without worrying about access permissions, we will give our user access using setfacl
apt-get install acl
setfacl -Rm u::rwx /data
setfacl -Rm d:u::rwx /data
setfacl -Rm u::rwx /opt/mediacenter
setfacl -Rm d:u::rwx /opt/mediacenter
Software
So, what requirements can we set for such a media server, given the fact that there is a wide range of equipment for Mac OS X, iOS, Windows, and Android:
- Storage for TimeMachine + share for Mac OS X
- Share for Windows
- Torrent client
- Monitoring of updated torrents
- Personal cloud storage
- Media server
Let's start in order.
Storage for TimeMachine + share for Mac OS X
Installation is very trivial, as well as everything described below.
apt-get install netatalk avahi-daemon
With this command, we install open source implementations of the AppleTalk protocol and Bonjour. Now all that remains is to export the / data / Media directory as an available shared resource, and the / data / TimeMachine directory as available for TimeMachine backup.
To do this, edit the file /etc/netatalk/AppleVolumes.default adding at the end
/data/TimeMachine "TimeMachine" cnidscheme:dbd options:tm,upriv,usedots volsizelimit:300000 allow:
/data/Media "Media" cnidscheme:dbd options:upriv,usedots dperm:0776 fperm:0666 allow:
An option has been added to limit the space available for TimeMachine.
volsizelimit:300000
An option has been added to restrict access for a specific user.
allow:
Share for Windows
Since there is Windows on my network, I also need Samba. Everything is super simple here, there are a lot of guides for using Samba on the network. However, to complete the article:
apt-get install samba smbclient
And the contents of 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 =
guest ok = no
writable = yes
browsable = yes
hide files = /lost+found/Network Trash Folder/Temporary Items/.Apple*/.DS*/
Torrent Client and Monitoring Updating Torrents and Personal Cloud Storage and Media Server
It was decided to combine these requirements into one part, since all this is implemented on the basis of docker compose, and in fact they are one file thanks to which everything can be started with one command. I’ll probably omit the installation of docker and docker-compose, since they are not complicated and are described quite well on the docker website.
Let's start with the selected software:
As a torrent client, we will use a relatively lightweight Transmission.
To monitor updated torrents, two solutions specializing in the Russian-language segment of the network were selected for testing, namely TorrentMonitor and Monitorrent. Now they both work on my media server, and as a result, the one that will show itself in the most optimal way will remain. By the way, the authors of both solutions are present on Habré.
We will use our ownCloud as a personal dropbox. I'm not sure that this is exactly the solution that will suit me one hundred percent, but at this stage it suits me. Alternatively, you can use NextCloud, Pydio, or Seafile. In fact, the choice is much wider and there are quite a few worthy alternatives on the market.
We will use Plex as a media server. An alternative called Emby was also tested, but I didn’t like it.
For all of the above, ready-made docker images are already present, the only thing I did not like was the image of TorrentMonitor, so it was decided to write my own.
Dockerfile
#------------------------------------------------------------------------------
# Set the base image for subsequent instructions:
#------------------------------------------------------------------------------
FROM alpine:3.4
MAINTAINER Andrey Aleksandrov
#------------------------------------------------------------------------------
# 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"]
The repository itself is here
UPD: My pull request to nawa / torrentmonitor was stink, so the article was updated.
So, the images are ready, let's write docker-compose.yml
UPD2: For those who do not have DLNA, you can comment out the ports section and uncomment 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://: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=
volumes:
- /opt/mediacenter/mariadb-data:/var/lib/mysql
Additional Actions
The first time you start your ownCloud, you will need a series of steps to create the database.
You need to select “Storage & database” -> “Configure the database” -> “MySQL / MariaDB”
Database user: root
Database password: P @ ssw0rd
Database name: any
Database host: mysql
You need to select “Storage & database” -> “Configure the database” -> “MySQL / MariaDB”
Database user: root
Database password: P @ ssw0rd
Database name: any
Database host: mysql
Default passwords
TorrentMonitor: torrentmonitor
Monitorrent: monitorrent
Monitorrent: monitorrent
A little explanation on controversial issues.
The / opt / mediacenter / torrentmonitor-torrents directory has been moved to a separate mountpoint and not linked to / data / Media / Torrents since we need to avoid duplicate torrents. Transmission is configured to monitor the / data / Media / Torrents directory, respectively, all .torrent files that fall into this directory will be processed by it. Since we need TorrentMonitor to work with Transmission via RPC, we don’t need to save .torrent files to the directory where Transmission will process them.
Now you need to create a directory structure for storing metadata and media data:
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}
And for complete convenience, create a systemd service
/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
Now do:
systemctl daemon-reload
systemctl enable mediacenter
systemctl start mediacenter
Docker compose will download images from the docker hub and launch our services. Now they will be available at:
Plex : http: //
Transmission : http: //
TorrentMonitor : http: //
Monitorrent : http: //
ownCloud : http: //
Well, it seems everything has started and works. Now you can start testing, for example, save the .torrent file to the Torrents directory. Transmission should start the download, and soon the downloaded files will appear in the Downloads / complete directory.
Now the last step remains, to facilitate the work of the media server in recognizing downloaded movies / TV shows / music. To do this, we use an excellent product called FileBot which can rename files based on information from open sources like TheTVDB.
Installation is simple:
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
Well, for the convenience of renaming, we write a couple of aliases:
~ / .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'
Now, for example, to work with the series, you can use the command:
series-test
If the result of the work does not suit us, we can modify the search conditions using the --q and --filter options. If the result of work suits us, we execute the command:
series-move
As a result, the files of our series will be in the directory / data / Media / TV Shows / Series Name. Well, if we work with ongaming or want to continue distribution, you can run the command:
series-hardlink
As a result, the hardlinks appear in the / data / Media / TV Shows / Series Name directory.
In general, such a trivial way to quickly and painlessly make your own media server.