*New 11.3 series Release:
2019-10-19: XigmaNAS 11.3.0.4.7014 - released

*New 12.0 series Release:
2019-10-05: XigmaNAS 12.0.0.4.6928 - released!

*New 11.2 series Release:
2019-09-23: XigmaNAS 11.2.0.4.6881 - released!

We really need "Your" help on XigmaNAS https://translations.launchpad.net/xigmanas translations. Please help today!

Producing and hosting XigmaNAS costs money. Please consider donating for our project so that we can continue to offer you the best.
We need your support! eg: PAYPAL

[HOWTO] NGiNX as a Reverse Proxy in a Jail

Jails with XigmaNAS
Forum rules
Set-Up GuideFAQsForum Rules
Post Reply
texneus
Starter
Starter
Posts: 23
Joined: 12 Oct 2017 05:02
Status: Offline

[HOWTO] NGiNX as a Reverse Proxy in a Jail

#1

Post by texneus » 20 Jan 2019 23:23

Forward: I originally got my hands dirty with this a few years ago as lighttpd (built into NAS4Free/Xigmanas) would not properly reverse proxy Libresonic (now Airsonic).

For background, see:
https://github.com/Libresonic/libresonic/issues/305
https://redmine.lighttpd.net/issues/152

To my surprise I just learned this issue was resolved about a year ago (after 12 years) although I have not re-tried lighttpd as a reverse proxy at this time. The step by step that follows shows how to setup NGiNX for a reverse proxy server over HTTPS using self signed certificates and follows some web guides on ensuring NGiNX is secure. Since I'm not serving up publicly available web pages this is "good enough" for my needs, but I would encourage somebody to append this with instructions for a certificate authority such (such as LetsEncrypt) to make this even more useful.

This how-to will require you to use the Xigmanas command prompt and is therefore not for the faint of heart and is intended for advanced users.

All that said, lets get to work!


1. Create a www share
The www share will host things like certificates and keys and can contain other data so that the most rudimentary of Nginx functions can be performed without having to access the Nginx jail. This example assumes the www share is created on the TANK zpool (you should, of course, substitute your actual zpool name).

Goto Disks | Datasets and click the + button to add a new dataset. Accept all defaults except:
  • Pool - Choose TANK
  • Quota - consider assigning a quota of about 1Gb or so in case somebody figures out how to malicously write to Nginx, in which case only a small amount can be written rather than filling up an entire disk.
  • Access Restrictions - Set the owner and group to www since this is the user Nginx will run under.

2. Create an SSL certificate and keys
Certificates and keys signed by a certificate authority are a good idea, especially if the server is accessed by multple users. Provided you can trust yourself though, a self signed certificate is probably sufficient. The SSL connection is still valid and encrypted, but the web browser simply will not be able to confirm the certificate authenticity. The following example will create a self signed certificate valid for 1 year. Periodically (no longer than 2-3 months per at least some HTTPS guidelines), the certificate and key should be refreshed. For that reason a script will be created to automate the script creation process.

The script will perform the following actions: (1) Create a self signed SSL certificate as nas4freekb.cert. (2) Create a private key as privkey.pem. Both keys are valid for 1 year. (3) Establish Diffie–Hellman keys as dhparam.pem. (4) Set ownership of all files to root:wheel. Nginx will run as root until it is initialized then drop to user "www" (as we will specify in the Nginx config). This will allow Nginx to read the certificates at startup but (in theory) attempts to access the key files over the web will be denied. (5) provide a reminder to restart Nginx to read the new keys.

Code: Select all

# cat /mnt/TANK/www/genkey.sh
openssl req -new -x509 -nodes -sha256 -days 365 -newkey rsa:2048 > nas4freekb.cert
chown root:wheel nas4freekb.cert
chown root:wheel privkey.pem

openssl dhparam -out dhparam.pem 4096
chown root:wheel dhparam.pem

echo
echo A new certificate, key, and DH has been created.  Restart Nginx to activate.
Make the script executable, then run the script to create the keys:

Code: Select all

# cd /mnt/TANK/www
# chmod u+x genkey.sh
# ./genkey.sh
You will be prompted for general information about the SSL Certificate, such as company, contact name, and so on. This information can be displayed by users who attempt to access an HTTPS page so you probably DO NOT want (and nor are you required to use) personally identifiable information (such as your real name and actual location). Instead use something generic or unique that you can remember to verify the certificate is your own. If all is successful you will be left with a new certificate, private key, and Diffie-Hellman files (nas4freekb.cert, privkey.pem, and dhparam.pem).


3. Create the Nginx Jail
The following assumes "TheBrig" has been installed for jail management. Login to the Xigmanas web admin page and navigate to Extensions|TheBrig and create a slim jail. Accept all defaults except as denoted below:

Under "Jail Parameters":
  • Jail Name: Nginx
  • Jail Type: Slim
In the "In Jail Allow" seciton, ensure the following are added to the "In Jail" section:
  • allow.mount
  • allow.mount.devfs
  • allow.mount.nullfs
  • allow.mount.procfs
Under "Mounts":
  • Check "Enable mount devfs"
Under "Networking" (note: you will need to use a valid static IP address from your network):
  • Assign an IP address "192.168.1.211/24", then select add.
Under "Commands":
  • Type a description "Nginx Reverse Proxy Server"
Under "Installation Source":
  • Check "FreeBSD xxxxx -base.txz" and "FreeBSD xxxxx -lib32.txz"
Click "Add" to create the jail.

At the Xigmanas command prompt, create the mount points to enable www to be seen by Nginx:

Code: Select all

# mkdir /<full path to thebrig>/Nginx/mnt/www
Return to the Xigmanas GUI and edit the Nginx jail. In the Fstab section, mount the www share you previously created. The following assume the share will be mounted as read only (writing to the share shouldn't be required and helps ensure web server security, but if you require a read-write mount, change "ro" to "rw" in the Args section).

Code: Select all

/mnt/TANK/www /<full path to thebrig>/Nginx/mnt/www nullfs ro 0 0
Now start the jail from the Xigmanas GUI. Now, login to the jail and verify www was correctly mounted:

Code: Select all

# jexec Nginx csh
# ls -al /mnt/www
drwxrwxrwx  3 www   www        11 Mar 24 10:36 .
drwxrwxrwx  4 root  wheel       5 Mar 18 13:20 ..
-rw-r--r--  1 root  wheel   424 Mar 24 20:31 dhparam.pem
-rwxr-xr-x  1 root  wheel   301 Mar 24 20:45 genkey.sh
-rw-r--r--  1 root  wheel  1383 Mar 24 20:31 nas4freekb.cert
-rw-r--r--  1 root  wheel  1704 Mar 24 20:31 privkey.pem

4. Create a basic www web page
Still in the Nginx jail, create a webroot folder on the www share. This will hold a simple web page for passerby's to see. Remember, whatever you put here will be visible to the world, so unless you have a specific need, keep it short and generic to avoid attracting unwanted attention to your NAS.

Code: Select all

# mkdir /mnt/www/webroot
# cat /mnt/www/webroot/index.html
<html>
   <head>
      <title>Hello</title>
   </head>
   <body> Hello World! </body>
</html>
Now change the owner/group to www so that Nginx can serve them:

Code: Select all

# chown -R www:www /mnt/www/webroot

5. Install and configure Nginx
Nginx comes in several varients. Since we only require Nginx to provide reverse proxy services, we can use the Lite version. Install the pakage manager, Nginx, and nano (or your favorite text editor) from within the jail (reminder: you should still be at a jail command prompt from the last step).

Code: Select all

# pkg update			;this will also install pkg onto the jail
# pkg install nginx-lite nano	;this will also install all prerequisites...
Edit the Nginx configuration file. Generally, the Nginx configuration file is divided into two sections: Initialization and HTTP. The initialization section (more or less) includes parameters read at Nginx startup that define how Nginx operates, while the HTTP section contains parameters that define how specific web pages are served. There is no "one size fits all" here, so you are encouraged to read the Nginx documentation to set this up to best fulfill your personal needs. Note the port number used for the reverse proxy service (4443 in the example) MUST be forwarded by your router to access it outside your local network.

Code: Select all

# cat /usr/local/etc/nginx/nginx.conf
#Run server as default FreeBSD web user
user www;

#Documentation says to set this to the number of CPU cores, however unless this is
#a very busy server it's hard to hard to believe that more than 2 threads are necessary
worker_processes 2;

#Defines max number of connections.  Unless this is a busy server a much lower number should suffice
events {
    worker_connections  50;
}

# Nginx log paths (Information only, do not enable these lines)
# Access Log:  /var/log/nginx/access.log
# Error Log:   /var/log/nginx/error.log
# PID:         /var/run/nginx.pid

http {

    server_tokens off;                  #Disable reporting of NGINX info
    
    #Define HTTPS reverse proxy's on port 4443.
    server {
        listen       4443 ssl;          #Listen to 4443 HTTPS
        server_name  <your servers DNS name i.e. defined by the Dynamic DNS service>;  #Sever to listen for

        #The following are recommended for secure SSL
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_prefer_server_ciphers on;

        #SSL certificate & key for HTTPS defined previously
        ssl_dhparam          /mnt/www/dhparam.pem;
        ssl_certificate      /mnt/www/nas4freekb.cert;
        ssl_certificate_key  /mnt/www/privkey.pem;

        #Defines a home page
        location / {
            root   /mnt/www/webroot;
            index  index.html;
        }

        # redirect http requests to https on this port
        error_page 497 https://$host:4443$request_uri;

########################################
#Insert specific reverse proxy server blocks here
########################################



########################################
    }

    # All other requests (usually by IP) are assumed malicious and immediately closed...
    server {
        listen 4443 ssl default_server;
        server_name _;

        #The following are recommended for secure SSL
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_prefer_server_ciphers on;

        #SSL certificate & key for HTTPS
        ssl_dhparam          /mnt/www/dhparam.pem;
        ssl_certificate      /mnt/www/nas4freekb.cert;
        ssl_certificate_key  /mnt/www/privkey.pem;

        # redirect http requests to https on this port
        error_page 497 https://$host:4443$request_uri;

        return 444;
    }

}

You will need to refer to your specific application and Nginx documentation to determine how to configure Nginx as a reverse proxy for your particular application(s). Unfortunately, there is not a "switch" that makes it reverse proxy everything...if only it were that easy. More often then not these will go in the space reserved above.


7. Start Nginx and test
Enable Nginx to run as a daemon and start at jail startup.

Code: Select all

# echo 'nginx_enable="YES"' >> /etc/rc.conf
Start Nginx and test the basic HTTP and HTTPS web pages.

Code: Select all

# service nginx start
Open your web browser and browse to your DNS name. If everything is working correctly, HTTP will redirect to HTTPS. The web browser should now complain with a “This connection is not secure” or similar error. This is because a self signed certificate was used so this error is to be expected. Somewhere their should be a mechanism to view the certificate information used to create it. Once you confirm the certificate is the one you created, you can add an exception to the browser to allow the connection. When complete, you should see the default web page created in step 4 above.


8. Nginx log rotation (optional)
Logging is available for access, error, and PID by default (these lines do not need to be commented for logging to occur). Default locations of the log files are:

Access Log: /var/log/nginx/access.log
Error Log: /var/log/nginx/error.log
PID: /var/run/nginx.pid

Unfortunately the access and error logs are single files that will build and build essentially forever. To rotate the logs, the built in newsyslog feature will be used, which by default runs once per hour to rotate system log files, but we can add our own as well.

Code: Select all

# nano /etc/newsyslog.conf
Add the following line at the end of the list to enable weekly rotation of Nginx logs (one month of logs saved).

Code: Select all

/var/log/nginx/*.log    root:wheel      644  5     *    $W0D0 BCG  /var/run/nginx.pid 1
You will need to restart the jail to refresh newsyslog and enable log rotations.

At the very least logs should be manually reviewed periodically for malicious activity, but can also be used for i.e. fail2ban.


9. Refreshing the HTTPS certificates
The SSL certificates created above are valid for 365 days, however should be refreshed sooner (every 3 months is recommended). To update the keys simply log into the Xigmanas command line, SU to be root, and execute the script created in step 2:

Code: Select all

# /mnt/TANK/www/genkey.sh
This is also a good time to apply nginx updates (etc). From a Xigmanas command prompt:

Code: Select all

# jexec Nginx csh
# pkg update
# pkg upgrade
# exit
After this is completed, restart the Nginx jail from the Xigmanas GUI to load the new keys and updates. At this time any web browsers or applications that access the server will likely require to have the self signed certificate re-validated.
Last edited by texneus on 20 Jan 2019 23:57, edited 1 time in total.

texneus
Starter
Starter
Posts: 23
Joined: 12 Oct 2017 05:02
Status: Offline

Example Reverse Proxy for Emby

#2

Post by texneus » 20 Jan 2019 23:30

The following can be inserted into nginx.conf to provide a reverse HTTPS proxy to Emby. Up to date recommendations may be found on the Emby forums or user guide.

Code: Select all

########################################
#Insert jail specific proxy blocks here#
########################################

        # Proxy to the Emby server
        location /emby {
          # Send www traffic to the backend
          proxy_set_header X-Real-IP         $remote_addr;
          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto https;
          proxy_set_header Host              $host;
          proxy_max_temp_file_size           0;
          proxy_pass                         http://<IP address of your emby server>:8096;
          proxy_redirect                     off;
          proxy_intercept_errors             on;

          # Send websocket data to the backend as well...
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }
        
########################################
Last edited by texneus on 20 Jan 2019 23:44, edited 1 time in total.

texneus
Starter
Starter
Posts: 23
Joined: 12 Oct 2017 05:02
Status: Offline

Example Reverse Proxy for Airsonic

#3

Post by texneus » 20 Jan 2019 23:34

The following can be inserted into nginx.conf to provide a reverse HTTPS proxy to Airsonic. Up to date recommendations may be found on the Airsonic forums or user guide.

Code: Select all

########################################
#Insert jail specific proxy blocks here#
########################################

        # Proxy to the Airsonic server
        location /airsonic {
          proxy_set_header X-Real-IP         $remote_addr;
          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto https;
          proxy_set_header X-Forwarded-Host  $http_host;
          proxy_set_header Host              $http_host;
          proxy_max_temp_file_size           0;
          proxy_pass                         http://<IP address of your Airsonic server>:4040;
          proxy_redirect                     http:// https://;
          proxy_intercept_errors             on;
        }

########################################
Last edited by texneus on 20 Jan 2019 23:44, edited 1 time in total.

texneus
Starter
Starter
Posts: 23
Joined: 12 Oct 2017 05:02
Status: Offline

Example Reverse Proxy for SageTV

#4

Post by texneus » 20 Jan 2019 23:43

The following can be inserted into nginx.conf to provide a reverse HTTPS proxy to SageTV. Up to date recommendations may be found on the SageTV forums or user guide.

Code: Select all

########################################
#Insert jail specific proxy blocks here#
########################################

        # Proxy to the SageTV Web UI
        location ^~ /sage {
          proxy_pass                         http://<IP address of your SageTV server>:8080/sage;
        }

########################################

Shperrung
experienced User
experienced User
Posts: 95
Joined: 04 Apr 2018 16:29
Status: Offline

Re: [HOWTO] NGiNX as a Reverse Proxy in a Jail

#5

Post by Shperrung » 31 Jan 2019 21:35

Hi, texneus!
Thank you for your tutorial. I'll try it in first but I have couple questions:
1. Do I need to make any changes in lighttpd built in Xigmanas?
2. How to insert 3 web-servers into nginx config? For example, Nextcloud in Xigmanas lighttpd and qbittorrent... and Emby? I mean syntaxis.
11.2.0.4 - Omnius (revision 6177)
ASRock J3710-ITX, LAN: Realtek RTL8111GR; 16Gb RAM; WD 1Tbx2, WD 2Tb; UPS Powercom WOW500U.

texneus
Starter
Starter
Posts: 23
Joined: 12 Oct 2017 05:02
Status: Offline

Re: [HOWTO] NGiNX as a Reverse Proxy in a Jail

#6

Post by texneus » 02 Feb 2019 03:13

Glad you found it! To answer your questions.
Shperrung wrote:
31 Jan 2019 21:35
1. Do I need to make any changes in lighttpd built in Xigmanas?
No, not at all. Lighttpd will continue to provide the web UI as usual.
Shperrung wrote:
31 Jan 2019 21:35
2. How to insert 3 web-servers into nginx config? For example, Nextcloud in Xigmanas lighttpd and qbittorrent... and Emby? I mean syntaxis.
You can "run together" the proxy configuration sections in one block, but they must be unique "locations". For example to provide all three services from the examples:

Code: Select all

########################################
#Insert jail specific proxy blocks here#
########################################

        # Proxy to the Emby server
        location /emby {
          # Send www traffic to the backend
          proxy_set_header X-Real-IP         $remote_addr;
          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto https;
          proxy_set_header Host              $host;
          proxy_max_temp_file_size           0;
          proxy_pass                         http://<IP address of your emby server>:8096;
          proxy_redirect                     off;
          proxy_intercept_errors             on;

          # Send websocket data to the backend as well...
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }

        # Proxy to the Airsonic server
        location /airsonic {
          proxy_set_header X-Real-IP         $remote_addr;
          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto https;
          proxy_set_header X-Forwarded-Host  $http_host;
          proxy_set_header Host              $http_host;
          proxy_max_temp_file_size           0;
          proxy_pass                         http://<IP address of your Airsonic server>:4040;
          proxy_redirect                     http:// https://;
          proxy_intercept_errors             on;
        }

        # Proxy to the SageTV Web UI
        location ^~ /sage {
          proxy_pass                         http://<IP address of your SageTV server>:8080/sage;
        }

########################################

Post Reply

Return to “Jails”