How I deployed Django Backend on AWS
Published: 2020-09-04 16:39:21

**Prerequisites**
Create AWS free tier account
Create IAM user

**Steps for Deployment**

Login to AWS console and search for EC2 service.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2xy8mrpslmrk6obii7qi.png)

Click on EC2, check for launch instance tab. Now click on launch an instance

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9lr5d3wc2yume0fr5lnf.png)

Once you launch instance choose an Amazon Machine Image
Here we are going to choose ubuntu 18.04 LTS AMI

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ga4g6shvslthns87e8qo.png)

Choose an Instance Type
Here we are going to select general purpose t2.micro instance type

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mgb5c28mj9mslicwja7a.png)

Click continue for further steps and launch an instance.

It will ask you to provide a key pair, either select an existing key pair, if you have one or create a new key pair. In this case we are going to create a new key pair named todo.You can give any name to key pair.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w4wff3viju8602f6z1oe.png)

Download the key pair and save it in a folder. At the end click on the launch instance. Now, your instance is ready to use. Click on view instances where you can see your instance is running.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gpvwwjbhcpqoeqno02xg.png)

Right click on the instance and select Connect

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uva1gikd31asho1nmybz.png)

Once you click on connect, copy the ssh string given in example tab

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/na2hq6hlg9h72wddmuac.png)

This string would be different for everyone.
Here, Todo.pem is the key that we created and downloaded in an earlier step.
Before starting deployment we should be in the same folder where we have saved this key.

Next, open a terminal

```
cd <into folder where todo.pem key is saved>
```
To convert key into read-only mode use

```
chmod 400 todo.pem
```
Now, start working in the same folder. For logging into the server paste ssh key string into terminal
It will ask, if you want to continue or not, insert yes. Now you are connected to the server and you will see a prompt as shown below.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yjfa26h2jmqreo4vrthe.png)

At this point, you are inside the newly installed server, next you have to install and upgrade all required packages. 

Lets see it steps by step
First, run sudo apt-get update and sudo apt-get upgrade -y command.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ugc6vttwk3pldhqf9le4.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jk0gsts3weik70l8lze6.png)

Next, install a set of softwares to set up a Django application on the server. First of all, to serve our application in the production environment, we need to set up an actual server such as apache or NGINX. Next, we need the WSGI interface which uses a mechanism called unix socket to achieve inter-process communication in order to connect the Django application with NGINX server. Here we are going to use the Gunicorn which is the most prominent python WSGI http server. We will also need python. It will be downloaded by default. Check the python version using command 

```
python3 --version.
```

Install virtual environment venv to create an environment called env. Install venv using command 

```
apt-get install python3-venv
```
Activate this environment using command
 
```
source env/bin/activate
```

Install Django using 

```
pip3 install django
```

Next, clone the github repository into our server.

```
Git clone <repository>
```

Change directory 
```
cd < repository>
```

Install Gunicorn using 

```
pip3 install gunicorn.
```

Next, install NGINX using command 

```
sudo apt-get install -y nginx
```

Start NGINX server using 

```
sudo nginx
```

It will give a message saying the address already is in use that means NGINX is started.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/h07wsnp81qypmiikr9hu.png)

Now, go back to the AWS console, click on connect to instance and copy the public DNS address. Paste it in your browser.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/svm0r6r7yedrwfrwlt6t.png)

It will still give you connection errors.
This is because we did not assign a server to a security group. Additionally, we have to assign traffic rules to allow traffic from different sources. By default it allows SSH traffic, but HTTP and TCP traffic are not allowed yet. We have to set up these settings.
Now, right click on EC2 instance, go to networking tab and select change security group.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rc96jefzv2lvhl2xrt59.png)

Select a security group and assign it to an instance. 
Once you assign a security group go to the network. Check for security tab on the left hand side then click on the security group.
Select the assigned security group and check inbound traffic, click on edit inbound rules.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ez3vp6uxim9anpmq40n4.png)

Select add rules, select type of traffic, in this case I have selected http, select port 80 and source as anywhere so that instance can be accessible from any location.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ez3vp6uxim9anpmq40n4.png)

If you go back to the browser then it will provide a message saying welcome to NGINX.

Next, we have to connect a Gunicorn to NGINX. For that, first we need to configure the wsgi file. 

```
cd < into django project> 
```
When you check files inside project folder, you will see it contains wsgi.py file. With the help of this file gunicorn accesses Django and communicates with nginx to process a request to the server.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/m8zbuvasx59v6rp6gdl5.png)

Change directory back to the main project using command 

```
cd..
```

Tell gunicorn to use wsgi file using command 

```
gunicorn --bind 0.0.0.0:8000 todo_django.wsgi:application
```
Here, todo_django is the Django project name, replace with  the project name you have used for Django app.
Go back to AWS console, select the security group as we did in earlier steps and add one more rule to set up inbound traffic to allow port 8000. Then revisit your server and you will be able to see the server is connected.
Next, let's install and configure supervisor, supervisor makes sure the application is always running in the background. First, install supervisor.

```
sudo apt-get install -y supervisor
```
Further, configure the supervisor.First change directory.

```
cd /etc/supervisor/conf.d
```
Create a new configuration file in this directory using command 

```
sudo touch gunicorn.conf

```

Open the configuration file using command

```
sudo nano gunicorn.conf
```
Once you press enter you’ll see an empty file, now insert the configuration into the file.

```
[program:gunicorn]
directory= <project directory>
command = <directory-path>/env/bin/gunicorn --workers 3 --bind unix:<directory-path>/app.sock todo_django.wsgi:application
autostart = true
autorestart=true
sterr_logfile=/var/log/gunicorn/gunicorn.err.log
stdout_logfile=/var/log/gunicorn/gunicorn.out.log

[group:guni]
Programs:gunicorn

```
Change directory-path to your project directory path, save the file and exit. Now make a new directory.

```
mkdir /var/log/gunicorn
```
Lets ask supervisor to reread the configuration 

```
sudo suervisorctl reread
```
It says guni is available. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zzacv1ivdqa812kad1ol.png)

Next, inform the supervisor to start the program in the background using command 

```
sudo supervisorctl update. 
```
It will give you message guni: added process group.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uhxyv19u63j7bqhda34y.png)

Go back to the main directory using command

```
cd..
```
Next, configure NGINX. For that, first change directory 

```
cd /etc/nginx/sites-available
```
Create django configuration file using 

```
sudo touch django.conf
``` 
Open this file to add configuration using 

```
sudo nano django.conf
```

Once you open the file add this configuration to file. Make sure you will change DNS address to the one you have.
If you right click on the instance and click connect, you will find public DNS.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/opvt7zoigbj9qghv4l65.png)

```
server {
        listen 80;
        server_name <DNS address>

        location / {
                include proxy_params;
                proxy_pass http://unix:/<main-file-path>/app.sock;
        }
}
```

Test this configuration using 

```
sudo nginx -t
```
It will say test is successful.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uhxyv19u63j7bqhda34y.png)

To read a conf file, run the command 

```
sudo ln sudo ln django.conf /etc/nginx/sites-enabled 
```
Run NGINX test again

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uhxyv19u63j7bqhda34y.png)

Restart the server

```
sudo service nginx restart

```
At this time your application is up and running.

Next, we need to configure database. For that, we are going to create RDS instance. Go back to AWS console and search for RDS in database services.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/twwhwcan3ohegu3qdxq5.png)

Then go to RDS and select create database.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dsqvximpwcqjje83b1gf.png)

Select PostgreSQL database and free tier template.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kvm5f9yz4b4o5iu8vtbk.png)

Add database instance identifier, password and t2.micro db instance size. Select default settings for other options. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/su1yxe6g4u7krl6h0myo.png)

Select additional configuration and add database name.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/g4mkrn1lhzw9pyw1naic.png)


Click on create database. Once your instance is ready, go back to the terminal 

```
cd <into the django app folder>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d19ndw83yeda0ragwkvu.png)

We will add database configurations. Open settings.py  using command 

```
vi settings.py
```
In settings.py change database name to one which you used while creating DB instance. Change the user to Postgres and password to that you used while creating the database instance.
Next, go back to AWS console, click on the database instance that you have already created. Copy endpoint and replace localhost with endpoint in settings.py. Keep port to 5432.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1xfc8eo1nbvw53qkr892.png)

Your final configuration will look like this

```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': ‘<RDS database instance name>’,
        'USER': ‘postgres’,
        'PASSWORD': '<RDS database instance password>',
        'HOST': ‘<Endpoint>’,
        'PORT': '5432',
    }
}
```
Exit the editor and go back to the main project directory and install psycopg2-binary.

```
pip3 install psycopg2-binary
```
Migrate the changes using command

```
python3 manage.py makemigration <django-app-name>

```
```
python3 manage.py migrate
```
Finally, restart the NGINX server, your database is connected and your app is up and running.