How I deployed my Django app to Vultr VPS

ndemo

richard ndemo

Posted on September 29, 2019

How I deployed my Django app to Vultr VPS

Having developed my Django app, it was time to deploy it so that it can be live, such a thrilling feeling to have my own hosted website online. - I did a couple of searches and decided to host with vultr VPS. Let us jump to the whole process from setting up my server to actual running my website.

Creating a New Instance

I chose cloud compute:

Alt Text

Selecting the region for my server:

Alt Text

selecting server operating system:

Alt Text

Selecting the size of the server:

Alt Text

I chose to name the server Testserver for a practical purpose.

Alt Text

after creating the server:

Alt Text

after receiving the root password via email, I ssh into the server using the server IP Address.

Alt Text

Updating the server

First thing is to upgrade the server's packages:

apt-get update
apt-get upgrade



######Creating Application User
It is always best practice not to work directly with the root user.so I created another user.

<code> adduser django</code>


since I am deploying a Django application, It is simple to use a simple name.
This is the output. There are few questions to be answered.
~~~
Adding user `django' ...
Adding new group `django' (1000) ...
Adding new user `django' (1000) with group `urban' ...
Creating home directory `/home/django' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for urban
Enter the new value, or press ENTER for the default
  Full Name []:
  Room Number []:
  Work Phone []:
  Home Phone []:
  Other []:
Is the information correct? [Y/n]
~~~

Adding the user to sudoers to be able to perform root functions:
<code>gpassword -a django sudo</code>

Now log in to the new user account.

##Installing the necessary Dependencies:

#####Supervisor
This will be used to start the Django application server and manage it.

<code>sudo apt-get install supervisor</code>

######Starting and enabling the supervisor:


Enter fullscreen mode Exit fullscreen mode

sudo systemctl enable supervisor
sudo systemctl start supervisor



#####PostgreSQL 

Installing the dependencies to be used by Postgresql and Django

<code>sudo apt-get install build-essential libpq-dev python-dev</code>

######Installing PostgreSQL server:

<code>sudo apt-get -y install postgresql postgresql-contrib</code>

######Creating and Configuring PostgreSQL database:

#####Switch users:

<code>su - postgres</code>

Creating a db user and database:


Enter fullscreen mode Exit fullscreen mode

createuser django_project
createdb prod --owner django_project
psql -c "ALTER USER u_urban WITH PASSWORD '!@#fs_877#$cdfd@@'"



######exit the postgreSQL user:
<code>exit</code>

####Install and Configure Virtualenv

I used python3 that is already installed in ubuntu 16.04

######First, install pip3:

<code>sudo apt-get install python3-pip</code>

######Using pip install virtualenv:

<code>pip3 install virtualenv</code>

######Then create virtualenv:

<code>python3 -m venv django_env</code>

######Activating it:
cd to the virtualenvdirectory <code>cd django_env</code>

<code>source bin/activate</code>

I used GitHub to store my Django website, so I cloned it from the git repository.

<code>git clone https://github.com/ndemo-richard/django_project.git</code>

cd into project directory and install project dependencies:

<code>pip install -r requirements.txt</code>

changing the database credentials in the settings.py file in the project root directory:

~~~
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'prod',
        'USER': 'django_project',
        'PASSWORD': '!@#fs_877#$cdfd@@',
        'HOST': 'localhost',
        'PORT': '',
    }
}
~~~

#####migrating the database:
<code>python manage.py migrate</code>

#####collect project static files:
<code>python manage.py collectstatic</code>

####Install and configure Gunicorn

<code>pip install gunicorn</code>

create a file named gunicorn inside bin directory

<code> vi bin/gunicorn</code> 
add this to the empty file:

~~~
#!/bin/bash

NAME="django_project"
DIR=/home/django/django_project
USER=django
GROUP=django
WORKERS=3
BIND=unix:/home/django/run/gunicorn.sock
DJANGO_SETTINGS_MODULE=django_project.settings
DJANGO_WSGI_MODULE=django_project.wsgi
LOG_LEVEL=error

cd $DIR
source ../bin/activate

export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DIR:$PYTHONPATH

exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $WORKERS \
  --user=$USER \
  --group=$GROUP \
  --bind=$BIND \
  --log-level=$LOG_LEVEL \
  --log-file=-
~~~

make the file executable

<code>chmod u+x bin/gunicorn</code>

create directory for the UNIX socket file:

<code> mkdir run</code>

#####Configure Supervisor

 first, create a directory for log files:

<code>mkdir logs</code>

######Create an empty log file inside the log directory:

<code>touch logs/gunicorn-error.log</code>

create a new supervisor config file:

<code>sudo vi /etc/supervisor/conf.d/django_project.conf</code>

django_project.conf

~~~
[program:django_project]

Enter fullscreen mode Exit fullscreen mode

command=/home/django/django_project/bin/gunicorn
user=urban
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/django/logs/gunicorn-error.log


Reread the config file:


```

sudo supervisorctl reread
sudo supervisorctl update

```


Check the status:

```

sudo supervisorctl status django_project
django_project                      RUNNING   pid 42173, uptime 0:00:13

```



##NGINX

Installing Nginx web server, this will be used to run the Django application behind a proxy server

<code>sudo apt-get install nginx</code>

create new config file inside /etc/nginx/sites-available/:

<code>sudo vim /etc/nginx/sites-available/django_project</code>

/etc/nginx/sites-available/djago_project

Enter fullscreen mode Exit fullscreen mode

upstream app_server {
server unix:/home/urban/run/gunicorn.sock fail_timeout=0;
}

server {
listen 80;

# add here the ip address of your server
# or a domain pointing to that ip (like example.com or www.example.com)
server_name 68.152.87.135;

keepalive_timeout 5;
client_max_body_size 4G;

access_log /home/urban/logs/nginx-access.log;
error_log /home/urban/logs/nginx-error.log;

location /static/ {
    alias /home/urban/static/;
}

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

location @proxy_to_app {
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect off;
  proxy_pass http://app_server;
}
Enter fullscreen mode Exit fullscreen mode

}


creating a symbolic link:



```

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

```




Remove the default nginx website:
<code>sudo rm /etc/nginx/sites-enabled/default</code>

Restart nginx:
<code>sudo service nginx restart</code>

Now we are good to go. My website is online.
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
ndemo
richard ndemo

Posted on September 29, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related