What's NginX?

NginX (pronounced Engine-X) is a web-server, and reverse proxy.  Basically, it can serve up web pages, and can provide a proxy service for incoming web requests.  It all sounds a bit generic, but that's because it is.  NginX can serve web pages, but can also direct requests for Web pages, Web Services, and Web Applications to the right place.  Essentially, it's a hub and router.  It receives a request for any number of web services, and routes the requests to the proper location.

NginX in and of itself, if configured through the terminal in configuration files.  It's not pretty, it's not overly difficult, but you definitely have to have a good feel for all of the options that can be set.

NginX Proxy Manager is a nice Graphical User Interface (GUI) for the user to utilize vs. having to edit and create a bunch of configurations.

Workflow of NginX Proxy Manager

When you want to route a user to a specific web page or site, NginX is a great tool for the job. NginX will listen on your server, and once it receives a request, will route the request to the appropriate service, server, page, or application.

Clarification of the term "Router"

I need to be clear about something here.  NginX is not an application router.  Many applications use routers to move you from page, or portion of a page or application, to another.  These are application level routers.   Also, NginX is not a hardware router, like the one on your home network that routes all of your network traffic to various machines, smart devices, etc.

NginX is a Proxy Router.  It acts as a proxy for the requested web page or site, and forwards that request on to the appropriate site on your server, then returns the response information to the browser.

Workflow Continued

Requests for websites come into a server on a standard port (generaly 80 or 443). When those requests are received, NginX will parse the request by name, and look through it's configuration files to see if any of them match for the request being made.

If I request fixitdelrio.com, NginX will look for a configuration file that tells it what to do with requests for that site.  If it finds a match it will then use the other information in that confiuration to push that request along to the appropriate server or service.

The configuration might tell NginX, "Hey, when you see fixitdelrio.com, send it to the IP 10.20.30.40 please."   So, since we asked so nicely, NginX does as requested.

For another site being run on the same server, like opensourceisawesome.com, NginX will send the request along to the same IP, but a different port.  While we make the request on the standard port 80, NginX knows that really that site is running on port 24356, and has in it's confguration file to push our request along to 10.20.30.40:24356.  Thus, we ask for opensourceisawesome.com, and don't have to know it's running on a special port.

What about SSL and Encryption?

NginX can also deal with SSL and Encryption, and can be quite helpful with it as well.

If I want to run lubbocklug.org on https instead of http, I can use NginX to help me do that.  I can use NginX-Proxy-Manager to tell the request for http://lubbocklug.org to always force the requestor over to https://lubbocklug.org, thus they never go to my site without encryption.

This is huge in today's world of unethical hackers.  Protecting our users is one of the most important steps we can take as self-hosters.

Okay, I'm tired of the Intro...tell me how to do it.

Information sourced from https://nginxproxymanager.com/setup/

First, you want to install Docker.  Docker CE (Community Edition) is a wonderful tool that uses a very lightweight virtualisation engine to run applications, web sites, and services.  You can hose many containers (a virtualized application server) on a single Docker install.

Instructions for Installing Docker CE will vary from Operating System to Operating System, so it will be better if you Google "How to Install Docker CE" and find the best instructions for your OS.

Once you have Docker installed, you will want to install NginX Proxy Manager.  This part is fairly straight-forward, so let's look at how it's done.

config.json

First you'll want to create a folder to hold your nginx-proxy-manager setup files.

On Linux / Unix / Mac, you can open a terminal shell, and do this command:

mkdir nginx_proxy_manager
Command to create a folder called nginx_proxy_manager

Next,  move into that folder:

cd nginx_proxy_manager

Now, let's create our config.json file.   You can use any text editor you want for this, so feel free to use emacs, vi, vim, or others.  I'll be using instructions for editing in nano.

nano config.json

This will open a blank text editor window.  You can simple copy and paste the code section below, then we'll edit it appropriately.  To copy it, just higlight the code with your mouse, trackpad, or finger, then do CTRL+C (Win, Linux, Unix) or CMD+C (MacOS).

{
  "database": {
    "engine": "mysql",
    "host": "db",
    "name": "npm",
    "user": "npm",
    "password": "npm",
    "port": 3306
  }
}

Now, paste the text into the blank text editor window.  Use CTRL+Shift+V for Linux, Unix, Win; and usse CMD+V for MacOS.

Now we need to just change a couple of the values in the file. We want to change the "user" value to something we know and can remember.  Using your arrow keys move to the user value ("npm"), and delete or backspace over it, then enter a new value for a username.  I used "brian", but feel free to use your own name, nickname, or username you like.

Now, let's change the "password" value as well.  We want to use the arrow keys again, to move to that value ("npm") and delete or backspace over it.  Next, enter a strong password. Strong passwordsa re longer than 10 characters, use upper and lower case letters, have at least 1 numbeer, and at least 1 special character (like #!<>^&*()-).   Make a note of this username and password (it's best to use a password manager like BitWarden if you can).  We'll need these two values in the next portion as well.   Also, make sure your new values have double quotes " around them.

To save our config.json file, use CTRL+O, then press  Enter/ Return, then CTRL+X to exit out of the nano editor, and back to your normal terminal.

If you want to verify that your config.json file exists, and is setup like above, use the cat command to view it's data.  

cat config.json

If you see the information you just entered and saved show in the terminal... great job!

docker-compose.yml

Next, we need a docker-copose.yml (pronounced yamuhl) file.  This file tells docker what images to pull, what containers to start, what to call them, how they connect to each other if there is more than one, and all kinds of other information.  It's, again, pretty straight-forward, so let's jump into it.

Still in our nginx_proxy_manager folder, we now want to create a file called docker-compose.yml.  So enter the command

nano docker-compose.yml

Copy the code below using CTRL+C (Win, Linux, Unix) or CMD+C (MacOS).

version: "3"
services:
  app:
    image: jc21/nginx-proxy-manager:2
    restart: always
    ports:
      # Public HTTP Port:
      - '80:80'
      # Public HTTPS Port:
      - '443:443'
      # Admin Web Port:
      - '81:81'
    environment:
      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'
    volumes:
      # Make sure this config.json file exists as per instructions above:
      - ./config.json:/app/config/production.json
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    depends_on:
      - db
  db:
    image: jc21/mariadb-aria:10.4
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
    volumes:
      - ./data/mysql:/var/lib/mysql

Now paste the text into the blank text editor window.  Use CTRL+Shift+V for Linux, Unix, Win; and usse CMD+V for MacOS.

Again, we need to edit come values in this file.  We want a couple of these values to match the values we changed in our config.json.  Using your arrow keys move down to the section titled # environment:.  Under that section you need to either remove the # symbol in front of the second line, or remove this entire section (3 lines).  

I suggest if you are not going to use IPv6, then make that section look like this.

environment:
      # Uncomment this if IPv6 is not enabled on your host
      DISABLE_IPV6: 'true'

If you intend to use IPv6, then change true to false, and ensure it's still surrounded by single quotes '.

Now use your arrow keys to move down to the section titled db:.  Below it, we want to chagne three values.

First let's change the value for MYSQL_ROOT_PASSWORD.  We, again, want to make this a strong, but different password from the config file earlier.

After that, change the MYSQL_USER value to match what we entered in our config.json file for "user", and our MYSQL_PASSWORD value to match what we entered in our config.json file for "password".  

Once those changes are made, save the file with CTRL+O, then press Enter / Return.  Next press CTRL+X to exit the nano editor.

Start the NginX Proxy Manager

Finally, we will use our docker-compose.yml file to fetch the docker images, and start our containers (yep, there are 2 conttainers - 1 for NginX Proxy Manager, and 1 for the MySql database for configs).

In the same terminal window, enter the command:

docker-compose up -d

if your user is not part of the `docker ` group, you may have to use

sudo docker-compose up -d

Then, enter your sudo password when prompted.

If all goes well, you should be able to browse to your server URL or IP address on port 81 to see the NginX-Proxy-Manager admin portal.

something like http://opensourceisawesome.com:81 <– of course using your own domain or IP.

If you see the admin portal, congratulations! You've got it setup!  Now NginX is listening on port 80 and port 443 for web-requests.  

The next part is setting up various sites for NginX to proxy.

Proxying Site Traffic with NginX Proxy Manager

Now that NginX Proxy Manager is up and running, let's setup a site.  Click on 'Proxy Hosts' on the dashboard.  The card will likely have a 0, and the view will be empty, or should, so we need to add a new host.  

Dashboard View

Now click on the 'Add Proxy Host' button on the upper right of the Proxy Hosts view.

You should see a modal (pop-up) window like the one below.

Add Proxy Host Modal Window

Enter the domain name you want NginX to listen for in the "Domain Name" field. Domain names should be entered wtihout http or https on the front.  so only enter something like billybobsbassboatsandboots.com or if you are listening for a subdomain inventory.billybobsbassboatsandboots.com

Next, enter the hostname or IP address of the server where the site you enteed in the previous step is running.  Finally, enter the port number on which that site is listening / hosting it's traffic.  If you're using Docker to host these sites, then you can see any port mapping using the docker ps or sudo docker ps command.

Click 'Save'.

If all goes well, the modal (pop-up) window will close, and you should see an entry in your Proxy Hosts view.

Now you can click on the domain name to have it open in a new tab.  If everything is setup properly, you should see your web site.

But what about SSL?

SSL is absolutely an option, and pretty easy to get setup with NginX Proxy Manager.  You do have to make sure that you've setup your domain to be reached on port 80.  Don't get confused.  The port you entered in the last step above, does not need to be 80, but the Domain Name you entered should not have a port added on the end of it...that's all it means.  

Essentially, you need to be able to get to billybobsbassboatandboots.com without having to add a specific port number.  So we don't want to have to do billybobsbassboatandboots.com:11232 or anything.

Once you are sure that your site comes up on port 80, you'll want to click on the three vertical dot icon at the right end of the line with your domain on it.

Click the 3-dot Menu Option

Select 'Edit' from the menu that is shown, and we'll edit our NginX entry.  In the modal (pop-up) window, we want to move to the second tab "Custom Locations".  In this section we just want to re-type the same domain name we entered on the first tab, but in the 'Location' field.

Next, click the drop-down menu under 'Scheme', and select "https".  Now enter the IP or Hostname address of the server we are proxying the traffic to (usually the same as what we entered on the first tab as well.  Finally, enter the port you mapped to 443 in the Port field.

Now we want to move to the third tab, "SSL".   Here you want to click where it says "None", and select "Request a new SSL Certificate".   If you want to force users to always go to the secure version of your site (which you almost always do), turn on the switch next to the "Force SSL" option.

Now enter your email address into the email field, and turn on the option next to "I agree to the LetsEncrypt Terms of Service".

Options to Request a LetsEncrypt SSL Certificate for your site.

Now click "Save".  It may take a minute or so, but if you are returned to the Proxy Hosts view, and no errors are displayed, then your site should now be available on https.

Conclusion

This process of proxying traffic through a single endpoint, is useful for controlling not only the traffic to and from your home or server, but also for allowing you to run multiple web-sites / hosts on a single server install.

Repeat the above steps for each site you are hosting, and over time you'll get a full list of sites being proxied by NginX.  You can add custom options as you become more familiar with NginX right inside the Edit modal as well (tab 4).  

I hope this is helpful to you, and please subscribe to my channel so you'll know when I release new Open Source, Self-hosted videos.