These are some notes I made when working on a customisable Nginx (also I made some other examples).

Nginx is many things, a super fast web server, a streaming server, a reverse proxy, load balancer, cache, and probably a lot more. Whats good about it?

  • Configuration is intuitive (based on C Structs)
  • It is asynchronous, so is highly performant with concurrent requests and has low memory usage.
  • Caching and video streaming are relatively easy to set up

Unlike Apache, you can't embed server side programming languages into Nginx. However, thats where the reverse proxy comes in (more later).

Installing Nginx

(The below is one way to install Nginx, but you are better off using docker tbh)

On a Mac you can install using homebrew brew install nginx.

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that nginx can run without sudo.

By default nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx at login:

ln -sfv /usr/local/opt/nginx/*.plist ~/Library/LaunchAgents

Set logs: /var/log/nginx

Then to load nginx:

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist

Or, if you don't want/need launchctl, you can just run nginx

Take a look at the 'nginx.conf' file. There are four 'contexts' - main, server, upstream, and location. All of these contain 'directives' - instructions for Nginx.

Reverse proxy

A reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client as though they originated from the proxy server itself -


With Nginx being asynchronous and a reverse proxy you have to configure all requests for dynamic content to use the upstream module.

Say you have 2 node apps and a static site. You want to have endpoints like:

An API would be running on port 8000 for example, and the admin section on port 8080. We would set them up as upstream in our nginx.conf file:

upstream api {
    server localhost:8000;

upstream admin { server localhost:8080; }

server {

location /api { proxy_pass http://api; }

location /admin { proxy_pass http://admin; }



Contexts/block directives are a bit like scope, server {} is a context.

Directives are key/value pairs like listen: 80;

server {
  listen: 80;
  root: '/path/to/your/sites';
  index: index.html;
  location / {
    default-type: 'text/html';
  • Standard directive - Set a value. Can only be defined once within a single context. It can be overwritten by a child context.
  • Array directive - set multiple values in single identifier. Can be used multipal times
  • Action - performs an action when triggered
  • try_files will look for files, space separated, in turn until it finds something. If nothing is found you can set a default to =404

Inheritance straight down from parent context http, server, location.

There are implicit variables available to us, for example the $url which equates to the url nginx variables.

Multiple sites

Digitalocean has a great tutorial on running multiple sites.


Digitalocean have a great tutorial about how to create an ssl certificate.

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /usr/local/etc/nginx/ssl/nginx.key -out /usr/local/etc/nginx/ssl/nginx.crt

Using with Node