Set-Up and Securing Reverse Proxy with Nginx on Docker

Posted on 14 Feb 2021

Man drawing and explaining to a woman on dry-erase board

Photo by Kaleidico

Prerequisites

  • Basic knowledge of using Docker and docker-compose,
  • Already installed Docker and docker-compose, and
  • Have valid SSL/TLS on Your domain.

or you can read the previous post on how to install Docker and get free Let’s Encrypt SSL/TLS.

Docker Compose File

Your docker-compose.yml file, will look like this.

services:
  # other service
  web-server:
    container_name: web-server
    image: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./fullchain.pem:/etc/nginx/fullchain.pem
      - ./privkey.pem:/etc/nginx/privkey.pem
    ports:
      - 443:443
      - 80:80
# another configuration

Inside volumes configuration, there is 3 external mounted volumes :

  1. nginx.conf

    Contains Your web server or Nginx configuration file, like upstream, reverse proxy, serve the static file, etc.

  2. fullchain.pem

    The file fullchain.pem contains both your server certificate file and the intermediate (conveniently placed in the correct order). This means that you should always use fullchain.pem when configuring a server certificate in an application. - on Get Your Certificate Chain Right

  3. privkey.key

    The private key is a separate file that’s used in the encryption/decryption of data sent between your server and the connecting clients. A private key is created by you — the certificate owner — when you request your certificate with a Certificate Signing Request (CSR). - on Where is Your Private Key?

Nginx Configuration File

Your nginx.conf file, will look like this.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections  1024;
}

# other configuration

http {
    # First server block
    # The following configuration will redirect all traffic to https
    server {
        server_name                 _;
        listen                      80 default_server;
        listen                      [::]:80 default_server;
        return                      301 https://$host$request_uri;
    }

    # Second server block
    # Main web server configuration
    server {
        # Change into your domain name
        server_name                 yourdomain.tld www.yourdomain.tld;

        # Listening socket
        listen                      443 ssl http2 default_server;
        listen                      [::]:443 ssl http2 default_server;

        # HTTPS server optimization
        ssl_session_cache           shared:SSL:10m;
        ssl_session_timeout         10m;
        keepalive_timeout           70;
        ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers                 HIGH:!aNULL:!MD5;

        # SSL certificate chains
        ssl_certificate             /etc/nginx/fullchain.pem;
        ssl_certificate_key         /etc/nginx/privkey.pem;
        ssl_trusted_certificate     /etc/nginx/fullchain.pem;

        # Nginx Logging
        access_log                  /var/log/nginx/access.log;
        error_log                   /var/log/nginx/error.log;

        # First Proxy Pass
        location / {
            proxy_pass              http://first_service:port;
            # other configuration here
        }

        # Second Proxy Pass
        location /api {
            proxy_pass              http://second_service:port;
            # other configuration here
        }
    }
}

# other configuration

Sample Application

Clone this repo Setup & Securing Nginx Reverse Proxy in Docker, and move into the repo folder.

git clone https://github.com/dnwandana/setup-secure-nginx-reverse-proxy.git
cd setup-secure-nginx-reverse-proxy
  1. Copy Your fullchain.pem and privkey.pem into this folder,
  2. Change apiDomain with your domain.tld/api/ inside client/package.json file,
  3. Run docker-compose up -d, and then access Your domain in your browser.

Homepage Application Homepage Application

Application API Route

Application API Route

Application Sending Get Request

Application Sending Get Request