Guide: install miniDLNA in a jail and patch with custom icons

Phil1295

Explorer
Joined
Sep 20, 2020
Messages
79
This is a detailed step by step to properly setup miniDLNA in a jail, patch the sources with custom icons, setup the media libraries and properly setup a service daemon script with a non destructive rescan

Enjoy

Code:
# *************************************************************
# Requirements on TrueNAS main system:
# *************************************************************
# First, I assume the media library to stream is in TrueNAS main system under below datasets:
# - /mnt/my_media/tank/family
# - /mnt/my_media/tank/movies
# - /mnt/my_media/tank/children
# - /mnt/data/tank/shared
# Note: the media datasets can be either unix or windows SMB shares
# In TrueNAS main system, we have created a dedicated user "minidlna" UID 1008, member of a group "smb_dlna" GID 1019
# Note: choose the UID/GID that you like, but later, we will need to create the same user/group IDs in the jail
# The group "smb_dlna" has read only permissions on each of the above media datasets under "/mnt/my_media/tank/"

# For easier maintenance, I advise storing the minidlna catalog database and log files in a dataset outside of the jail directories
# That way, when the jail is destroyed, the database catalog doesn't need to be rebuilt which is a time and resource consuming operation
# I assume a UNIX type dataset under main TrueNAS system "/mnt/data/tank/common"
# In TrueNAS GUI, create a user "dlna" UID 933, member of group "dlna" GID 933
# Note: you must use the 933 IDs, because these are the IDs created by default when installing minidlna
#       We can also use teh same minidlna user created previously, but I prefer distinct users for teh lib access and running the daemon
# It is the user running the minidlna daemon
# In shell, we create the database and log directories for minidlna
root@truenas:~ #
mkdir -p /mnt/data/tank/common/minidlna/db
chown dlna:dlna /mnt/data/tank/common/minidlna/db
chmod 755 /mnt/data/tank/common/minidlna/db

# The log directory can be set to root:wheel
mkdir -p /mnt/data/tank/common/minidlna/log
chown root:wheel /mnt/data/tank/common/minidlna/log
chmod 755 /mnt/data/tank/common/minidlna/log


# *************************************************************
# First step: Setup a jail named "streaming":
# *************************************************************
# - Create a jail in TrueNAS GUI
# - Assign the network and IP on the subnet where your receiving devices reside
#   Note: DLNA multicast traffic is limited to teh same subnet/VLAN, so the jail and media clients must be on teh same subnet

# Add the jail mount point for the database and logs
    rw  /mnt/data/tank/common -> /mnt/data/iocage/jails/streaming/root/mnt/common

# Add the jail mount point for the media library
# Note: the media directories will be mounted under /media in jail
    ro  /mnt/data/tank/family       -> /mnt/data/iocage/jails/streaming/root/media/family
    ro  /mnt/my_media/tank/movies   -> /mnt/data/iocage/jails/streaming/root/media/movies
    ro  /mnt/my_media/tank/shared   -> /mnt/data/iocage/jails/streaming/root/media/shared
    ro  /mnt/my_media/tank/children -> /mnt/data/iocage/jails/streaming/root/media/children

# fstab result:
root@truenas:~ #
cat /mnt/data/iocage/jails/streaming/fstab
    /mnt/data/tank/common        /mnt/data/iocage/jails/streaming/root/mnt/common       nullfs  rw  0   0
    /mnt/data/tank/family        /mnt/data/iocage/jails/streaming/root/media/family     nullfs  ro  0   0
    /mnt/my_media/tank/movies    /mnt/data/iocage/jails/streaming/root/media/movies     nullfs  ro  0   0
    /mnt/my_media/tank/shared    /mnt/data/iocage/jails/streaming/root/media/shared     nullfs  ro  0   0
    /mnt/my_media/tank/children  /mnt/data/iocage/jails/streaming/root/media/children   nullfs  ro  0   0


# *************************************************************
# Jail: Add user/group permissions for the minidlna service
# *************************************************************
# In teh jail, we will add the group and user that will access the libraries
# Note: as stated above, this is not necessarily the same user running the mindlnad daemon

# - shell into the jail
root@truenas:~ #
iocage console streaming

# - notes about setting up the group and user
#   + username must exist on both host and jail
#   + username must have read rights on the media library IN THE HOST, either explicitely, or through a group membership (primary or auxiliary)
#   + username must be added to the jail, with THE SAME UID as in the host
#   + if username does not have an explicit read access to the media library on the host, but rather through a group membership:
#     then, the group with read access must also be added on the jail, with the same gid as in the host
#
#   NOTE: we can start minidlnad daemon as root and it will no more need the username setup in minidlna.conf or any host permissions
#         However, I do not recommend this for security reasons
#
# - create group "smb_dlna" with gid 1019 : it must exist on TrueNAS host AND have read access to each share we want to stream
root@streaming:~ #
pw groupadd smb_dlna -g 1019

# - create user "minidlna" uid 1008 : it must exist on TrueNAS host.
#   If user minidlna has no explicit read access in the host, the group "smb_dlna" must be either his primary or auxiliary group in the host
#   In the jail, we must make "smb_dlna" the PRIMARY group of user "minidlna"
pw useradd minidlna -d /nonexistent -s /usr/sbin/nologin -u 1008 -g 1019 -c "MiniDLNA"


# *************************************************************
# Install minidlna using pkg install
# *************************************************************
# This is the recommended first step because it installs latest version with all dependencies
# Note: we cannot patch the source to use custom icons in this method, so we do it later in next section
#
root@streaming:~ #
pkg update
pkg install minidlna

# [Optional] Force update with patched version having a TrueNAS icon instead of the FreeBSD ugly bad guy icon !
# - copy my patched pkg file to the jail under for example /mnt/common
root@streaming:/mnt/common #
pkg add -f minidlna-1.3.0_2,1-custom-icon.pkg


# *************************************************************
# [Optional] Compile minidlna from FreeBSD ports collection
# *************************************************************
# If you want to compile yourself the patched minidlna pkg with a custom icon, follow this section, else skip it

# We will use this method to create a custom binary pkg from ports collection source files
# We will patch the ports collection sources to use a custom icon
# Then, we will create a binary pkg from these patched latest sources
# The created binary pkg can be used to update the currently installed minidlna version

# Also, use this method if the ports collection has a newer version than pkg install

# Download/Update the ports collection
# - If it is the first time or we deleted the collections to spare space:
root@streaming:~ #
portsnap fetch && portsnap extract && portsnap update

# - If it is already extracted and not removed, just update the collection:
portsnap fetch update

# Download and extract the minidlna latest port source files
cd /usr/ports/net/minidlna/

root@streaming:/usr/ports/net/minidlna #
make clean     # if we previously installed without cleaning
make patch BATCH=yes

# Note: make patch will run automatically the below 3 commands:
make fetch     # fetches the distfile tarball
make extract   # extracts the distfile into the work directory
make patch     # applies any specific FreeBSD patches

# The port source files should be now located under "/usr/ports/net/minidlna/work/minidlna-4f6a473/"
# Note: replace minidlna-4f6a473 directory with current version name

# Edit source files to support custom icons:
# - get the patched icons.c and icons_custom.c files from my git: https://github.com/PhilZ-cwm6/minidlna-bsd
# - copy teh patched files to /mnt/common in jail
# - we replace the modded icons.c and icons_custom.c files
cp /mnt/common/icons.c /mnt/common/icons_custom.c /usr/ports/net/minidlna/work/minidlna-4f6a473/

# - [OPTIONAL]: edit the icons_custom.c file if you want to select different custom icons
#   Just uncomment only one line and comment the others. MINIDLNA_COL is for a default coloured minidlna icon
#   As is, teh patched files will use a TrueNAS icon
    #define TRUENAS
    /* #define FREENAS */
    /* #define FREENAS_3D */
    /* #define MINIDLNA_COL */

# - [OPTIONAL]: edit the icons.c file to revert to default FreeBSD icon
    /* #define USE_CUSTOM_ICON true */

# Compile and install the patched minidlna port:
# - to update an existing install:
root@streaming:/usr/ports/net/minidlna #
make reinstall BATCH=yes

# - to install for first time:
root@streaming:/usr/ports/net/minidlna #
make install BATCH=yes

# Create a pkg file for offline install on other jails
# - this creates a pkg binary file from our patched ports collection source with custom icons
root@streaming:/usr/ports/net/minidlna #
make package
    # --> /usr/ports/net/minidlna/work/pkg/minidlna-1.3.0_2,1.pkg

# Copy the created patched "minidlna-1.3.0_2,1.pkg" file to the streaming jail

# [OPTIONAL] Remove and cleanup the ports files if needed
root@streaming:/usr/ports/net/minidlna #
make clean
rm -v /var/db/portsnap/tag
rm -rvf /var/db/portsnap/files
rm -rvf /usr/ports/*

# Now, update minidlna installation in streaming jail with the patched package
# Note: we should already have did "pkg install minidlna" like above to install stock version with dependencies
# -f: to force update existing package of same version
root@streaming:~ #
pkg add -f minidlna-1.3.0_2,1.pkg


# *************************************************************
# Setup minidlna config and service to auto start with jail
# *************************************************************
# Ensure that "dlna" user and group were added by installer
# User "dlna" is the user running the minidlnad service. Database files need to be writable by the dlna user
# It is not the same user we setup under minidlna.conf that is used to access the media libraries
#
# - user:group dlna:dlna (933:933) should be created by minidlna installer
root@streaming:~ #
cat /etc/passwd | grep dlna
    dlna:*:933:933:DLNA Daemon:/nonexistent:/usr/sbin/nologin
    minidlna:*:1008:1019:MiniDLNA:/nonexistent:/usr/sbin/nologin

cat /etc/group | grep dlna
    dlna:*:933:
    smb_dlna:*:1019:

# - [OPTIONAL]: if the user:group dlna:dlna were not created:
#   The defaults for freeBSD port are dlna:dlna uid 933 and gid 933
root@streaming:~ #
pw groupadd dlna -g 933
pw useradd dlna -d /nonexistent -s /usr/sbin/nologin -u 933 -g 933 -c "DLNA Daemon"

# Edit minidlna service script
root@streaming:~ #
ee /usr/local/etc/rc.d/minidlna

# - Paste the code between the [start][end] tags
[CODE file start][minidlna]
#!/bin/sh
#
# $FreeBSD: head/net/minidlna/files/minidlna.in 323762 2013-07-26 23:25:40Z wg $
#
# PROVIDE: minidlna
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# Add the following line to /etc/rc.conf[.local] to enable minidlna:
#
# minidlna_enable="YES"

. /etc/rc.subr

name=minidlna
rcvar=minidlna_enable

load_rc_config $name

minidlna_enable=${minidlna_enable-"NO"}

# this is the user running the daemon, it doesn't need to exist on TrueNAS host
minidlna_uid=${minidlna_uid-"dlna"}
#minidlna_uid=${minidlna_uid-"root"}

# path to minidlnad binary
command=/usr/local/sbin/minidlnad

# file that holds the pid of the minidlna service when it is started
pidfile="/var/run/minidlna/minidlna.pid"

# config file defined in minidlna.conf
conf=/usr/local/etc/minidlna.conf

# database folder (only touched at startup. In all cases, the db folder set in minidlna.conf is used)
#dbfile=/var/db/minidlna
dbfile=/mnt/common/minidlna/db

# Add -r to do a non destructive scan on service start/restart
# Using -R would destroy all cached data and do a full scan again, which is very time consuming
command_args="-r -P $pidfile -u $minidlna_uid -f $conf"

# Create the $pidfile basedir and $dbfile folders (-d) with proper owner (-o)
# if folders exist, the owner is reset on every start of minidlna service
start_precmd="install -d -o $minidlna_uid ${pidfile%/*} $dbfile"

# On stopping the service, remove the pidfile
stop_postcmd="rm -f $pidfile"

extra_commands="rescan refresh"

# rescan command: destructive rescan (-R option) with rebuild of all the media library database
# a service restart is needed because minidlnad doesn't support -R without loading the daemon
rescan_cmd="rescan_minidlna"
rescan_minidlna() {
    echo 'Scanning media library and rebuilding database...'
    command_args="-R -P $pidfile -u $minidlna_uid -f $conf"
    if [ -f "$pidfile" ]; then
        run_rc_command restart
    else
        run_rc_command start
    fi
}

# refresh command: non destructive rescan (-r option) of the media lib
# Actually same as restart
refresh_cmd="refresh_minidlna"
refresh_minidlna() {
    echo 'Scanning media library for changes...'
    command_args="-r -P $pidfile -u $minidlna_uid -f $conf"
    if [ -f "$pidfile" ]; then
        run_rc_command restart
    else
        run_rc_command start
    fi
}

run_rc_command $1

[CODE file end][minidlna]

# - Set proper permissions
chmod 755 /usr/local/etc/rc.d/minidlna
chown root:wheel /usr/local/etc/rc.d/minidlna

# Edit minidlna config file
root@streaming:~ #
ee /usr/local/etc/minidlna.conf

# - Paste the code between the [start][end] tags
[CODE start minidlna.conf]
# port for HTTP (descriptions, SOAP, media transfer) traffic
port=8200

# network interfaces to serve, comma delimited (8 interfaces max)
#network_interface=eth0

# specify the user account name or uid to run as
user=minidlna

# set this to the directory you want scanned.
# * if you want multiple directories, you can have multiple media_dir= lines
# * if you want to restrict a media_dir to specific content types, you
#   can prepend the types, followed by a comma, to the directory:
#   + "A" for audio  (eg. media_dir=A,/home/jmaggard/Music)
#   + "V" for video  (eg. media_dir=V,/home/jmaggard/Videos)
#   + "P" for images (eg. media_dir=P,/home/jmaggard/Pictures)
#   + "PV" for pictures and video (eg. media_dir=PV,/home/jmaggard/digital_camera)
media_dir=/media

# set this to merge all media_dir base contents into the root container
# note: the default is no
#merge_media_dirs=no

# set this if you want to customize the name that shows up on your clients
friendly_name=TrueNAS miniDLNA

# set this if you would like to specify the directory where you want MiniDLNA to store its database and album art cache
#db_dir=/var/db/minidlna
db_dir=/mnt/common/minidlna/db

# set this if you would like to specify the directory where you want MiniDLNA to store its log file
#log_dir=/var/log
log_dir=/mnt/common/minidlna/log

# set this to change the verbosity of the information that is logged
# each section can use a different level: off, fatal, error, warn, info, or debug
#log_level=general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn

# this should be a list of file names to check for when searching for album art
# note: names should be delimited with a forward slash ("/")
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg

# set this to no to disable inotify monitoring to automatically discover new files
# note: the default is yes
inotify=yes

# set this to yes to enable support for streaming .jpg and .mp3 files to a TiVo supporting HMO
enable_tivo=no

# set this to beacon to use legacy broadcast discovery method
# defauts to bonjour if avahi is available
tivo_discovery=bonjour

# set this to strictly adhere to DLNA standards.
# * This will allow server-side downscaling of very large JPEG images,
#   which may hurt JPEG serving performance on (at least) Sony DLNA products.
strict_dlna=no

# default presentation url is http address on port 80
#presentation_url=http://www.mylan/index.php

# notify interval in seconds. default is 895 seconds.
notify_interval=900

# serial and model number the daemon will report to clients
# in its XML description
serial=12345678
model_number=1

# Override the uuid to run multiple instances
# uuid=550e8400-e29b-41d4-a716-446655440000

# specify the path to the MiniSSDPd socket
#minissdpdsocket=/var/run/minissdpd.sock

# use different container as root of the tree
# possible values:
#   + "." - use standard container (this is the default)
#   + "B" - "Browse Directory"
#   + "M" - "Music"
#   + "V" - "Video"
#   + "P" - "Pictures"
#   + Or, you can specify the ObjectID of your desired root container (eg. 1$F for Music/Playlists)
# if you specify "B" and client device is audio-only then "Music/Folders" will be used as root
#root_container=.

# always force SortCriteria to this value, regardless of the SortCriteria passed by the client
# note: you can prepend the sort criteria with "!" to alter the titles of the objects so that they
# will be alphanumerically sorted in the order you specify here, to work around clients that do their
# own alphanumeric sorting.
force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title

# maximum number of simultaneous connections
# note: many clients open several simultaneous connections while streaming
#max_connections=50

# set this to yes to allow symlinks that point outside user-defined media_dirs.
#wide_links=no

# enable subtitle support by default on unknown clients.
# note: the default is yes
#enable_subtitles=yes

[CODE end minidlna.conf]

# - Set proper permissions
chmod 644 /usr/local/etc/minidlna.conf
chown root:wheel /usr/local/etc/minidlna.conf

# Start minidlna daemon:
root@streaming:~ #
service minidlna onestart

# Display version
minidlnad -V

# Test the daemon
# - with a conservative scan -r
service minidlna onestop
service minidlna onestart
service minidlna onerefresh

# - with a destructive -R rescan
service minidlna onestop
service minidlna onerescan

# Enable daemon on jail boot
sysrc minidlna_enable=yes
# - or
echo minidlna_enable="YES" >>/etc/rc.conf

# Start / stop / rescan (Destructive) / refresh (updates the library, non destructive)
service minidlna stop
service minidlna start
service minidlna restart
service minidlna rescan
service minidlna refresh


# If there are issues with permissions, delete these directories so that they are recreated with proper permissions:
# - recreate the mount points
# - delete minidlna database and log or manually chown/chmod them
service minidlna stop
rm -rvf /mnt/common/minidlna/db
rm -rvf /mnt/common/minidlna/log/minidlna.log
service minidlna start


## Fix file limit exceeded and additional files are not scanned by minidlna/Plex
# - display max files limits, globally and per process:
#   sysctl -a : displays all readable variables
root@streaming:~ #
sysctl -a | grep kern.maxfiles
    kern.maxfiles: 2084861
    kern.maxfilesperproc: 1876374

# - to read a particular variable, specify its name:
sysctl kern.maxfiles
    kern.maxfiles: 2084861

# - to set a particular variable, use the variable=value syntax:
sysctl kern.maxfiles=3000000
    kern.maxfiles: 2084861 -> 3000000
sysctl kern.maxfilesperproc=3000000
    kern.maxfilesperproc: 1876374 -> 3000000

# - to make the change stick on reboot, you must edit /etc/sysctl.conf
ee /etc/sysctl.conf

[sysctl.conf] {
# Set max readable files
kern.maxfiles=3000000
kern.maxfilesperproc=3000000

} [sysctl.conf]

# - if the variable is read-only and doesn't apply on reboot, modify/add it to /boot/loader.conf
ee /boot/loader.conf
[loader.conf] {
# Set max readable files
kern.maxfiles=3000000
kern.maxfilesperproc=3000000

} [loader.conf]
 

mysticpete

Contributor
Joined
Nov 2, 2013
Messages
148
Very well written and worked a treat, thank you sir.
 
Top