Introduction

In this blog, we will use a simple Django project and set it on an Ubuntu 22 server with the help of Gunicorn and Nginx. For the Database part, we will be using the PostgreSQL database. We will set up the PostgreSQL on the same server. Once the project and database are set up, We will configure the Gunicorn application server to interface with our application. We will then set up Nginx to reverse proxy traffic to Gunicorn, giving us access to its security and performance features to serve our apps.

In this blog, we will not be creating a new Django project for setup, we will use one of the previously created demo project. As we are not creating a Django project from the start, we will also discuss things to be taken care of while setting up a Django project for the production environment. We will use the wsgi for setup, so we do not cover any async functionality.

Requirements

  • To follow the blog you should have the user with sudo privileges on the server
  • We will require the public IP of the server
  • Email for sending all kinds of system emails to users and also to project admins.
  • Domain for HTTPS setup (Optional)

Basic intro of Nginx and Gunicorn

If you are reading this article, you should be familiar with Django, So I am not adding extra paragraphs for Django’s intro. When a user sends a request, the request is received by the Nginx on the server. Nginx will forward the request to the Gunicorn via socket and Gunicorn send the request to the Django application to process the request and send the response back to the user.

We will require Nginx and Gunicorn both because both have their limitations and to achieve all the required functionality we need to use both. You can read more about this on the below stack overflow links.

Requirements and installation of libraries

Now let’s install the required libraries and packages on the server. First, let’s update the apt packages index with the below command. If you are setting up this on an existing server, you can skip the below command.

sudo apt update

On the server, I am using Python version 3.10, you can check your version by running the python3 -V command in the terminal. Please make sure you are using the same Python version as the development environment of your project to avoid any unnecessary errors. Now let’s install the required packages on the server with the below command.

sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx gunicorn

The above command will install PostgreSQL, Gunicorn, Nginx, and a couple of other Python libraries. Once all the required packages are installed successfully without any errors we can move to the next part.

Setup PostgreSQL

Let’s dive into creating the foundation for your Django app’s data storage – the database and its user.

By default, Postgres relies on “peer authentication” for local connections. it means if your operating system username matches a valid Postgres username, you can log in without extra steps.

During Postgres installation, an operating system user named “postgres” is created. This user corresponds to the administrative Postgres user of the same name. We’ll use this account for administrative tasks using sudo with the -u option to specify the username.

Now let’s log into the interactive Postgres session with the below command.

sudo -u postgres psql

Create a new database for the project by running the below command in the same terminal. You can give any name to your database. I am using the ‘demodb’ name for demo purposes.

CREATE DATABASE demodb;

Now let’s create a new PostgreSQL user for our project with the below command. I am using ‘demouser’ as a username, you can set any username.

CREATE USER demouser WITH PASSWORD 'Hello#1122';

Once we create the user, let’s fine-tune their connection parameters to improve performance. This avoids querying and setting values every time a connection opens. The Django project itself recommends these all. Source: Optimizing PostgreSQL’s configuration

  • We’ll set the default encoding to UTF-8, which aligns with Django’s expectations for handling text data.
  • We’ll configure the default transaction isolation level to “read committed.” This ensures reads only encounter committed transactions, preventing inconsistencies.
  • Finally, we’ll establish the timezone. By default, Django projects use Coordinated Universal Time (UTC).

Run the below commands one by one to make all these 3 changes to the database. If you are using any other username for the PostgreSQL user, make sure to change the username before running the command.

ALTER ROLE demouser SET client_encoding TO 'utf8';
ALTER ROLE demouser SET default_transaction_isolation TO 'read committed';
ALTER ROLE demouser SET timezone TO 'UTC';

Now need to make the admin of our new user to the project’s database by running the below command to give all the permission and full access to the database. Make sure to change both names if you are using different names.

GRANT ALL PRIVILEGES ON DATABASE demodb TO demouser;

Once all is done, exit the PostgreSQL session with the \q command. If everything runs properly, you will see a response similar to the below screenshot for all the commands.

You can read more about PostgreSQL setup on How To Install and Use PostgreSQL on Ubuntu 20.04

Project setup with a virtual environment

Now let’s move to the next step, I am using one of the existing projects for the demo, you can use this tutorial to create the same project from scratch for learning purposes. If you have any existing Django project you can use that too. I am cloning the below git repo, which is the same as the tutorial.

NOTE: The project we are using is built for learning purposes, not a production-ready project, We are using it just for the demo.

In the project, we have used Django’s authentication system and built register and login pages. just a simple project with a couple of routes. We have used the SqlLite in the Tutorial, but for the production, we will be moving to PostgreSQL for better performance and reliability.

We can change the database backend on Django very easily if we don’t have any existing data and database-specific queries in the project. Some ORM queries will require a specific database to run.

There are a couple of other required changes too in the project for production deployment, we will cover it down the line.

Clone the project with the below command and change the current working directory to the project’s root directory.

git clone https://github.com/pragnakalpdev28/blog-django-auth-demo-basic.git
cd blog-django-auth-demo-basic/

Now create the new virtual environment within the same project directory. We have already installed the venv library in the requirements part. we will be using that. Create a new virtual environment with the below command in the same directory.

python3 -m venv env

Activate the environment with the below command before installing the project requirements. If the environment is not activated, all the libraries will installed globally.

source env/bin/activate

If everything works fine and environment is activated successfully, you will see the environment name in the terminal within the round brackets as per the below screenshot.

Now install the requirements with the below command from the req.txt file.

pip install -r req.txt

The requirements file does not have the PostgreSQL client library to communicate with Postgresql. install it with the below command in the same environment.

pip install psycopg

If everything is installed without any errors, you will see the responses in the terminal similar to the below screenshot.

Once this is done, we are required to update the database configuration in the project’s settings.py file. update the DATABASES dict as described below. If you are using a different database name, username, and password, make sure to change the values.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'demodb',
        'USER': 'demouser',
        'PASSWORD': 'Hello#1122',
        'HOST': 'localhost',
        'PORT': '5432'
    }
}

You can check more about Postgresql configuration on Django’s official documentation.

Now run the below commands to perform the migrations with the PostgreSQL database to create tables on the new database.

python3 manage.py makemigrations
python3 manage.py migrate

Once both the migration commands run successfully, create a super user with the below command. If there is any error in the project or the database connection, fix the error and run both the migrations commands again.

python3 manage.py createsuperuser

Provide the username and password for the admin user. Once everything is done successfully, you can see the response similar to the below screenshot in the terminal.

If the admin user is created successfully. the project is set up properly without any errors. You can check it by running the Django development server.

Once the project is set up, we move to setting up the Gunicorn.

Gunicorn setup

First, we are required to install the Gunicorn in the virtual environment, Install Gunicorn with the below command. In the requirements part we have installed the Gunicorn as a system package, we also need to install it in the environment. Make sure the virtual environment is active before running the command.

pip install gunicorn

Next, run the below command to run the Django project with the Gunicorn. Make sure to change the django_auth_demo with your project name if you are using some other Django project before running the command. Keep the .wsgi as it is after the project name.

gunicorn --bind 0.0.0.0:8000 django_auth_demo.wsgi

If the server runs without any errors, you will see a response similar to the below screenshot.

Once this is done, we can move to the next step, the required changes in Django for production setup.

Required Changes for Production

To set up any Django project for production, we will required to make a couple of changes to improve the security, stability, and performance of the project. Here, we are making the most required changes, you can find all the recommended changes on the Deployment checklist.

  • Required to set ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS variables in the settings.py file.
  • Set ADMINS list for receiving internal server error emails and required configured email to send system emails.
  • Move the sensitive variables to the environment file from the settings file.
  • Set error pages.
  • Change DEBUG variable.
ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS

Open the project’s settings file with any text editor.

I am using (Also recommended) the vscode with the SSH connection to open the project folder with the vscode. You can use any text editor of your choice for the modifications.

First, add ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS in the settings.py file as described below. Make sure to replace the YOUR_PUBLIC_IP with the actual IP of your server.

SECURITY NOTE: Do not keep the * in any of these lists. Keep only the domain name or IP address in the list. Also, remove the localhost or 127.0.0.1 from both the list if present. This is important for the project’s security to avoid unwanted access to the site. You can keep multiple domains or IPs in both lists.

ALLOWED_HOSTS = ['YOUR_PUBLIC_IP']
CSRF_TRUSTED_ORIGINS = ['http://YOUR_PUBLIC_IP/']
ADMINS

Next, add the ADMINS list to the settings.py file to receive any internal server errors directly in emails. Django will send all the internal servers to all the admins of the projects if the DEBUG is set to False. We will change the DEBUG variable later on. Please make sure that you replace the dummy values with your name and email. You can add N number of emails to the ADMINS list.

ADMINS = [('summay1', 'hello1@gmail.com'),('summay2', 'hello2@gmail.com'),]
Email configurations

Next, we need to configure email variables for the server’s sending email. If you have already configured it, you can skip this step.

We will require the email ID, Password, Host, and Port number variables for the configurations. Set the below variables in the settings.py file. Django will use this email for sending all the system emails. Make sure, you replace all the necessary values based on your email configuration.

EMAIL_HOST = "smtp.gmail.com"
EMAIL_HOST_USER = 'hello1@gmail.com'
EMAIL_HOST_PASSWORD = '123456789'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FORM_EMAIL = 'hello1@gmail.com'
EMAIL_FROM = 'hello1@gmail.com'
SERVER_EMAIL = 'hello1@gmail.com'

Note: The above configurations are for the Gmail server. if you are using Gmail, just change the email and password variables. Google doesn’t allow the use of the Google account password for programmatically sending emails. You can follow this document to create an app password for your Google account.

DEBUG

For the production, we also need to change the DEBUG variable to False . The variable will affect below functionality of Django. We will change the variable when we set up the service and socket files for the project, till then keep it True This will help to debug errors before the final configuration of the service and socket files.

  • Django was not responsible for serving the static files, This need to be handled by the Nginx.
  • Do not display any errors on the page and in the server logs. All the internal server errors will be sent to admin emails to notify the developers/admins about errors.
  • Required the sending email configured for sending all kinds of error mail. The same email configuration will be used for all the system emails.
  • Required the CSRF_TRUSTED_ORIGINS variable with the list of all the domains, to avoid form submission requests from any third-party site or specious domain.
  • Set required HTML pages with the error code as a file name in the main templates directory, Django will fetch the page based on the error code and display it on the page.
    • Example. If any internal server error occurs while processing the request, admins will receive the error mail and Django will display the 500.html template to the user.
  • There are a couple of other useful features for the development, that also will be disabled by changing the variable.
Setup Error pages

Let’s add the 500.html , 400.html , 404.html , 403.html , and other similar error pages inside the main templates folder of the project. Django will use these pages based on the error code and display it to the user in case any error occurs while processing the request. If you are using any theme, use error pages of your theme or create simple HTML pages to notify a user about the error.

Move passwords and other sensitive variables to separate file

For security reasons, it’s a good practice to keep all the sensitive information in a separate file and access it from there,

Create a new settings.ini file to store all the variables. I am creating it in the project folder, but you can keep it anywhere on the system. I am moving SECRET_KEY, DATABASES - USER , DATABASES - NAME , DATABASES - PASSWORD, EMAIL_HOST_PASSWORD to the ini file. If you have more variables like this, you can add them here. Make sure you replace all the values with actual values.

In the ini file make sure there is no extra space around the = and at the end of the line. In the file all the values will be in string format but no need to use a single quote or a double quote around the values. quotes around value will be also considered as a part of actual value while reading the data.

[keys]
django_sec_key=YOUR_SECRET_KEY

[database]
db_username=YOUR_DB_USERANEM
db_password=YOUR_DB_PASSWORD
db_name=YOUR_DB_NAME

[email]
email_password=YOUR_PASSWORD

Next, we need to update the setting file to get values from the ini file and assign them to the variables. We will access the variables with Python’s configparser library. If you have added extra variables to ini file, make sure you set those variables too.

from configparser import RawConfigParser 

env_variables = RawConfigParser()
env_variables.read('INI_FILE_PATH')


SECRET_KEY = env_variables.get('keys', 'django_sec_key')
...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': env_variables.get('database', 'db_name'),
        'USER': env_variables.get('database', 'db_username'),
        'PASSWORD': env_variables.get('database', 'db_password'),
        'HOST': 'localhost',
        'PORT': '5432'
    }
}

...
EMAIL_HOST_PASSWORD = env_variables.get('email', 'email_password')

Reference for more details on StackOverflow about environment variables.

You can check the list of all the warnings for the production deployment by running the below command in the project’s root folder after activating the environment.

python3 manage.py check --deploy
Static files

Next, we need to set the static files, when we serve a Django application with Gunicorn and Nginx, Nginx is responsible for serving the static files.

First, set the paths for the static files in the project’s settings file. Add the below 2 variables after the STATIC_URL variable in the setting file. If you have multiple folders for the static files, you can add that inside the STATICFILES_DIRS List, I have kept one sample for reference.

STATIC_ROOT = BASE_DIR / 'static'
STATICFILES_DIRS = [
    # BASE_DIR / 'templates/static', # Folder does not exist in the project
]

Next, open the terminal in the project’s root folder, activate the environment, and run the below command in the terminal, This will copy all the static files and place them inside a static folder under the project’s root folder.

python3 manage.py collectstatic

Next, we need to configure the Nginx to server the application with the IP address of Django. But before that start the Gunicorn server to link the project with the Nginx config file by running the below command. Make sure to change the django_auth_demo with your project name if you are using some other Django project before running the command.

gunicorn --bind 0.0.0.0:8000 django_auth_demo.wsgi

Nginx configuration

First, we need the public IP of the server. You can find it on the dashboard of your service provider. We will require it for the Nginx configuration. Once you get it, we can move to the Nginx configurations part.

Open any text editor of your choice, and prepare the configurations as described below.

First, configure the root proxy and other variables. set the listen , server_name, and location variables as described below, Make sure you replace the YOUR_SERVER_IP with the public IP of your server. keep ; at the end of all lines. apart from this keep everything else as it is. You can find more about Nginx configuration on its official docs.

server {
    listen 80;
    server_name YOUR_SERVER_IP;

    location / {
        include proxy_params;
        proxy_pass http://0.0.0.0:8000;
    }
}

Next, we need to set the location block for loading the static files with the Nginx. Add one more block as described below before closing the main server block. Make sure you replace the PATH_OF_YOUR_PROJECTS_HOME_DIR with the project’s root folder. Do not add static at the end of the path and also do not add the / at the end of the path and keep the ; at the end of the line.

location /static/ {
    root PATH_OF_YOUR_PROJECTS_HOME_DIR;
}

Once everything is done, your configurations will look something like this.

Note: Please make sure that there is no extra space at the end of any line, not even after the ; . It will generate an error.

server {
    listen 80;
    server_name 123.123.123.123;

    location / {
        include proxy_params;
        proxy_pass http://0.0.0.0:8000;
    }

    location /static/ {
       root /home/ubuntu/blog-django-auth-demo-basic;
    }
}

Once you are done with the configurations in the text editor, create and open the new file inside the /etc/nginx/sites-available/ folder. I am giving the configuration file name demo_config you can change the name as per your project. (Note: Keep the file name the same as the project name to avoid confusion later with the multiple config files).

If you have any existing configuration files of the Nginx, you need to modify the file as per your existing configurations. The Nginx configurations we have configured, are for fresh servers only and create a new configurations file. Keep the Gunicorn server running and open the new terminal. open the configuration file with the below command with Vim editor. Copy the configurations from the text editor and paste them into the Vim editor (Ctrl + Shift + v is a shortcut to past the configuration in the vim editor).

sudo vim /etc/nginx/sites-available/demo_config

Now save and exit the file. To save and exit the VIm editor, press esc This will move the cursor at the bottom with the : symbol, and press the wq to save and exit the file.

Next, we need to enable the file by linking it with the sites-enabled dir by running the below command. Please make sure to replace the file name if you are using any other file name for the Nginx config file.

sudo ln -s /etc/nginx/sites-available/demo_config /etc/nginx/sites-enabled

Test the nginx configurations with the below command.

sudo nginx -t

If you get the response with test is successful we can now restart the Nginx service to apply the new configurations with the below command.

sudo systemctl restart nginx

Testing the configurations

Before preparing the service and socket files, confirm that all the back-end functionality working as expected. If there is any error in the project, need to fix it before preparing the service and socket files for the project. We have kept the DEBUG variable True To display errors on the page and in the terminal.

If you are using the same git repo as mine open the http://YOUR-SERVER-IP/egister page, and register a new user. Once you are done with the register, open the /login route to logging in with the username and password. If everything works you will see the Login success message on the page. If you are using any other Django project you can review the functionality as per your project.

Next, open the /admin to check whether static files are loading or not. if you see the page the same as the below image, Congratulations, You have done great till now. You can move to the next step and skip the below steps. If you faced the error, follow the below steps to fix the error.

If you are following everything step by step, the Static files error will solved with the below steps. If not you need to debug the error.

This happens because of different user for the Nginx service. Nginx uses the www-data user by default. We have been using the default user or some other user till now to follow all the steps.

There are 2 ways to fix it, The First is by permitting to access files created by other users and the second is by changing the Nginx service user to some other user.

We will follow the second option for easy configuration. By default, ubuntu has a user called ubuntu we will run the Nginx service with that user. If you are using any other user, you can set that too for the Nginx service.

Open the Nginx config file with the below command.

sudo vim /etc/nginx/nginx.conf

In the first couple of lines, you will find the user variable, and replace the www-data with ubuntu or any other username if you are using some other system user. Save the file with the esc and wq commands. now before restarting the Nginx, check for any errors with the below command in the Nginx configuration.

sudo nginx -t

If you get a success message, restart the Nginx service. with the below command.

sudo systemctl restart nginx

After the restart, check all the functionality of the site. If everything works as expected we can move to the next step.

Service and Socket Configurations

Currently, we are serving the application by terminal command, but to keep the application running in the background without the terminal, we need to set up the system service which will run in the background and we can close the terminal.

I will use the demo_setup.service and demo_setup.socket names for the service and socket files. You can give any name to the service and socket files (Recommended: Keep the file name same as the project name). We need to keep both the files in the /etc/systemd/system/ folder.

First, let’s prepare the socket file. Copy the below code to any text editor. You can change the Description based on your project. Make sure you replace the demo_setup from the ListenStream variable if you are using some other names for the service and socket file to avoid extra confusion.

[Unit]
Description=Demo description for setup.

[Socket]
ListenStream=/run/demo_setup.sock

[Install]
WantedBy=sockets.target

NOTE: Make sure there is no extra space at the end of any line. Extra space will generate unusual errors in the production so make sure everything is fine.

Once you are done, open the socket file with the below command and paste the configurations in the file.

sudo vim /etc/systemd/system/demo_setup.socket

Save the file and exit the terminal. Next, let’s prepare the service file which will finally connect everything and make the site accessible with the terminal. Copy the below code in a text editor. We will required to make a couple of changes based on your setup.

[Unit]
Description=Demo for Django production setup
Requires=demo_setup.socket
After=network.target

[Service]
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/blog-django-auth-demo-basic
Environment="PATH=/home/ubuntu/blog-django-auth-demo-basic/env/bin:/usr/bin" "PYTHONUNBUFFERED=True"
ExecStart=/home/ubuntu/blog-django-auth-demo-basic/env/bin/gunicorn \
 --error-logfile /home/ubuntu/blog-django-auth-demo-basic/logs/error.log \
 --access-logfile /home/ubuntu/blog-django-auth-demo-basic/logs/access.log \
 --capture-output \
 --enable-stdio-inheritance \
 --workers 2 \
 --log-level debug \
 --bind unix:/run/demo_setup.sock \
  django_auth_demo.wsgi:application

[Install]
WantedBy=multi-user.target
  • Description: You can change it as per your project.
  • Requires: If you are using any other file name for your service and socket. replace the demo_setup with the file name. Keep the .socket at the end of the file name.
  • WorkingDirectory: Change the path with the project’s root folder. Make sure not to put the / At the end of the line.
  • Environment: Just replace the /home/ubuntu/blog-django-auth-demo-basic/env/bin with your environment bin path and keep everything else as it is.
  • ExecStart: This command will start the Django application. We need to pass all the hyperparameters within this command itself.
    • First will be the Gunicorn environment path.
    • error-logfile and access-logfile: For storing the access log and error logs in a file.
    • capture-output: Redirect stdout/stderr to the specified file in error log.
    • enable-stdio-inheritance: Enable inheritance for stdio file descriptors in daemon mode.
    • workers: Number of workers to run the project.
    • log-level: Keep it in debug, This will capture all the necessary information about the server in this mode. There are other options are also available you can read about them and use them at your convenience.
    • bind: Here we will bind it with the socket that we have created previously. At the end provide the application path of the wsgi file with the project name (Same as the gunicorn terminal command)

You can read more about these parameters in the gunicorn docs

NOTE: Make sure to keep the \ At the end of the line after a single space only in the ExecStart command. Make sure there must be only a single space before the \ at the end of the line. Make sure that there is no extra space at the end of any lines. Extra space will generate unusual errors in the production, so make sure everything is fine.

Once the required changes are done, run the below command in the terminal to create and open the service with the Vim editor.

sudo vim /etc/systemd/system/demo_setup.service

Paste all the configurations in the file, save it, and exit. Next before starting the service and socket, we need to change the DEBUG variable in the settings.py file to False To receive error email notifications in case any error occurs and also disable the development features in the project. Next need to create a logs folder under the project’s root folder and also be required to create 2 log files, error.log, and access.log in the logs folder.

Next, run the below commands to start the socket and service.

sudo systemctl start demo_setup.socket && sudo systemctl start demo_setup.service

Next, check the status of the service and socket by running the below command.

sudo systemctl status demo_setup.socket && sudo systemctl status demo_setup.service

You will get a response similar to the below image, Make sure both the service are active and running as described in the image.

Next, we need to update the nginx configurations file to use the socket instead of directly accessing the application with localhost and port number. Open the nginx config with the below command.

sudo vim /etc/nginx/sites-available/demo_config

Change the proxy_pass http://0.0.0.0:8000; line inside one of the location section with the proxy_pass http://unix:/run/demo_setup.sock. If you are using a different name for the socket and service files, make sure to replace the name in the line, Save the file, and exit the editor. Restart the Nginx to apply the changes.

After a code update or any modification in the Django application required to restart the services. You can use the below command to restart the socket and service files after any changes or code updates on the server.

sudo systemctl restart demo_setup.socket && sudo systemctl restart demo_setup.service

Next, let’s enable the socket and service files to start automatically on the system reboot. In case we are required to restart the server, the service must be automatically started on the boot. run the below 2 commands to enable the socket and service.

sudo systemctl enable demo_setup.socket
sudo systemctl enable demo_setup.service

Now, if you check the status of the service by running the below command, it will be enabled.

sudo systemctl status demo_setup.socket && sudo systemctl status demo_setup.service

Setup HTTPS

HTTPS makes data transmission between client and server secure and encrypted and makes it a trusted site. We will require the SSL certificate to use the HTTPS for a website. There are various ways to get a certificate and use it with the Nginx. We will get the certificate from Let’s Encrypt.

We will require a domain name to get the SSL certificate, If you have a domain you can create one subdomain for the setup too. If you are following this for the learning purposes, you can easily skip this step. Without the HTTPS, the site will work fine.

To obtain the SSL certificate, first, we need to update the nginx configurations. open the Nginx config file with the below command.

sudo vim /etc/nginx/sites-available/demo_config

replace the server_name variable value with the domain name as described below. Replace the your_domain With the actual domain name. Do not add http or https at the beginning and also do not add the / at the end of the domain name.

server_name your_domain www.your_domain;

We also need to update the ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS With the domain name in the settings.py file. Make sure you follow the same syntax as described above for adding the domain to the settings file. Once you are done with these changes we can continue the process of setting up the HTTPS.

First, let’s install the Nginx Certbot plugin to get the certificate. Run the below command in the terminal to install the package.

sudo apt install python3-certbot-nginx

Next, we request the certificate with the below command. Make sure to replace your_domain with your actual domain.

sudo certbot --nginx -d your_domain -d www.your_domain

You will prompted to accept the T&C for the certificate, Accept it.

You will be asked to set up the redirect http traffic to https Make sure you setup the redirect to avoid site access without the secure connection.

You will be also required to add the email ID to get important updates about the certificate and certificate re-renewal.

There will be an option to set the auto re-newel of the certificate, make sure you enable that to avoid manually re-renewal of the certificate.

Once everything is done, You can access your site with a secure connection via the domain.

This is how you can set the Django project for production with the Nginx + Gunicorn and PostgreSQL as database-backed.

Categories: AWS Django Gunicorn How To Nginx Python Server Setup

Leave a Reply

Your email address will not be published.

You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*