NGINX - Reverse Proxy
This is a guide on how to install NGINX for Windows and add extra security to it.
Ever want to get an A security rating for your website. Then look no further

Pre-Requisites
Your own Domain name A Trust certificate in either .crt or .pem format A Private.key to go with the certificate Access to your router for port forwarding Either a DDNS or have an A Record for WAN IP.
If you havent got a Trusted Certificate you can use my guide Easy Let's Encrypt Certificate to get a free one.
This guide assumes you have either setup a DDNS or have an A record setup to point your Domain Name to your WAN IP. If you dont have this setup go here.
Step 1 - Port Forwarding
Every router is different and rather than try to describe how to do this on all the different brands I will simplify it so it is more relevant to all routers.
- Log into your router
- Head over to port forwarding
- Create a new rule to forward port 443 and port 80 to the machine that NGINX will be running on.
Step 2 - Installing NGINX
Head over to NGINX-Win and download the latest version of NGINX for Windows. As of writing this guide the latest version is 1.13.1.1 Violet.

Extract the .zip folder somewhere easy to find. for my example I will extract it to C:\NGINX\ Open up the config folder C:\NGINX\config

Open up notepad (I recommend Notepad++) and copy the following into it.
Worker_processes 2;
events {
worker_connections 8192;
}
http {
include mime.types;
default_type application/octet-stream;
server_tokens off;
gzip on;
gzip_disable "msie6";
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
text/plain
text/css
text/js
text/xml
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
image/svg+xml;
tcp_nodelay on;
sendfile off;
server_names_hash_bucket_size 128;
map_hash_bucket_size 64;
## Start: Timeouts ##
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 30;
send_timeout 10;
keepalive_requests 10;
## End: Timeouts ##
This is some default code to let NGINX know what to do. For security i added
server_tokens off;
This prevents outsiders looking up what version of NGINX the server is running. This prevent version weaknesses being easily exploited.
After the part above copy in this code
## Default Listening ##
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
This part makes NGINX listen on port 80 and any traffic it receives on port 80 (HTTP) it redirects to port 443 (HTTPS). It forces the connection to use a secure connection. listen [::]:80 is only required if you have users connecting on IPv6 addresses.
The next part is to configure NGINX to forward the traffic it receives to the correct location. Copy the code below into the same notepad.
##Server Block##
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name mysite.com;
Anything with # in front of it means that its a note or a disabled configuration.
From the code above change mysite.com to what ever your sub-domain name is. listen 443 ssl http2; means that NGINX listens on port 443 and uses the http2 protocol.
Next we look at adding our beefed up security into the config.
ssl_session_timeout 30m;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_certificate SSL/cert.pem;
ssl_certificate_key SSL/private.key;
ssl_session_cache shared:SSL:10m;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
Most of the above is to do with the ciphers to create the secure connection. ssl_protocols lists in order the protocols to use. TLSv1.2 is the most secure. These have replaced SSL which are now obsolete. In the very near future TLSv1.3 will make all the other versions of TLS obsolete. Preferred ciphers just list in the order of the ciphers used to create the secure connection.
So from the above we need to edit the following
ssl_certificate SSL/cert.pem;
ssl_certificate_key SSL/private.key;
This is the location of our cert.pem and private.key. I have them located in my NGINX folder in the following location C:\NGINX\config\SSL

To find out how to create the Certs please use the guide Easy Let's Encrypt Certificates At the bottom it describes how to create .pem certs.
add_header X-Xss-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
proxy_hide_header X-Powered-By;
add_header 'Referrer-Policy' 'no-referrer';
add_header Content-Security-Policy "frame-ancestors mysite.com emby.mysite.com;";
Most of the above is to do with the headers in html. They add extra security to the connection.
X-Xss-Protection - sets the configuration for the cross-site scripting filters built into most browsers. The best configuration is "X-XSS-Protection: 1; mode=block".
#
X-content-type-options - stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. The only valid value for this header is "X-Content-Type-Options: nosniff".
#
Strict-Transport-Security - is an excellent feature to support on your site and strengthens your implementation of TLS by getting the User Agent to enforce the use of HTTPS.
#
X-Frame - tells the browser whether you want to allow your site to be framed or not. By preventing a browser from framing your site you can defend against attacks like clickjacking.
#
Referrer Policy - is a new header that allows a site to control how much information the browser includes with navigations away from a document and should be set by all sites.
#
Content-Security-Policy - is an effective measure to protect your site from XSS attacks. By whitelisting sources of approved content, you can prevent the browser from loading malicious assets. Analyse this policy in more detail.
Next part we need to change from the above is
add_header Content-Security-Policy "frame-ancestors mysite.com emby.mysite.com;";
Change mysite.com emby.mysite.com to your Domain names. Also you need to add in here ALL your other sub domains that NGINX will manage. for example mysite.com emby.mysite.com sonarr.mysite.com
The next block is the location block, add this to your notepad.
location / {
proxy_pass http://127.0.0.1:*PORT;
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
The location block tells NGINX what to do when it received data and where to forward it to. It is also required for web sockets to work.
Edit the proxy_pass and point it to the location of your Service that you are running. If it is running on the same machine as NGINX you can leave it as http://127.0.0.1:PORT. If its running on another machine you will need to know the IP. http://192.168.1.10:PORT etc.
location / {
proxy_pass http://127.0.0.1:*PORT;
The whole config should now look like this.
worker_processes 2;
events {
worker_connections 8192;
}
http {
include mime.types;
default_type application/octet-stream;
server_tokens off;
gzip on;
gzip_disable "msie6";
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
text/plain
text/css
text/js
text/xml
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
image/svg+xml;
tcp_nodelay on;
sendfile off;
server_names_hash_bucket_size 128;
map_hash_bucket_size 64;
## Start: Timeouts ##
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 30;
send_timeout 10;
keepalive_requests 10;
## End: Timeouts ##
## Default Listening ##
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
##Server Block##
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name mysite.com;
ssl_session_timeout 30m;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_certificate SSL/cert.pem;
ssl_certificate_key SSL/private.key;
ssl_session_cache shared:SSL:10m;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
add_header X-Xss-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
proxy_hide_header X-Powered-By;
add_header 'Referrer-Policy' 'no-referrer';
add_header Content-Security-Policy "frame-ancestors mysite.com emby.mysite.com;";
location / {
proxy_pass http://127.0.0.1:*PORT;
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
Save the notepad as nginx.config in the following location C:\NGINX\config
Step 3 - Set NGINX as a Windows Service
To get NGINX to start with Windows we need to donwload an application called NSSM (Non-sucking service manager). Download it and extract it. You will have a choice to use win32 or win64 version. Choice the version that relates to your Windows installation. Copy the nssm.exe to C:\Windows\System32
Open up a command prompt (Run as administrator) type the following
nssm install NGINX
It will now display this

Fill in the Path to the NGINX.exe and the Startup Directory as above.
Click ok

Open up Service.msc and find the NGINX Service we just installed.
Right click and Start.

To Test, we can navigate to emby.mysite.com and it should bring up your Emby Server!
If you have any problems drop a comment below. I will also be creating a Troubleshooting NGINX post soon.