Skip to content

Instantly share code, notes, and snippets.

@zenxedo
Forked from jacobblock/FreeNAS.md
Last active April 21, 2023 17:36
Show Gist options
  • Save zenxedo/e2fd4991bd2b787ca407a355d134b0ff to your computer and use it in GitHub Desktop.
Save zenxedo/e2fd4991bd2b787ca407a355d134b0ff to your computer and use it in GitHub Desktop.
Ultimate FreeNAS 11.3 iocage Setup

TrueNAS

I will be moving from FreeNAS jails to ubuntu with docker, docker compose, and portainer. FreeNAS support and updates are lacking. There are many advantages to making the switch and with ZFS on linux I think FreeNAS may be a thing of the past. Stay tuned for a new guide of my latest setup. Check out my other gists for progress on the switch. https://gist.github.com/mow4cash/626275e095f7f90898944a85d66b3be6

WARNING READ THIS: This page contains incomplete and possibly incorrect info. The page is constantly being edited and worked on. Many of these should work but some may be broken. Read the code carefully to understand what you are doing, stuff may be need to be changed for your own use. This includes but not limited too JAIL AND ROUTER IPs, YOUR FREENAS MAIN VOLUME,THE MOST RECENT RELEASE OF DOWNLOADED FILES Use at your own risk.There may be helpful info in the comments.

Find me in the FreeNAS forums

Thanks to the creator of this guide https://forums.freenas.org/index.php?resources/fn11-1-iocage-jails-plex-tautulli-sonarr-radarr-lidarr-jackett-ombi-transmission-organizr.58/

Setup Structure

myVol > media >  -series
                 -movies
                 -downloads > -radarr
                              -sonarr
                              -complete
                              -incomplete
                              -recycle bin   
                            ```

READ THIS: I have pool named myVol. I created a dataset named "media" and GAVE IT PERMISSIONS of the the default freenas user media:media. The dataset contains the folders series,movies,downloads. Radarr, Sonarr, Transmission will need to run as the user media:media to have access to them, this is very important and should not be overlooked. I also have a dataset named "apps" to hold the config data.

Permissions

READ THIS: For Sonarr, Radarr, Transmission you will have to change the default user to media:media so the jails can work together properly.

Use the name of your plugin instead of PLUGIN

service PLUGIN onestop
chown -R media:media /usr/local/PLUGIN (this location might be different for some of the apps)
sysrc 'PLUGIN_user=media'
sysrc 'PLUGIN_group=media'
service PLUGIN start

My current setup (dates show the last successful test):

Ombi and Unifi have been moved to docker containers in Rancher. See my other guide here https://gist.github.com/mow4cash/a57e893fc640ccf3720e99fc6b3b879a

Configuration:

Plex

# Create the jail
iocage create -n "plex" -r 12.1-RELEASE ip4_addr="vnet0|10.68.69.3/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on" 

# Update to the latest repo
iocage exec plex "mkdir -p /usr/local/etc/pkg/repos"
iocage exec plex "echo -e 'FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/latest\" }' > /usr/local/etc/pkg/repos/FreeBSD.conf"

# Install Plex and dependencies
iocage exec plex pkg install -y plexmediaserver

# Mount storage
iocage exec plex "mkdir -p /config"
iocage exec plex mkdir -p /mnt/media
iocage fstab -a plex /mnt/myVol/apps/plex /config nullfs rw 0 0
iocage fstab -a plex /mnt/myVol/media /mnt/media nullfs ro 0 0

# Set permissions
iocage exec plex chown -R plex:plex /config

# Enable service
iocage exec plex sysrc "plexmediaserver_enable=YES"
iocage exec plex sysrc plexmediaserver_support_path="/config"
iocage exec plex service plexmediaserver start

Transmission

iocage create -n "transmission" -r 12.1-RELEASE ip4_addr="vnet0|10.68.69.6/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on"

iocage exec transmission pkg install -y transmission

iocage exec transmission mkdir -p /config/transmission-home
iocage exec transmission mkdir -p  /mnt/downloads
iocage fstab -a transmission /mnt/myVol/apps/transmission /config nullfs rw 0 0
iocage fstab -a transmission /mnt/myVol/media/downloads /mnt/downloads nullfs rw 0 0

iocage exec transmission sysrc "transmission_enable=YES"
iocage exec transmission sysrc "transmission_conf_dir=/config/transmission-home"
iocage exec transmission sysrc "transmission_download_dir=/mnt/downloads/complete"

iocage exec transmission "pw user add media -c media -u 8675309 -d /nonexistent -s /usr/bin/nologin"
iocage exec transmission "pw groupadd -n media -g 8675309"
iocage exec transmission "pw groupmod media -m transmission"
iocage exec transmission  chown -R media:media /config/transmission-home
iocage exec transmission  chown -R media:media /mnt/downloads
iocage exec transmission  sysrc 'transmission_user=media'

iocage exec transmission service transmission start
 
# you may need to change the white list in settings.json to 0.0.0.0 or set to your preferred settings

Sonarr V3

iocage create -n "sonarr" -r 11.2-RELEASE ip4_addr="vnet0|10.68.69.25/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on" 

# update to Latest Repo
iocage exec sonarr "mkdir -p /usr/local/etc/pkg/repos"
iocage exec sonarr "echo -e 'FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/latest\" }' > /usr/local/etc/pkg/repos/FreeBSD.conf"
# install pkgs
iocage exec sonarr pkg install -y mono mediainfo sqlite3 curl
# mount storage
iocage exec sonarr mkdir -p /config
iocage exec sonarr mkdir -p  /mnt/downloads
iocage exec sonarr mkdir -p /mnt/series
iocage fstab -a sonarr /mnt/myVol/apps/sonarr /config nullfs rw 0 0
iocage fstab -a sonarr /mnt/myVol/media/downloads /mnt/downloads nullfs rw 0 0
iocage fstab -a sonarr /mnt/myVol/media/series /mnt/series nullfs rw 0 0

# download sonarr
iocage exec sonarr ln -s /usr/local/bin/mono /usr/bin/mono
iocage exec sonarr "fetch 'https://services.sonarr.tv/v1/download/phantom-develop/latest?version=3&os=linux' -o /usr/local/share/sonarr.tar.gz"
iocage exec sonarr "tar -xzvf /usr/local/share/sonarr.tar.gz -C /usr/local/share"
iocage exec sonarr rm /usr/local/share/sonarr.tar.gz
# Media Permissions
iocage exec sonarr "pw user add media -c media -u 8675309 -d /nonexistent -s /usr/bin/nologin"
iocage exec sonarr "pw groupadd -n media -g 8675309"
iocage exec sonarr "pw groupmod media -m sonarr"
iocage exec sonarr chown -R media:media /usr/local/share/Sonarr /config
iocage exec sonarr  sysrc 'sonarr_user=media'

# create rc.d
iocage exec sonarr mkdir /usr/local/etc/rc.d
iocage exec sonarr "ee /mnt/iocage/jails/sonarr/root/usr/local/etc/rc.d/sonarr"
# use rc.d below
CLICK TO SHOW SONARR rc.d

#!/bin/sh

# $FreeBSD$
#
# PROVIDE: sonarr
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
# sonarr_enable: Set to YES to enable sonarr
# Default: NO
# sonarr_user: The user account used to run the sonarr daemon.
# This is optional, however do not specifically set this to an
# empty string as this will cause the daemon to run as root.
# Default: media
# sonarr_group: The group account used to run the sonarr daemon.
# This is optional, however do not specifically set this to an
# empty string as this will cause the daemon to run with group wheel.
# Default: media
# sonarr_data_dir: Directory where sonarr configuration
# data is stored.
# Default: /var/db/sonarr

. /etc/rc.subr
name=sonarr
rcvar=${name}_enable
load_rc_config $name

: ${sonarr_enable:="NO"}
: ${sonarr_user:="media"}
: ${sonarr_group:="media"}
: ${sonarr_data_dir:="/config"}

pidfile="${sonarr_data_dir}/nzbdrone.pid"
command="/usr/sbin/daemon"
procname="/usr/local/bin/mono"
command_args="-f ${procname} /usr/local/share/Sonarr/Sonarr.exe --data=${sonarr_data_dir} --nobrowser"

start_precmd=sonarr_precmd
sonarr_precmd() {
if [ ! -d ${sonarr_data_dir} ]; then
install -d -o ${sonarr_user} -g ${sonarr_group} ${sonarr_data_dir}
fi

export XDG_CONFIG_HOME=${sonarr_data_dir}
}

run_rc_command "$1"

iocage exec sonarr chmod u+x /usr/local/etc/rc.d/sonarr
iocage exec sonarr sysrc "sonarr_enable=YES"
iocage exec sonarr service sonarr start

Radarr

iocage create -n "radarr" -r 11.2-RELEASE ip4_addr="vnet0|10.68.69.27/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on"

# Update to Latest Repo
iocage exec radarr "mkdir -p /usr/local/etc/pkg/repos"
iocage exec radarr "echo -e 'FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/latest\" }' > /usr/local/etc/pkg/repos/FreeBSD.conf"

# Install pkgs
iocage exec radarr pkg install -y mono mediainfo sqlite3 curl

iocage exec radarr mkdir -p /config
iocage exec radarr mkdir -p  /mnt/downloads
iocage exec radarr mkdir -p /mnt/movies
iocage fstab -a radarr /mnt/myVol/apps/radarr /config nullfs rw 0 0
iocage fstab -a radarr /mnt/myVol/media/downloads /mnt/downloads nullfs rw 0 0
iocage fstab -a radarr /mnt/myVol/media/movies /mnt/movies nullfs rw 0 0

iocage exec radarr ln -s /usr/local/bin/mono /usr/bin/mono
iocage exec radarr "fetch https://github.com/Radarr/Radarr/releases/download/v0.2.0.1217/Radarr.v0.2.0.1217.linux.tar.gz -o /usr/local/share"
iocage exec radarr "tar -xzvf /usr/local/share/Radarr.v0.2.0.1217.linux.tar.gz -C /usr/local/share"
iocage exec radarr rm /usr/local/share/Radarr.v0.2.0.1217.linux.tar.gz

## Media Permissions
iocage exec radarr "pw user add radarr -c radarr -u 352 -d /nonexistent -s /usr/bin/nologin"

iocage exec radarr "pw user add media -c media -u 8675309 -d /nonexistent -s /usr/bin/nologin"
iocage exec radarr "pw groupadd -n media -g 8675309"
iocage exec radarr "pw groupmod media -m radarr"
iocage exec radarr chown -R media:media /usr/local/share/Radarr /config
iocage exec radarr sysrc 'radarr_user=media'
iocage exec radarr service radarr start
On Windows, you need to change the End of Line (EOL) format in Notepad++ to UNIX:

use ee editor or it won't work at least for me!
Create an rc file for radarr using your favorite editor at /mnt/iocage/jails/radarr/root/usr/local/etc/rc.d/radarr

iocage exec radarr mkdir /usr/local/etc/rc.d
iocage exec radarr "ee /mnt/iocage/jails/radarr/root/usr/local/etc/rc.d/radarr"

#!/bin/sh

# $FreeBSD$
#
# PROVIDE: radarr
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
# radarr_enable:    Set to YES to enable radarr
#            Default: NO
# radarr_user:    The user account used to run the radarr daemon.
#            This is optional, however do not specifically set this to an
#            empty string as this will cause the daemon to run as root.
#            Default: media
# radarr_group:    The group account used to run the radarr daemon.
#            This is optional, however do not specifically set this to an
#            empty string as this will cause the daemon to run with group wheel.
#            Default: media
# radarr_data_dir:    Directory where radarr configuration
#            data is stored.
#            Default: /var/db/radarr

. /etc/rc.subr
name=radarr
rcvar=${name}_enable
load_rc_config $name

: ${radarr_enable:="NO"}
: ${radarr_user:="media"}
: ${radarr_group:="media"}
: ${radarr_data_dir:="/config"}

pidfile="${radarr_data_dir}/nzbdrone.pid"
command="/usr/sbin/daemon"
procname="/usr/local/bin/mono"
command_args="-f ${procname} /usr/local/share/Radarr/Radarr.exe --data=${radarr_data_dir} --nobrowser"

start_precmd=radarr_precmd
radarr_precmd() {
    if [ ! -d ${radarr_data_dir} ]; then
    install -d -o ${radarr_user} -g ${radarr_group} ${radarr_data_dir}
    fi

    export XDG_CONFIG_HOME=${radarr_data_dir}
}

run_rc_command "$1"
iocage exec radarr chmod u+x /usr/local/etc/rc.d/radarr
iocage exec radarr sysrc "radarr_enable=YES"
iocage exec radarr service radarr start

Organizr V2

#Note to self: Make sure port forwarding is disabled before removing or rebuilding this jail

iocage create -n "organizr" -r 11.2-RELEASE ip4_addr="vnet0|10.68.69.7/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on"

iocage exec organizr pkg install -y nginx git wget php72 php72-curl php72-pdo php72-sqlite3 php72-simplexml php72-zip php72-openssl php72-hash php72-json php72-session php72-pdo_sqlite php72-filter

iocage exec organizr mkdir -p /config
iocage fstab -a organizr /mnt/myVol/apps/organizr /config nullfs rw 0 0

iocage console organizr
echo 'listen = /var/run/php-fpm.sock' >> /usr/local/etc/php-fpm.conf
echo 'listen.owner = www' >> /usr/local/etc/php-fpm.conf
echo 'listen.group = www' >> /usr/local/etc/php-fpm.conf
echo 'listen.mode = 0660' >> /usr/local/etc/php-fpm.conf
exit

iocage exec organizr cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
iocage exec organizr sed -i '' -e 's?;date.timezone =?date.timezone = "Universal"?g' /usr/local/etc/php.ini
iocage exec organizr sed -i '' -e 's?;cgi.fix_pathinfo=1?cgi.fix_pathinfo=0?g' /usr/local/etc/php.ini

iocage exec organizr git clone -b v2-develop https://github.com/causefx/Organizr /usr/local/www/Organizr
iocage exec organizr chown -R www:www /usr/local/www /config
user www;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
root /usr/local/www/Organizr;
location / {
index index.php index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
}
}
}
iocage exec organizr sysrc nginx_enable=YES
iocage exec organizr sysrc php_fpm_enable=YES
iocage exec organizr service nginx start
iocage exec organizr service php-fpm start

#important step Navigate to http://JailIP and set the follow the setup database location to "/config/Organizr" and Organizr for the database name. If you have an exsisting config file in the database location once you complete the setup restart the jail and login with you exsisting credentials.

# link my exsisting nginx config, you need to upload your own or edit the exsisting
iocage exec organizr service nginx stop
iocage exec organizr rm /usr/local/etc/nginx/nginx.conf
iocage exec organizr ln -s /config/nginx/nginx.conf /usr/local/etc/nginx/nginx.conf
iocage exec organizr service nginx start

#note to self renable port forwarding

I keep folders in /config for nginx,log,letsencrypt,Backups

Jackett

iocage create -n "jackett" -r 11.2-RELEASE ip4_addr="vnet0|10.68.69.26/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on"

# Update to Latest Repo
iocage exec jackett "mkdir -p /usr/local/etc/pkg/repos"
iocage exec plex "echo -e 'FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/latest\" }' > /usr/local/etc/pkg/repos/FreeBSD.conf"

iocage exec jackett pkg install -y mono curl

iocage exec jackett mkdir -p /config
iocage fstab -a jackett /mnt/myVol/apps/jackett /config nullfs rw 0 0

iocage exec jackett ln -s /usr/local/bin/mono /usr/bin/mono
iocage exec jackett "fetch https://github.com/Jackett/Jackett/releases/download/v0.10.531/Jackett.Binaries.Mono.tar.gz -o /usr/local/share"
iocage exec jackett "tar -xzvf /usr/local/share/Jackett.Binaries.Mono.tar.gz -C /usr/local/share"
iocage exec jackett rm /usr/local/share/Jackett.Binaries.Mono.tar.gz

iocage exec jackett "pw user add jackett -c jackett -u 818 -d /nonexistent -s /usr/bin/nologin"
iocage exec jackett chown -R jackett:jackett /usr/local/share/Jackett /config
iocage exec jackett mkdir /usr/local/etc/rc.d

ee /mnt/myVol/iocage/jails/jackett/root/usr/local/etc/rc.d/jackett
#!/bin/sh

# $FreeBSD$
#
# PROVIDE: jackett
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
# jackett_enable:    Set to YES to enable jackett
#            Default: NO
# jackett_user:    The user account used to run the jackett daemon.
#            This is optional, however do not specifically set this to an
#            empty string as this will cause the daemon to run as root.
#            Default: media
# jackett_group:    The group account used to run the jackett daemon.
#            This is optional, however do not specifically set this to an
#            empty string as this will cause the daemon to run with group wheel.
#            Default: media
# jackett_data_dir:    Directory where jackett configuration
#            data is stored.
#            Default: /var/db/jackett

. /etc/rc.subr
name=jackett
rcvar=${name}_enable
load_rc_config $name

: ${jackett_enable:="NO"}
: ${jackett_user:="jackett"}
: ${jackett_group:="jackett"}
: ${jackett_data_dir:="/config"}

command="/usr/sbin/daemon"
procname="/usr/local/bin/mono"
command_args="-p ${jackett_data_dir}/jackett.pid -f ${procname} /usr/local/share/Jackett/JackettConsole.exe -d ${jackett_data_dir}"

start_precmd=jackett_precmd
jackett_precmd() {
    export USER=${jackett_user}
    if [ ! -d ${jackett_data_dir} ]; then
    install -d -o ${jackett_user} -g ${jackett_group} ${jackett_data_dir}
    fi

    export XDG_CONFIG_HOME=${jackett_data_dir}
}

run_rc_command "$1"
iocage exec jackett chmod u+x /usr/local/etc/rc.d/jackett
iocage exec jackett sysrc "jackett_enable=YES"
iocage exec jackett service jackett start

Tautulli

echo '{"pkgs":["python2","py27-sqlite3","py27-openssl","git" ," py27-pycryptodome" ,"ca_root_nss"]}' > /tmp/pkg.json
iocage create -n "tautulli" -p /tmp/pkg.json -r 11.2-RELEASE ip4_addr="vnet0|10.68.69.16/24" defaultrouter="10.68.69.1" vnet="on" allow_raw_sockets="1" boot="on"
rm /tmp/pkg.json
iocage exec tautulli mkdir -p /config
iocage fstab -a tautulli /mnt/myVol/apps/tautulli /config nullfs rw 0 0
iocage exec tautulli git clone https://github.com/Tautulli/Tautulli.git /usr/local/share/Tautulli
iocage exec tautulli "pw user add tautulli -c tautulli -u 109 -d /nonexistent -s /usr/bin/nologin"
iocage exec tautulli chown -R tautulli:tautulli /usr/local/share/Tautulli /config
iocage exec tautulli cp /usr/local/share/Tautulli/init-scripts/init.freenas /usr/local/etc/rc.d/tautulli
iocage exec tautulli chmod u+x /usr/local/etc/rc.d/tautulli
iocage exec tautulli sysrc "tautulli_enable=YES"
iocage exec tautulli sysrc "tautulli_flags=--datadir /config"
iocage exec tautulli service tautulli start

Backups

Important files

Backup your entire apps folder

Common Commands

https://www-uxsup.csx.cam.ac.uk/pub/doc/suse/suse9.0/userguide-9.0/ch24s04.html

cd /directorypath	: Change to directory.
chmod [options] mode filename	: Change a file’s permissions.
chown [options] filename :	Change who owns a file.
cp [options] :source destination	: Copy files and directories.
ln -s test symlink	: Creates a symbolic link named symlink that points to the file test
mkdir [options] directory	: Create a new directory.
mv -i myfile yourfile : Move the file from "myfile" to "yourfile". This effectively changes the name of "myfile" to "yourfile".
mv -i /data/myfile :	Move the file from "myfile" from the directory "/data" to the current working directory.
rm [options] directory	: Remove (delete) file(s) and/or directories.
tar [options] filename :	Store and extract files from a tarfile (.tar) or tarball (.tar.gz or .tgz).
touch filename :	Create an empty file with the specified name.

Testing/Updates

iocage exec <jail> pkg upgrade <name of service>
iocage exec <jail> pkg upgrade && pkg update

iocage exec <jail> service <name of service> start
iocage exec <jail> service <name of service> restart
iocage exec <jail> service <name of service> stop

Default User Ports/UID/Location

PORT - SERVICE - USER (UID)
radarr- 7878 - radarr (352) 
sonarr- 8989 - 
jackett - 9117 - jackett (818)
0rganizr - 80 - organizr (www)
plexmediaserver 32400 - plex (972)
transmission - 9091 -transmission (921) 
tautulli - 8181 - tautlli (109)
ombi - 3579 - ombi (819)
@pathsny
Copy link

pathsny commented Aug 23, 2020

Great tutorial , just started about 45min ago. Currently on the Emby setup.
Struggled with transmission setup tho, struggling to understand a few things. eg. sysrc transmission_download_dir="" -----where should i set the download directory to? /media/downloads?
i stopped transmission....editted settings.json in /var/db/transmission. started plex and then get this error 👍
root@media:/mnt # service transmission restart
Stopping transmission.
Waiting for PIDS: 89362.
usage: chown [-fhvx] [-R [-H | -L | -P]] owner[:group] file ...
chown [-fhvx] [-R [-H | -L | -P]] :group file ...
Starting transmission.

" Create this user in your FreeNAS with the same uid and gid (typically 1001 if you haven't made a custom account yet).
--- Do i create this user in the freenas gui? What if iv already created a user in freenas gui?
"Add mounts for media + crashplan backups inside the jail (/mnt//media to /mnt/media). "

  • i dont have a /mnt//media folder....only a /mnt/media folder?

Hi Wez,looking at the guide, did you ever figure out how to get emby setup? i dont see it in the gist

@JoMas971
Copy link

Looks like it doesn't work anymore with TrueNAS 12.0-U2. It doesn't find the pre-build version for this build.
Screenshot 2021-02-14 at 22 51 49

@zenxedo
Copy link
Author

zenxedo commented Feb 14, 2021

Looks like it doesn't work anymore with TrueNAS 12.0-U2. It doesn't find the pre-build version for this build.
Screenshot 2021-02-14 at 22 51 49

That's weird. One of the reasons I moved away from Freenas. TrueNAS scale may be headed on the right direction.

@zierbeek
Copy link

zierbeek commented Apr 5, 2021

Hi, i am new to all this, I started with creating the file directories, skipped the permissions step and went to the setup of Plex and so on.
Plex went fine.

when I started with transmission, everything went fine until the permissions. I got the message that the account already existed. How do I solve this? I just copy pasted the commands.

And when I try to create he rc.d file, I always get the message: unable to create file. I already changed the /mnt/iocage to /mnt/myvol/iocage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment