How to setup Organizr with Let's Encrypt on unRAID

In this guide I will explain the steps I took to get Organizr to be the frontend/homepage for all the Plex tools that I run.

Preparation

Before we start you need to acquire a domain. You can do that on duckdns or any other domain service. I'm using a .tech domain from get.tech and I got a very nice price by using a coupon code from the people over at level1techs

Level1 ($3.99 for 1 year registration)
Level3 ($24.99 for 3 year registration)
Level110 ($49.99 for 10 year registration)
This guide is based a regular domain setup, not something like duckdns. For a duckdns setup see: https://cyanlabs.net/tutorials/the-complete-unraid-reverse-proxy-duck-dns-dynamic-dns-and-letsencrypt-guide/

Forward your domain to your public IP address.

After you've done that add your different ANAME records e.g www.yourdomain.com or blog.yourdomain.com

You can now start installing the different docker containers from the "Apps" tab in unRAID.

Installation

This guide assumes you have Community applications installed, if not check out this video from Spaceinvader One

Let's Encrypt
  1. Container Port: 80 - Choose your desired port. e.g 81
  2. Container Port: 443 - Set this to 443
  3. Enter you email
  4. Add you domain e.g yourdomain.com
  5. Add your different sub domains e.g www,blog,plex ect
  6. Container Path: /config Install the container config to your desired location. I recommend using an SSD.

Next is portforwarding. This is done on your router and you need to forward port 80 to the port you chose in step 1. You also need to forward port 443 to 443. So if your servers ip is 192.168.1.2 and you have chosen that the container is on port 81, you need to forward all traffic on port 80 to port 81 on ip 192.168.1.2 And do the same for port 443.

If you're unsure how to do this on your router check out: Portforward.com

Next go to https://yourserverip or http://yourserverip:81 If you now see the Nginx welcome page, it works. Also test if yourdomain.com redirects you to the nginx welcome page.

Organizr

Nothing special you need to configure. Just enter your desired container port (Must be something different than letsencrypt)

Setting up Nginx

This config is a combination of different configs I have found googling and getting help from the guys over at the Organizr lobby I'm by no means an expert and I'm suprised I've gotten this far..

Go to the location where you have installed the letsencrypt container. Find the nginx folder and then edit the file called "default" in the "site-conf" folder. I recommend using notepad++

In my config I use both sub directories (domain.com/service) and sub domains (plex.domain.com) Use what you need below, and change the IP adresses and ports to your different services.

As you can see below I use an upstream for organizr.

Add

#ORGANIZR UPSTREAM
upstream organizr-upstream {
#This is the local ip and port to Organizr
server 192.168.1.2:8282;
    keepalive 32;
}

above your server block

And add

#ORGANIZR CONTAINER
    location / {
        proxy_pass http://organizr-upstream;
        include /config/nginx/proxy.conf;
    }

in your main server block.

For custom errorpages add

    # Custom error pages 
        error_page 400 401 402 403 404 405 408 500 502 503 504 $scheme://$server_name/error.php?error=$status;  
Server auth (Recommended)

For server auth add the location blocks below in your main server block. I'd recommend to use server based auth, as it's the more secure option.

I haven't managed to get auth to work with the letsencrypt container yet. Well I got it to partially work. I could load the Sonarr/Radarr page but when trying to use the service other than browsing the pages nothing would happen. Remember to clear your cache after you add the cookie.

UPDATE: By using the authenticatzion block below, server auth works! Thanks Fr00t!

UPDATE 2: Seems to only work on sub directories NOT sub domains

Authentication | Server Based

(PSA: If Organizr is on sub domain, auth wont work!)

Add:

    location /auth-admin {
            internal;
            proxy_pass http://192.168.1.2:8282/auth.php?admin;
            proxy_set_header Content-Length "";
        }

        location /auth-user {
            internal;
            proxy_pass http://192.168.1.2:8282/auth.php?user;
            proxy_set_header Content-Length "";
        }

In your MAIN SERVER BLOCK

Remember to add the admin or user block to any SUB DOMAIN BLOCK also.

http://192.168.1.2:8282 is the local ip and port to Organizr

Just add auth_request /auth-admin; or auth_request /auth-user;

  • admin - Only allows Admins to access the block/page.
  • user - Only allows logged in users to access the block/page.

like this:

    # RADARR CONTAINER
    location ^~ /radarr/ {
        auth_request /auth-admin;
        proxy_pass http://192.168.1.34:7878/radarr/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

By using server auth you will block any apps like nzb360 to be able to connect to Sonarr/Radarr. But by allowing /sonarr/api you can get around that. Read more here

Like this:

# SONARR CONTAINER API
    location ^~ /sonarr/api {
        proxy_pass http://192.168.1.34:8989/sonarr/api;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
Cookie password

If you want to use cookie password add

if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }

in your proxy blocks.

It referes to the cookie password set in the Organizr settings, so remember to comment this out if you are not using a cookie password.

If you are going with Browser [Cookie] Authentication it's important that the "Domain Name for Cookie" in Organizr is your top level domain e.g domain.com, and not a sub domain e.g yourdomain.duckdns.org

This will block anyone trying to to access /sonarr or plex.yourdomain.com without logging in to Organizr first.

X-Frame-Options

You also have to comment out the X-Frame option in your nginx.conf file in the nginx folder. e.g /appdata/letsencrypt/nginx/nginx.conf

#   add_header X-Frame-Options SAMEORIGIN;

Just add # before the line. If you dont do this the iframe won't load on the proxy redirects and it will just display a white page.

Remember that on a lot of these services (Sonarr/Radarr/Ombi ect) you need to add a webroot/URL base. That means that the internal address to Sonarr is http://192.168.1.2:8989/sonarr/ instead of http://192.168.1.2:8989. Reverse proxy wont work without it. If the service you want to access does not have the option to add an URL base I recommend creating a sub domain and using upstream.

Once you have added all your services you need to restart the letsencrypt container.

And remember to check the container logs of something is not working.

For Fail2ban integration check out my post here

Here is an example config with different services.
#PLEX UPSTREAM FOR THE SUB DOMAIN
upstream plex-upstream {
    server 192.168.1.2:32400;
    keepalive 32;
}

#ORGANIZR UPSTREAM
upstream organizr-upstream {
    server 192.168.1.2:8282;
    keepalive 32;
}

#NETDATA UPSTREAM
upstream backend {
    server 192.168.1.2:19999;
    keepalive 64;
}

#DELUGE UPSTREAM
upstream deluge-upstream {
    server 192.168.1.2:8112;
    keepalive 32;
}

#REDIRECT TRAFFIC TO https://[yourdomain.com]
server {
     listen 80;
     server_name _;
     return 301 https://$host$request_uri;
}

#MAIN SERVER BLOCK
server {
    listen 443 ssl http2 default_server;
    server_name yourdomain.com;

    #SSL settings
    ssl_certificate /config/keys/letsencrypt/fullchain.pem;
    ssl_certificate_key /config/keys/letsencrypt/privkey.pem;
    ssl_dhparam /config/nginx/dhparams.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;

    client_max_body_size 0;

#CUSTOM ORGANIZR ERROR PAGES
    error_page 400 401 402 403 404 500 502 /error.php?error=$status;

#AUTHORIZATION BLOCK    
    location /auth-admin {
            internal;
            proxy_pass http://192.168.1.2:8282/auth.php?admin;
            proxy_set_header Content-Length "";
        }

        location /auth-user {
            internal;
            proxy_pass http://192.168.1.2:8282/auth.php?user;
            proxy_set_header Content-Length "";
        }

#ORGANIZR CONTAINER
    location / {
        proxy_pass http://organizr-upstream;
        include /config/nginx/proxy.conf;
    }

# PLEX SUB DIR
# Check the comment in the bottom of this page for the include /config/nginx/plex.conf
    location /plex/ {
        auth_request /auth-user;
        proxy_pass          http://plex-upstream/;
        include /config/nginx/plex.conf;
    }
    if ($http_referer ~* /plex/) {
        rewrite ^/web/(.*) /plex/web/$1? redirect;
    }

#PLEXPY CONTAINER
#Do NOT check "Enable HTTP Proxy" in PlexPy
#Oh And yourdomain.com/plexpy/auth is the address..
    location /plexpy {
        auth_request /auth-user;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        proxy_pass http://192.168.1.2:8181;
        include /config/nginx/proxy.conf;
        proxy_bind $server_addr;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Forwarded-Ssl     on;
    }   

#RADARR CONTAINER
    location ^~ /radarr {
        auth_request /auth-admin;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        proxy_pass http://192.168.1.2:7878/radarr;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

#SONARR CONTAINER
    location ^~ /sonarr {
        auth_request /auth-admin;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        proxy_pass http://192.168.1.2:8989/sonarr;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

#JACKETT CONTAINER
    location ^~ /jackett/ {
        auth_request /auth-admin;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        proxy_pass http://192.168.1.2:9117/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }   

#NETDATA 301 REDIRECT
    location /netdata {
        return 301 /netdata/;
    }

#NETDATA CONTAINER
    location ~ /netdata/(?<ndpath>.*) {
        auth_request /auth-user;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://backend/$ndpath$is_args$args;
        proxy_http_version 1.1;
        proxy_pass_request_headers on;
        proxy_set_header Connection “keep-alive”;
        proxy_store off;
    }

#OMBI CONTAINER
    location ^~ /ombi {
        auth_request /auth-user;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        include /config/nginx/proxy.conf;
        proxy_pass http://192.168.1.2:3579/ombi;
    }
# SABNZBD CONTAINER
    location ^~ /sabnzbd {
        auth_request /auth-admin;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        include /config/nginx/proxy.conf;
        proxy_pass http://192.168.1.2:8383/sabnzbd;
        proxy_set_header Host $host;
    }
# NZBGET CONTAINER
    location ^~ /nzbget {
        auth_request /auth-admin;
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        include /config/nginx/proxy.conf;
        proxy_pass http://192.168.1.2:6789;
        proxy_set_header Host $host;
    }    
}

#PLEX SERVER 
   server {
     listen 443 ssl http2;
     server_name plex plex.domain.com;

     location /error/ {
       alias /www/errorpages/;
       internal;
       }

     location / {

       proxy_redirect off;
       proxy_buffering off;
       proxy_hide_header X-Frame-Options;

       # Spoof the request as coming from ourselves since otherwise Plex will block access, e.g. logging:
       # "Request came in with unrecognized domain / IP 'tv.example.com' in header Referer; treating as non-local"
       proxy_set_header        Host                      $server_addr;
       proxy_set_header        Referer                   $server_addr;
       proxy_set_header        Origin                    $server_addr;

       proxy_set_header        X-Real-IP                 $remote_addr;
       proxy_set_header        X-Forwarded-For           $proxy_add_x_forwarded_for;
       proxy_set_header        X-Plex-Client-Identifier  $http_x_plex_client_identifier;
       proxy_set_header        Cookie                    $http_cookie;

       ## Required for Websockets
       proxy_http_version      1.1;
       proxy_set_header        Upgrade                   $http_upgrade;
       proxy_set_header        Connection                "upgrade";
       proxy_read_timeout      36000s;                   # Timeout after 10 hours

       proxy_next_upstream     error timeout invalid_header http_500 http_502 http_503 http_504;

       #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
       proxy_pass http://plex-upstream;
     }
   }

#BLOG SITE
server {
        listen 80;  
        listen 443 ssl http2;
        server_name blog.domain.com;

      root /config/www/grav/;
      index index.html index.php;

    location /error/ {
        alias /www/errorpages/;
        internal;
        }

    location / {
                try_files $uri $uri/ /index.php?_url=$uri&$query_string;
        }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # With php7-cgi alone:
        fastcgi_pass 127.0.0.1:9000;
        # With php7-fpm:
        #fastcgi_pass unix:/var/run/php7-fpm.sock;
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
    }

    fastcgi_buffer_size 4K;
    fastcgi_buffers 64 4k; 
}

#DELUGE CONTAINER
server {
    server_name  deluge.domain.com;
        listen 80;
        listen 443 ssl http2;

    location / {
        #if ($cookie_cookiePassword != "yourcookiepasswordhere") { return 401; }
        proxy_pass http://deluge-upstream;
        include /config/nginx/proxy.conf;
    }

}

This is the content of the plex.conf in the plex sub directory block:

client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_buffers 32 4k;
proxy_hide_header X-Frame-Options;
proxy_http_version 1.1;
proxy_read_timeout 240;
proxy_redirect  http://  $scheme://;
proxy_send_timeout 240;
proxy_set_header    Connection            "upgrade";
proxy_set_header    Host                $host;
#proxy_set_header    Host                $host:$server_port;
proxy_set_header    X-Real-IP            $remote_addr;
proxy_set_header    X-Forwarded-For        $proxy_add_x_forwarded_for;
proxy_set_header    X-Forwarded-Host    $server_name;
proxy_set_header    X-Forwarded-Proto    https;
proxy_set_header    X-Forwarded-Ssl        on;
proxy_set_header    Upgrade                $http_upgrade;
send_timeout 5m;

See: https://github.com/causefx/Organizr/wiki/Plex-SSO

For fast and great support, check out the Organizr discord! https://organizr.us/discord

W.

Next Post Previous Post

Blog Comments powered by Disqus.