This post explains how to make a media management jail in FreeBSD/FreeNAS that includes:

  • Plex media server
  • Sonarr
  • Radarr
  • SABnzbd
  • Transmission
  • nginx as a reverse proxy for the above

Creating the jail

If you are running FreeNAS, simply create a new jail from the jail template. If you are on FreeBSD, follow the instructions below.

  1. Enable jails on the host machine
1
sysrc jail_enable="YES"
  1. Create a dataset for the jail. Replace the paths with paths that are appropriate for your system.
1
2
zfs create -o mountpoint=/usr/local/jails zroot/jails
zfs create zroot/jails/mediajail
  1. Install FreeBSD in to the jail
1
bsdinstall jail /usr/local/jails/mediajail
  1. Copy DNS settings and time to the new jail
1
2
cp /etc/resolv.conf /usr/local/jails/mediajail/etc/resolv.conf
cp /etc/localtime /usr/local/jails/mediajail/etc/localtime
  1. Create /etc/jail.conf and enter the appropriate configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface = "igb0";
host.hostname = "$name.domain.local";
path = "/usr/local/jails/$name";
ip4.addr = 10.0.0.$ip;
mount.fstab = "/usr/local/jails/$name.fstab";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
mediajail {
$ip = 40;
}
  1. Create the fstab file
1
touch /usr/local/jails/mediajail.fstab
  1. Enter the paths you wish to present to the jail in to the fstab
1
2
3
/media/tank/tv /usr/local/jails/mediajail/media/tv nullfs rw 0 0
/media/tank/movies /usr/local/jails/mediajail/media/movies nullfs rw 0 0
/media/tank/downloads /usr/local/jails/mediajail/media/downloads nullfs rw 0 0
  1. Create the folder that will be mounted
1
2
3
4
5
mkdir /usr/local/jails/mediajail/media/tv
mkdir /usr/local/jails/mediajail/media/movies
mkdir /usr/local/jails/mediajail/media/downloads
mkdir /usr/local/jails/mediajail/media/downloads/incomplete
mkdir /usr/local/jails/mediajail/media/downloads/complete
  1. Create and start the new jail
1
jail -c mediajail

Creating the mediagroup group on the host system, and assigning permissions

  1. Create a group on the host system with the name being mediagroup and the group ID being 816. For FreeNAS this can be done through the GUI, for FreeBSD run:
1
sudo pw groupadd -n mediagroup -g 816
  1. Next, change the owner and permissions of the folders so that the jail can read and write through the shared mediagroup
1
2
3
4
5
6
chown -R root:mediagroup /media/tank/tv
chown -R root:mediagroup /media/tank/movies
chown -R root:mediagroup /media/tank/downloads
chmod -R 6775 /media/tank/tv
chmod -R 6775 /media/tank/movies
chmod -R 6775 /media/tank/downloads

Installing the apps

  1. Enter the new jail. In FreeNAS you can click the terminal window. In FreeBSD, run jexec mediajail /bin/sh

  2. If the jail is in an unsupported version of FreeBSD (looking at you FreeNAS), an unsupported version of sqlite3 is needed. Run the following, accepting all defaults

1
2
3
4
portsnap fetch
portsnap extract
cd /usr/ports/databases/sqlite3
make install clean ALLOW_UNSUPPORTED_SYSTEM=true
  1. Run pkg install with the application names. If you do not have Plex Pass, replace plexmediaserver-plexpass with plexmediaserver
1
pkg install plexmediaserver-plexpass sonarr radarr sabnzbdplus nginx transmission-daemon py27-certbot
  1. Enable all the applications to start on bootup of the jail. Again, if you do not have Plex Pass, replace plexmediaserver_plexpass_enable=YES with plexmediaserver_enable=YES
1
2
3
4
5
6
sysrc plexmediaserver_plexpass_enable=YES
sysrc sonarr_enable=YES
sysrc radarr_enable=YES
sysrc sabnzbd_enable=YES
sysrc nginx_enable=YES
sysrc transmission_enable=YES
  1. Create the mediagroup group in the jail and add all the appliation accounts needed
1
2
3
4
5
pw groupadd -n mediagroup -g 816
pw groupmod mediagroup -m sabnzbd
pw groupmod mediagroup -m sonarr
pw groupmod mediagroup -m radarr
pw groupmod mediagroup -m transmission
  1. Start the applications
1
2
3
4
5
6
service plexmediaserver_plexpass start
service sonarr start
service radarr start
service sabnzbd start
service nginx start
service transmission start

Configuring SABnzbd

  1. SABnzbd only allows connections from localhost initially. First, stop sabnzbd
1
service stop sabnzbd
  1. Replace the host line in the config
1
sed -i -e 's/host = 127.0.0.1/host = 0.0.0.0/g' /usr/local/etc/sabnzbd/sabnzbd.ini
  1. Start sabnzbd
1
service start sabnzbd
  1. Log in to SABnzbd in your browser at:
1
http://<mediajailip>:8080
  1. Run through the initial setup of SABnzbd, inputting the language and news server details.

  2. Once in SABnzbd, click on the cog in the top right corner to get to the settings.Click on the cog on the top to get to “General” settings.

  3. Set up a username and password, then click “Save Changes”.

  4. Go to the “Folders” settings and click “Advanced Settings”. Set the “Temporary Download Folder” to:

1
/media/downloads/incomplete
  1. Set the “Completed Download Folder” to:
1
/media/downloads/complete
  1. Set the “Permissions for completed downloads” to 775 then press “Save Changes”.

Configuring Transmission

  1. Transmission only allows connections from localhost initially, same as SABnzbd. First, stop transmission
1
service stop transmission
  1. Open settings.json and edit the following lines:
1
2
3
4
5
6
7
8
9
rpc-enabled -> change to true
rpc-password -> change to the password you want. This will be hashed upon restarting the service
rpc-username -> change to the username you want
rpc-whitelist -> set to your IP range, ie. 10.1.1.*
rpc-whitelist-enabled -> change to true
download-dir -> /media/downloads/complete
incomplete-dir -> /media/downloads/incomplete
incomlete-dir-enabled -> set to true
umask -> set to 0
  1. Sometimes the download directory set does not stick. Change this with a variable
1
sysrc transmission_download_dir=/media/downloads/complete
  1. Start transmission
1
service start transmission
  1. Log in to Transmission in your browser at:
1
http://<mediajailip>:9191

Configuring Sonarr

  1. Log in to Sonarr in your browser at:
1
http://<mediajailip>:8989
  1. Go to “Settings” and then “General”

  2. Change the “URL Base” to:

1
/sonarr
  1. Set the “Authentication” to Forms and enter a Username and Password. Click “Save”.

Configuring Radarr

  1. Log in to Radarr in your browser at:
1
http://<mediajailip>:7878
  1. Go to “Settings” and then “General”

  2. Change the “URL Base” to:

1
/radarr
  1. Set the “Authentication” to Forms and enter a Username and Password. Click “Save”.

Configuring nginx

  1. Stop the nginx service
1
service stop nginx
  1. Open /usr/local/etc/nginx/nginx.conf in an editor and change to the following, changing when needed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name <hostname>;
location ^~ /.well-known/acme-challenge/ {
alias /usr/local/www/nginx/.well-known/acme-challenge/;
}
location / {
return 301 https://<hostname>$request_uri;
}
}
server {
listen 443 default_server ssl;
server_name <hostname> <jail ip address>;
ssl_certificate /usr/local/etc/letsencrypt/live/<hostname>/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/<hostname>/privkey.pem;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
location /sonarr {
proxy_pass http://localhost:8989;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
location /radarr {
proxy_pass http://localhost:7878;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
location /sabnzbd {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
location /transmission {
proxy_pass http://localhost:9091;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_redirect off;
}
access_log /var/log/nginx/<hostname>.log;
}
}
  1. Start nginx
1
service start nginx
  1. Tell Certbot to generate a new SSL certificate
1
certbot certonly --webroot -w /usr/local/www/nginx -d <hostname>
  1. Reload nginx for the certificate to take effect
1
service reload nginx
  1. Set up a new cron schedule with visudo
1
37 2,15 * * * root /usr/local/bin/certbot renew --post-hook "service nginx reload"

Finishing up

You can now access services through the following:

  • Sonarr - https://<hostname>/sonarr
  • Radarr - https://<hostname>/radarr
  • SABnzbd - https://<hostname>/sabnzbd
  • Transmission - https://<hostname>/transmission