Deploy Django with SSL and Nginx on Google Cloud Platform Using Ubuntu VM

0
4579

This article is a sequel to the earlier one on deploying Django ‘on GCP, which was carried in the December 2019 issue of OSFY. It guides users on installing Nginx, enabling SSL and controlling the Django application using Supervisor to ease the process.

As you know, Nginx (http://nginx.org/) is an HTTP server which listens to Port 80 and can redirect to your application. We can also configure the SSL certificate and related configurations in Nginx.

sudo apt-get install nginx

You can check the status of Nginx by running the following command:

sudo systemctl status nginx.service

Creating an SSL certificate
We have different authorities providing SSL certificates — GoDaddy, Comodo, DigiCert, etc, but here, we are going to use Let’s Encrypt (https://letsencrypt.org/) — an organisation that provides free SSL certificates. (Let’s Encrypt is a free, automated, and open certificate authority brought to you by the non-profit Internet Security Research Group.)

I have used ZeroSSL (https://zerossl.com/) to access Let’s Encrypt, but have made the process simple to create, verify and download from the ZeroSSL online tool. Once the certificate is generated, you may scp the certificate to your GCP VM, where you have your Django application running.

Making changes in Django settings
For a production environment, you have to change debug= true to false, as follows:

debug=false

You may also add the security parameters given below to your Django settings:

SECURE_PROXY_SSL_HEADER = (‘HTTP_X_FORWARDED_PROTO’, ‘https’)
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

Installing and configuring Supervisor
Supervisor helps us to automate the starting and stopping of the Django process in production, as follows:

sudo apt-get install supervisor

Configure the Django app for Supervisor in the /etc/supervisor/config.d/<<your project name>> file sample content is shown below:

[program:your_project_name]
command = /usr/bin/python3 /path/to/project/manage.py runserver 0.0.0.0:8000 ;
Command to start app
user = vm_user_name ;
User to run as
stdout_logfile = /path/log_file_name ; Where to write log messages
redirect_stderr = true ;
Save stderr in the same log
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ;
Set UTF-8 as default encoding

The above config file instructs Supervisor what to run and where to write logs. You have to run the commands given below to make Supervisor understand the configuration for your application:

sudo supervisorctl reread
sudo supervisorctl update

The commands given below are for starting, stopping and restarting the application:

sudo supervisorctl start project_name
sudo supervisorctl stop project_name
sudo supervisorctl restart project_name
sudo supervisorctl status # to check status and make sure app is running

Nginx configurations
We have our application running in Port 8000, which we triggered from Supervisor. Now, it is time to configure the HTTP server and redirect Port 80 requests to 8000 and also, configure SSL for our app. Make sure Nginx is running, by using the command given below:

sudo systemctl status nginx.service

You can configure your app for Nginx in the file given below:

/etc/nginx/sites-available/project_name_here

Here is a sample configuration:

upstream app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response
# for UNIX domain socket setups
# server unix:/tmp/gunicorn.sock fail_timeout=0;
# for a TCP configuration
server VM_IP:8000 fail_timeout=0;
# above statement will forward request to django application which running on port 8000
}

# below section is to forward default request (to http port 80) to SSL port 443
server {
listen 80;
server_name host_name_or_IP_or_domain_name www.host_name_or_IP_or_domain_name;
return 301 https://$server_name$request_uri;
}

server {
# use ‘listen 80 deferred;’ for Linux
# use ‘listen 80 accept_filter=httpready;’ for FreeBSD
listen 443 ssl; # <-
ssl on; # <-
ssl_certificate /path/to/ssl/certificate; # <-
ssl_certificate_key /path/to/ssl/certificate_key; # <-
client_max_body_size 4G;
# set the correct host(s) for your site
server_name host_name_or_IP_or_domain_name www.host_name_or_IP_or_domain_name;
keepalive_timeout 5;
# path for static files
root /path/to/static/files;
location /static/ {
alias /path/to/static/files;
}
location /media/ {
alias /path/to/static/media/files/;
}

location / {
# checks for static file, if not found proxy to app
try_files $uri @proxy_to_app;
}
location @proxy_to_app {
}

location @proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
# we don’t want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_pass http://app_server;
}

error_page 500 502 503 504 /500.html;
location = /500.html {
root /path/to/app/current/public;
}
}

Link the site to site enabled list,
sudo ln -s /etc/nginx/sites-available/project_name /etc/nginx/sites-enabled/project_name
sudo service nginx restart
sudo systemctl status nginx.service

Now, you can access the application by its HTTPS. The HTTP request will be forwarded to HTTPS, as per the Nginx configuration.

LEAVE A REPLY

Please enter your comment!
Please enter your name here