NGINX Reverse Proxy

Problem

I’ve got multiple websites running on different servers on my local LAN.  I have a domain name under a dynamic DNS service that maps my domain name to my home network.  I need to be able to route multiple subdomains to the different servers on my LAN.  I have an Emby server and an OwnCloud server running in separate FreeNAS jails.  This I have this WordPress virtual machine running on a different box.  All have separate local IPs.

NGINX

Enter NGINX.  I can use NGINX as a reverse proxy to route my subdomains to a specific local IP.

Installation

First I need to start with a base image.  I went to TurnKeyLinux and downloaded the TurnKey Core based on Debian GNU/Linux as a good starting server using minimal resources.  But, it requires a few modifications first.  After initial setup, we have a root account but it would be best to setup a user and add them to the to the sudoers list.

Next, I installed the sudo package then I followed the tutorial here.

$ apt-get install sudo
$ adduser sammy

Create new information or leave it all blank.  Then add that new user to the sudo group

$ usermod -aG sudo sammy

Now switch to our new user and install NGINX.

$ su sammy

Update / create a sources.list file

$ nano /etc/apt/sources.list

Add Nginx package URL for the appropriate Linux release.  In my case, it was jessie.

deb http://nginx.org/packages/ubuntu/ jessie nginx
deb-src http://nginx.org/packages/ubuntu/ jessie nginx

Save the file then update and install.  I received this error upon the first install.

.W: GPG error: http://nginx.org/packages/ubuntu jessie Release: The following signatures couldn’t beverified because the public key is not available: NO_PUBKEY $key 

I followed the instructions on the NGINX website to add the key, and install NGINX

$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $key
$ sudo apt-get update
$ sudo apt-get install nginx
Setup

I originally setup my reverse proxy then configure let’s encrypt and update the config to use SSL.  Once complete we will force all HTTP connections to be rerouted to HTTPS.

First I create a .well-known folder in the HTML root for the 3 domains

$ sudo mkdir /usr/share/nginx/html/myhoard.org/.well-known
$ sudo mkdir /urs/share/nginx/html/blog.myhoard.org/.well-known

Then I modified my default.conf using this post as a guide.

/etc/nginx/conf.d/default.conf

## Basic reverse proxy server ##
## backend for www.myhoard.org ##
upstream wordpress {
 server 192.168.1.49:80; #wordpress
}

## emby backend for myhoard.org ##
upstream emby {
 server 192.168.1.6:8096; #emby
}

## Start www.myhoard.org ##
server {
 listen 80;
 server_name myhoard.org www.myhoard.org;

 #charset koi8-r;
 access_log /var/log/nginx/myhoard.org.access.log main;
 error_log /var/log/nginx/myhoard.org.error.log;
 root /usr/share/nginx/html;
 index index.html index.htm;
 
 location /.well-known {
 alias /usr/share/nginx/html/myhoard.org/.well-known;
 }
 
 ## send request back to apache1 ##
 location / {
 proxy_pass http://emby;
 proxy_next_upstream error timeout invalid_header http_500   http_502 http_503 http_504;
 proxy_redirect off;
 proxy_buffering off;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 }
}
## End www.myhoard.org ##
 
## START blog.myhoard.org ##
server {
 listen 80;
 server_name blog.myhoard.org www.blog.myhoard.org;
 
 access_log /var/log/nginx/blog.myhoard.org.access.log main;
 error_log /var/log/nginx/blog.myhoard.org.error.log;
 root /usr/local/nginx/html;
 index index.html;
 
 location /.well-known {
 alias /usr/share/nginx/html/myhoard.org/.well-known;
 }
 
 location / {
 proxy_pass http://wordpress;
 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
 proxy_redirect off;
 proxy_buffering off;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 }
}
## END blog.myhoard.org ##

Now we restart NGINX and generate some SSL certificates using certbot.  I chose to create a cert for both the root domain and the subdomain.  When running certbot I received the following error:

The 'python2-pythondialog>=3.2.2rc1' distribution was not found and is required by certbot

And I corrected it by installing the python dialog package as indicated in this post.

sudo apt-get install python-dialog=3.3.0-2~bpo8+1
$ sudo systemctl restart nginx
$ sudo certbot certonly --webroot -w /usr/share/nginx/html/myhoard.org/ -d myhoard.org -d www.myhoard.org
$ sudo certbot certonly --webroot -w /usr/share/nginx/html/blog.myhoard.org/ -d blog.myhoard.org -d www.blog.myhoard.org

With that complete now we can configure NGINX to use the new certificates by following this post.  So I update my default.conf file like so.

## Basic reverse proxy server ##
## wordpress backend for blog.myhoard.org ##
upstream wordpress {
 server 192.168.1.49:80; #wordpress
}

## emby backend for myhoard.org ##
upstream emby {
 server 192.168.1.6:8096; #emby
}

server {
 listen 80;
 server_name myhoard.org www.myhoard.org blog.myhoard.org www.blog.myhoard.org;
 rewrite ^ https://$host$request_uri? permanent;
}

## Start myhoard.org ##
server {
 listen 443 ssl;
 server_name myhoard.org www.myhoard.org;

 ssl_certificate /etc/letsencrypt/live/myhoard.org/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/myhoard.org/privkey.pem;
 
 ssl_stapling on;
 ssl_stapling_verify on;
 
 add_header Strict-Transport-Security "max-age=15552000";
 
 #charset koi8-r;
 access_log /var/log/nginx/myhoard.org.access.log main;
 error_log /var/log/nginx/myhoard.org.error.log;
 root /usr/share/nginx/html;
 index index.html index.htm;
 
 location /.well-known {
 alias /usr/share/nginx/html/myhoard.org/.well-known;
 }
 
 ## send request back to emby ##
 location / {
 proxy_pass http://emby;
 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
 proxy_redirect off;
 proxy_buffering off;
 proxy_set_header Host $host;
 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 $scheme;
 }
}
## End myhoard.org ##
 
## START blog.myhoard.org ##
server {
 listen 443 ssl;
 server_name blog.myhoard.org www.blog.myhoard.org;
 
 ssl_certificate /etc/letsencrypt/live/blog.myhoard.org/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/blog.myhoard.org/privkey.pem;
 
 ssl_stapling on;
 ssl_stapling_verify on;
 
 add_header Strict-Transport-Security "max-age=15552000";
 
 access_log /var/log/nginx/blog.myhoard.org.access.log main;
 error_log /var/log/nginx/blog.myhoard.org.error.log;
 root /usr/local/nginx/html;
 index index.html;
 
 location /.well-known {
 alias /usr/share/nginx/html/blog.myhoard.org/.well-known;
 }
 
 location / {
 proxy_pass http://wordpress;
 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
 proxy_redirect off;
 proxy_buffering off;
 proxy_set_header Host $host;
 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 $scheme;
 }
}
## END blog.myhoard.org ##

The X-Forwarded-Proto header was added, as indicated in this post, to successfully load static resources of WordPress with HTTPS.  This is necessary because WordPress itself is run under HTTP but is being proxied by NGINX as HTTPS.

Leave a Reply

Your email address will not be published. Required fields are marked *