SPICE | Nginx Proxy Config Guide - UMCST/SPICE-user-info GitHub Wiki

Nginx, along with many other webserver options, are incredibly powerful tools of which many people do not realize the full potential of. This guide will outline how the filestructure of Nginx is laid out but also to provide working examples of various methods of which one could use Nginx to achieve different functional goals.

How Nginx is Laid Out

While it may look really confusing at first, at least with less-sophisticated systems, the layout of Nginx is pretty simple. The primary files and directories you should know about are:

  • nginx.conf
  • conf.d

nginx.conf

As you may have guessed, nginx.conf is responsible for dictating a lot of the host-wide functionality of the service. While you can take a more in depth look at most of this functionality here, the only thing I'll point out is the lines containing the following:

include /etc/nginx/conf.d/.conf; include /etc/nginx/sites-enabled/

These are a couple of lines to point out because, depending on your method of setting up your Nginx modules, you're likely better off commenting out the include of the directory you're not using to prevent any unintended functionality where Nginx is finding configs for the same subdomain in both directories.

conf.d

While it pains me to say this, conf.d is the better choice in organizing configuration files in Nginx. As you may or may not know, historically, we would use the sites-available/sites-enabled structure (though only strictly for debian-based OS's) to dictate whether or not a site should be present depending on whether or not you have a sym-link present in sites-enabled to a config in sites-available. However, due to it's presence only on Debian and the admittedly more intuitive method of conf.d filestructure, I'll be moving forward with conf.d in this guide. I will, however, include a segment at the end of this guide on sites-available/sites-enabled since it's something that you'll very likely run into at some point or another (older infrastructure, etc.) and is something that you should be aware of.

Since we're going over the configuration setup later on, the only thing you really need to worry about is the naming scheme of files in conf.d. For every virtual host, whether its a url forwarder, a reverse web proxy, or actually pointing to a directory on the local machine, the filename has the format of .conf. So, if I own the domain spicelab.org and want to create a config for wazuh.spicelab.org, the name of my file in conf.d will be wazuh.spicelab.org.conf. And this is a strict requirement since Nginx does the virtual host lookup based on the filename.

Sample Configs

Reverse Web Proxy

If you didn't already know, a reverse web proxy allows you to forward user and web browser requests to web servers on a network, all while protecting the identity of the web server actually operating on these requests. This has multiple applications. From an administrative and cybsersecurity standpoint, it makes your network that much more secure since, if you configure your firewalls correctly, you only really need to worry about locking down access to one publicly accessible host as opposed to all of them since all of the traffic to the hidden hosts are only allowed from your own proxy server and nothing else. You can learn more here. A reverse web proxy also has basically a million other benefits and capabilities further than this, but for this guide, we're just going to focus on the config itself.

Sample Config

server {
    listen 80;
    server_name rocketchat.ad.sweetcentral.org;

    location / {
            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_pass https://sourpatch.sweetcentral.org;
    }
}

Now you can really just copy paste this config for the most part and you'd only have to change a couple of things.

listen 80; - You could have this listening on 443 and just have an additional redirect to make sure that port 80 is redirected to 443, but it's not strictly necessary.

server_name - Subdomain that you want the proxy host to be reachable from. Make sure that your A record in DNS is pointing to the host that this config is present on (the proxy host) and not the host that it's going to be ultimately pointed at.

proxy_pass - Now this is the subdomain name of your host you want the proxy host to point to. In terms of https vs. http and such, the same rules apply to this as everything else (handle 80 -> 443 redirects internally, etc.)

HTTPS Redirects

Https redirects are another great thing to implement in your virtual host setup in Nginx. If you weren't already aware, when you search google.com in a browser, for example, you're doing so over port 80. But you may notice that when you actually press enter, you see that "https://" automatically pops up in the search bar even though you didn't specify to use Https. Google is using what's called an https redirect where the traffic coming in over port 80 is redirected to port 443 that was the more secure https protocol can be used. Below I've included two sample configs, one that does a global https redirect on your machine as well as one that does it for a specific site, both of these having their own advantages.

Sample Config

server {
    listen 80 default_server;

    server_name _;

    return 301 https://$host$request_uri;
}

As you can see, https redirects are exceedingly simple to put together, but they're also really easy to understand!. In this situation, if you're doing a global redirect, you're going to want to put this in your "default.conf" file since you can see I'm using the "default_server" directive in the listening port line. Then, since I have "server_name _;", that indicates that this applies to all subdomains that are hitting the server, regardless of name. Then, we use a 301 redirect (moved permanently), to re-route the user's request to it's https equivalent.

Sample Config

server {
    listen 80;

    server_name foo.com;
    return 301 https://foo.com$request_uri
}

More often than not, however, you'll likely be using site-specific re-routes since while a little less clean than a global redirect, it's far more modular and will cause you less problems when scaling your infrastructure in the future. Ultimately, a global redirect is fine on a production webserver and may even be encouraged since it leaves no chance of accidentally leaving a server on http, but for any kind of development environment, it's just really annoying and time-consuming to be constantly generating ssl certs for test servers. In terms of the differences in this config that I just provided, you can see that I'm no longer using the "default server" directive since, in this situation, this server block would be included in the foo.com.conf file instead of the default.conf file. Additionally, you can see that the "server_name" and 301 redirect are adjusted accordingly to accommodate for this singular site.

I would also go over configuring SSL for servers, but with the sheer amount of variation in automatic and manual implementation of it, I'm going to leave it be for now, though I'll probably make a guide for using Certbot with Nginx for configuring SSL through the command line. Once that is created, it will be linked here if you want to learn some more about that. Additionally, since in the case of Certbot, and potentially other tools, the ssl config is automatically applied to the site config, you don't necessarily need to know much about what's going on under the hood.

.conf files for your subdomains. In Nginx's current state, the whole conf.d | sites-available/sites-enabled dichotomoy can be a little confusing, however there's a bit of useful information I think I can provide for this situation. While I (and many others, to my knowledge) prefer the sites-available/sites-enabled setup where you can just set a sym-link in sites-enabled to easily manage what sites are enabled vs. disabled, this isn't really the best practice nowadays. At this point, not only is sites-enabled/sites-