Skip to content

Nginx

Installation

Docker

With docker, you can install nginx with something like:

yaml
version: "3"
services:
  web:
    # https://hub.docker.com/_/nginx/
    # image: nginx:latest
    image: nginx:stable
    container_name: boilerplate_web
    # restart: unless-stopped
    volumes:
      - ./ui/dist:/srv/boilerplate/dist
      - ./web/static:/srv/boilerplate/static
      - ./web/ssl:/etc/nginx/ssl
      - ./web/default.conf:/etc/nginx/conf.d/default.conf
      # mount any static / public content for efficient serving directly
      # ./web/public;/srv/boilerplate/files/
    working_dir: /srv/boilerplate/
    ports:
      # for development
      - 127.0.0.1:8888:80
      # leave off '127.0.0.1' if you want to expose the service beyond localhost
      # (useful when you want to access dev instance of boilerplate remotely
      #  from e.g. a phone)
      # - 8888:80
      # for production
      # - 80:80
      # - 443:443
    # if the container doesn't run, there may be a problem with the nginx.conf
    # try running `docker-compose log web` for clues
    # (usually SSL keys have not yet been generated in `web/ssl`)
    # keep the container running to debug or run interactively with
    #     docker-compose exec web bash
    # entrypoint: ["tail", "-f", "/dev/null"]
    networks:
      default:
        aliases:
          - boilerplate.local
version: "3"
services:
  web:
    # https://hub.docker.com/_/nginx/
    # image: nginx:latest
    image: nginx:stable
    container_name: boilerplate_web
    # restart: unless-stopped
    volumes:
      - ./ui/dist:/srv/boilerplate/dist
      - ./web/static:/srv/boilerplate/static
      - ./web/ssl:/etc/nginx/ssl
      - ./web/default.conf:/etc/nginx/conf.d/default.conf
      # mount any static / public content for efficient serving directly
      # ./web/public;/srv/boilerplate/files/
    working_dir: /srv/boilerplate/
    ports:
      # for development
      - 127.0.0.1:8888:80
      # leave off '127.0.0.1' if you want to expose the service beyond localhost
      # (useful when you want to access dev instance of boilerplate remotely
      #  from e.g. a phone)
      # - 8888:80
      # for production
      # - 80:80
      # - 443:443
    # if the container doesn't run, there may be a problem with the nginx.conf
    # try running `docker-compose log web` for clues
    # (usually SSL keys have not yet been generated in `web/ssl`)
    # keep the container running to debug or run interactively with
    #     docker-compose exec web bash
    # entrypoint: ["tail", "-f", "/dev/null"]
    networks:
      default:
        aliases:
          - boilerplate.local

This is a good option to encapsulate all necessary settings for an application stack.

Local

On some servers with multiple services running (e.g. a server instead of a development machine), it may help to run one nginx server at the host level and configure that to proxy to other services as needed.

sudo apt-get install nginx
sudo apt-get install nginx

Configuration

http://nginx.org/en/docs/beginners_guide.html#conf_structure

https://www.digitalocean.com/community/tutorials/understanding-the-nginx-configuration-file-structure-and-configuration-contexts

The main config file is typically found:

/etc/nginx/nginx.conf

On a fresh install, by default it is configured to point to :

Can have as many server contexts as needed:

# main context

http {

    # http context

    server {

        # first server context

    }

    server {

        # second server context

    }

}
# main context

http {

    # http context

    server {

        # first server context

    }

    server {

        # second server context

    }

}

Generally these are configured in separate files in

/etc/nginx/conf.d/*.conf

In:

sudo vi /etc/nginx/sites-enabled/default
sudo vi /etc/nginx/sites-enabled/default

You should look at the following URL's in order to grasp a solid understanding of Nginx configuration files in order to fully unleash the power of Nginx.

https://www.nginx.com/resources/wiki/start/
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
https://wiki.debian.org/Nginx/DirectoryStructure

Then set it to run on startup

sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl enable nginx

See also: Startup Services

Disable the default site and add in the desired configuration:

sudo rm /etc/nginx/sites-enabled/default
sudo rm /etc/nginx/sites-enabled/default

Ok to use either /etc/nginx/conf.d/ or /etc/nginx/sites-available and link to the enabled ones in /etc/nginx/sites-enabled. Call the files something.conf

server {
  listen 80;
  listen [::]:80;

  server_name example.com;

  location / {
      proxy_pass http://localhost:3000/;
  }
}
server {
  listen 80;
  listen [::]:80;

  server_name example.com;

  location / {
      proxy_pass http://localhost:3000/;
  }
}

Alias vs Root

https://stackoverflow.com/questions/10631933/nginx-static-file-serving-confusion-with-root-alias

be sure to include trailing slash with alias directives!

Static Content

When developing web applications, it's tempting to use the application server to serve static content:

https://expressjs.com/en/starter/static-files.html

This works for local development, but becomes a headache when it's time to deploy your application publicly.

Using a dedicated webserver like nginx for serving static files removes that burden from the application server.

https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/

Auto Indexes

If you have static content that would benefit from a dynamic index, nginx can do that. For example, want to get a list that includes new files without manually knowing the new file path. Alternatively, an application server could navigate and iterate through the file system.

    location /static {
        alias /srv/static/;
        autoindex on;
        autoindex_format json;
    }
    location /static {
        alias /srv/static/;
        autoindex on;
        autoindex_format json;
    }

https://fuzzyblog.io/blog/nginx/2020/06/15/configuring-nginx-to-serve-a-directory-listing.html Configuring NGINX to Serve a Directory Listing https://stackoverflow.com/questions/24387118/nginx-list-static-files-directories-as-xml-json Nginx list static files/directories as XML/Json - Stack Overflow

https://duckduckgo.com/?q=nginx+list+directory+contents+as+json&t=ffab&ia=web nginx list directory contents as json at DuckDuckGo

Websockets

https://www.serverlab.ca/tutorials/linux/web-servers-linux/how-to-proxy-wss-websockets-with-nginx/

HTTPS / SSL

Self-signed

For local development environments, self signed is good enough. It makes sure that the application is configured correctly to work behind an HTTPS connection, but doesn't require an external certificate / local DNS entry.

https://codewithhugo.com/docker-compose-local-https/

https://medium.com/@codingwithmanny/configure-self-signed-ssl-for-nginx-docker-from-a-scratch-7c2bcd5478c6

https://medium.com/@oliver.zampieri/self-signed-ssl-reverse-proxy-with-docker-dbfc78c05b41

https://www.ssls.com/knowledgebase/how-to-install-an-ssl-certificate-on-a-nginx-server/

Use OpenSSL to create a self signed certificate

openssl req -subj '/CN=localhost' -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365

Let's Encrypt

Once it's time to publish your application, you'll need a domain name. If you have that ready to go, you can use Let's Encrypt for a certificate

https://medium.com/@pentacent/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71

Troubleshooting

Log files are typically stored in

/var/log/nginx

With containers

docker-compose exec web bash

then

nginx -t 

is super helpful for debugging nginx configurations

To see if the nginx process is running:

service nginx status

(On the nginx docker container, ps is not available)

To reload nginx without reloading all of the containers:

docker-compose -p boilerplate exec web nginx -s reload

For netstat:

apt-get update
apt-get install net-tools

netstat -pan | grep LISTEN

See also dedicated section for nginx

https://gitlab.com/charlesbrandt/public/-/blob/main/system/virtualization/docker.md#troubleshooting-nginx