Self-signed SSL

1) Generate SSL key

sudo openssl req -new \
-newkey rsa:4096 -x509 -days 365 -nodes \
-subj /C=US/ST=NY/L=NY/O=NA/CN=localhost \
-keyout KEY_DIR/insecure.key \
-out KEY_DIR/insecure.pem

KEY_DIR can be arbitary. But it has to be correctly pointed in the server.conf

2) Generate dhparam

# use 4096 in production. But it may take a bit longer to generate
sudo openssl dhparam -out KEY_DIR/dhparam.pem 2048

3) Map the keys to docker

In nginx Dockerfile, add

RUN mkdir /etc/ssl/nginx

In prod-compose.yml map the KEY_DIR volume and open port 443 under nginx service

Allow HTTPS traffic to host

sudo ufw allow https
    nginx:
      build:
        context: .
        dockerfile: Docker/prod/nginx/Dockerfile
      ports:
        - "80:80"
        - "443:443"
      volumes:
        # app creates a docker volume, which is inturn mapped here
        - static_files:/vol/static
        - ${PWD}/Docker/prod/nginx/servers.conf:/etc/nginx/conf.d/servers.conf
        # ssl keys
        - ${PWD}/Docker/prod/nginx/ssl:/etc/ssl/nginx

4) Point paths to the key in server conf

Make sure to redirect http traffic to https

yml
server {
    listen 443 ssl default_server;
    server_name localhost;

    # redirect http traffic to https
    # 444 is the WAN port
    error_page  497 https://$host:444$request_uri;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 5m;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;
    resolver_timeout 5s;
    #add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";

    ssl_dhparam /etc/ssl/nginx/dhparam.pem;
    ssl_certificate /etc/ssl/nginx/private/insecure.pem;
    ssl_certificate_key /etc/ssl/nginx/insecure.key;
    ssl_trusted_certificate /etc/ssl/nginx/private/insecure.pem;

    location / {
        try_files $uri $uri/ @python_django;
    }

    ...
}

When port 443 can not be opened

Sometimes, ISP blocks port 443

In such cases, forward someother WAN port to LAN port 443 and access the webpage as

url
https://domainname.com:PORT_NUM