Beginner's guide to deploy Django application using Gunicorn and Nginx
Tags: devops, tutorial, linux, django
Published: 2022-12-27 08:18:38

Before getting into **serious business**, here are some **pre-requisites** for following the post:

1. This post assumes you have your Django project without any bugs on GitHub (we are going to use GitHub to transfer our
project to the server). 

2. Make sure you have your `requirements.txt` file in the repository to setup the virtual environment. You can generate the requirements file using `pip freeze > requirements.txt` command.

3. We will be looking at commands for a server using Ubuntu OS, the commands for other Linux based systems remain the same
except for the package manager part. 

4. You would also need the ssh tool installed in your system. To install it in Ubuntu based system use the following commands:

```python
sudo apt-get update
```
```python
sudo apt-get upgrade
```
```python
sudo apt-get install openssh-client
```


## Serious Business:
Now starts the serious business, in this section we will do all the configurations and make our application run on the remote server.  
  

To do so, we will follow a series of steps listed below:  
  
**Step-1 :**  

- First log into your remote server using ssh tool.

- If you have username and password to log into the remote server you can do it like this:

```python
ssh username@domain 
```
where domain can be your _server's assigned domain_ name or _simply the IP address_ of your server.
After doing this it would ask you to for your password. After successful completion of the process you will be logged into the server.  


**Step-2 :**  

Next we would need to run a series of commands to install the necessary packages which would be required, the command are listed below:

```python
sudo apt update
```
```python
sudo apt install python3-pip python3-dev nginx git
```
```python
sudo pip3 install virtualenv
```

**Step-3 :**  

After we are done with the step-2 ,we would need to clone our GitHub repository into the server. To clone the repository use the `git clone` command. for example:

> `git clone https://github.com/mayankt18/glugle`

**Step-4 :**  

In this step, we are going to setup the virtual environment for our project.
- Switch into your project directory:
`cd projectdir`  

- Create a new virtual environment, activate it and install the packages required into it using the commands listed below:

```python
python3 -m venv env
```
```python
source ./env/bin/activate
```
```python
pip install -r requirements.txt
```

- Also we need to install [gunicorn](https://gunicorn.org/) which would be our web server. To do so follow the commands:
```python
pip install gunicorn
```

- Deactivate the virtual environment
```python
deactivate
```  
  
**Step-5 :**  

After installing the required packages in the virtual environment, we need to configure the gunicorn socket and service files to run our application.
- First let us configure the **gunicorn.socket** file. Run the command to edit the socket file in nano.
```python
sudo nano /etc/systemd/system/gunicorn.socket
```
Now paste the following into the file

```python
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target
```

Save the file using `ctrl+s` and exit nano using `ctrl+x`.

- Let us now configure the **gunicorn.service** file:
```python
sudo nano /etc/systemd/system/gunicorn.service
```
and paste the following content into the file
```python
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=<username>
Group=www-data
WorkingDirectory=/home/<username>/<projectdir>
ExecStart=/home/<username>/<projectdir>/env/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          <application_name>.wsgi:application

[Install]
WantedBy=multi-user.target
```

<u>and don't forget to replace the \<username\> with your username, \<projectdir\> with the name of your project directory and \<appliation_name\> with the name of module in your django project which contains the wsgi.py file.</u>

Save and exit nano as instructed before.

We are done with configuring the gunicorn configs and now we need to start and enable gunicorn workers. To do that use the commands below:

```python
sudo systemctl start gunicorn.socket
```
```python
sudo systemctl enable gunicorn.socket
```

**Step-6 :**  

We need to configure nginx to communicate with our running application. To do so you would first need to create a new nginx config file.
- Run the command below to create a new nginx config file and open it in nano
```python
sudo nano /etc/nginx/sites-available/<application_name>
```
<u>replace the \<application_name\> with your application name</u>
- Paste the following in the nginx config with the <u>required modifications</u>. 
```python
server {
    server_name www.domain_name.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/<username>/<projectdir>;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}
```
- We would also need to create a link of the config file inside the `/etc/nginx/sites-enabled/`, to do so we need to run
```python
sudo ln -s /etc/nginx/sites-available/<application_name> /etc/nginx/sites-enabled/
```
<u>and replace \<application_name\> with your app name.</u>

- Check the correctness of your nginx config file using the command
```python
sudo nginx -t
```

![Correct Nginx config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3frn9ykk3tu3u3sfy9un.png)
if you see any result like above, you are good to go.

- Now just restart the nginx daemon and we are all done.
```python
sudo systemctl restart nginx
```

**Pre-Final step :**  

Go to your browser and type the domain name and check the working of your deployment. 
If it is working Congratulations🎉!!! You have successfully deployed a Django project on a server. Now you can finally move to the final step. 

Now, if you are among the people who are facing errors don't be discouraged. I am going to tell you the ninja way to identify and tackle the errors that might have crept. 
1. Run `cat /var/log/nginx/error.log` and see what error nginx is facing

2. You can have a look at the running status of gunicorn server using `sudo systemctl status gunicorn` command, you would probably find if the server is running or not.

In most of the cases the above steps will help you identify the errors and provide you the error codes, you can have a look at them.

<u>Pro Tip</u> : If you make changes to your nginx config file, just do 
```
sudo systemctl reload nginx
```
 for loading the changes.  

**Final Step**

If you are at the final step i would like to thank you for patiently reading through my post. 
If you liked this post and my writing style, do <u>leave a like </u>so i get encouragement to keep posting such articles and do leave your <u>comments on the post</u>. Even a 👍 would mean a lot.