Deploy Django Website Using Nginx, Gunicorn, Postgres DB and Apply SSL
Deploy Django Website Using Nginx, Gunicorn, Postgres DB and Apply SSL
Introduction
Django is undoubtedly one of the most popular and powerful framework / MVC today. This is a high-level Python web framework. Many
popular and heavy websites like Instagram, Pinterest use django framework.
As a developer, I struggled initially on how to deploy a website in a Ubuntu server. After going through many tutorials, videos and how-to
guides over the internet I compiled following steps to deploy a django website / application on server.
Deploy Django website in Ubuntu server with Nginx Gunicorn PostgreSQL DB and apply SSL | Sleeksoft
Prerequisites
You need to have following
Legend
1. example.com – You need to replace this with the domain name you use in your setup
2. sleekproject – This is project directory, you can name this according to your project requirements
3. sleekenv – This is virtual environment, you can name it as whatever you want to.
4. sleeksoft – This is our django project, you can name this based on your project title etc..
Copy
sudo apt update -y
Copy
sudo apt upgrade -y
Copy
1 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl file
Copy
sudo -u postgres psql
Copy
CREATE DATABASE sleeksoft;
Create a database user for our project. Make sure to select a secure password.
Copy
CREATE USER sleekuser WITH PASSWORD 's133ks0ft';
Copy
ALTER ROLE sleekuser SET client_encoding TO 'utf8';
Set the default transaction isolation scheme to ‘read committed’. This blocks the reads from uncommitted transactions.
Copy
ALTER ROLE sleekuser SET default_transaction_isolation TO 'read committed';
Set the default timezone to UTC. This is the default timezone our django project too will have.
Copy
ALTER ROLE sleekuser SET timezone TO 'UTC';
Now, give our database user ‘sleekuser’ to have all the privileges in the database ‘sleeksoft’.
Copy
GRANT ALL PRIVILEGES ON DATABASE sleeksoft TO sleekuser;
Now we have successfully created a database and a database user who has all the privileges over the database we created in the
PostgreSQL. Quit from Postgres environment.
Copy
\q
Copy
sudo -H pip3 install --upgrade pip
Copy
sudo -H pip3 install virtualenv
Create a project folder where you can create virtual environment and install django, gunicorn etc.. for our project. In this tutorial, I am
going to create the project folder inside /home/ directory.
Copy
cd /home
2 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
mkdir sleekproject
Copy
cd sleekproject/
Create virtual environment inside the project directory. I am naming the virutal environment as ‘sleekenv’.
Copy
virtualenv sleekenv
This will create a directory called ‘sleekenv‘ within ‘sleekproject‘ directory. Inside, it will install a local version of Python and a local
version of pip. We can use this to install and con�gure an isolated Python environment for our project. Before we install our project’s
Python requirements, we need to activate the virtual environment.
Copy
Copy
source sleekenv/bin/activate
The terminal prompt should change to indicate that you are now operating within a Python virtual environment. It will look something like
this
(sleekenv) root@host:/home/sleekproject#
With virtual environment activated, now we can install Django, Gunicorn and the PostgreSQL adapter (psycopg2) using pip. In virtual
environment we can just use pip instead of pip3 no matter if you are using Python version 3.
Copy
pip install django gunicorn psycopg2-binary pillow
We now have all the softwares we needed to start our Django project.
Copy
django-admin startproject sleeksoft
Now you will see a new directory ‘sleeksoft’ inside our project folder. So the whole path will be /home/sleekproject/sleeksoft. Now we
need to con�gure settings.py �le in ‘sleeksoft’ directory.
Open settings.py and add ALLOWED_HOSTS to have the localhost and domain name. Change ‘example.com’ to your domain name.
Copy
ALLOWED_HOSTS = ['example.com', 'localhost']
Note: Be sure to include localhost as one of the options since we will be using connections through a local Nginx server instance.
Update database details in settings.py. These settings will de�ne the link between our django project and the PostgreSQL database we
created. By default settings.py will have a Database details linking to SQLite, replace that with the following code.
Copy
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'sleeksoft',
'USER': 'sleekuser',
'PASSWORD': 's133ks0ft',
'HOST': 'localhost',
'PORT': '',
}
}
Add / Change setting indicating where the static �les should be placed. This is necessary so that Nginx can handle requests for these
�les. The following setting tells Django to place static �les in a directory called static in the base project directory.
Copy
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'
3 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
Let’s make the initial migration, which will setup the database tables etc.. You need to be inside the django project we created to run
following commands /home/sleekproject/sleeksoft.
Copy
cd sleeksoft/
Copy
python3 manage.py makemigrations
Copy
python3 manage.py migrate
Copy
python3 manage.py createsuperuser
You should enter username, email and password to create a superuser account. After this, lets do the collectstatic command which will
collect all the static �les in our website to /static/ folder. Remember we de�ned ‘/static/’ folder in settings.py.
Copy
python3 manage.py collectstatic
Create an exception for port 8000. So, we can test that django setup is installed properly.
Copy
sudo ufw allow 8000
Now, we can test our your project by starting up the Django development server with the following command
Copy
python3 manage.py runserver 0.0.0.0:8000
In the web browser, visit the server’s domain name or IP address followed by :8000. Here 8000 is a port number.
Copy
http://server_domain_or_IP:8000
If all setup is done properly, you should see following in the browser.
4 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
We can login into the django admin by going to /admin/ from home page. There we can use the super user account we created in previous
steps. After exploring the Django admin, use CTRL-C in the terminal window to shut down the development server.
Copy
gunicorn --bind 0.0.0.0:8000 sleeksoft.wsgi
This will start Gunicorn on the same interface that the Django development server was running on. We can go back and test the website
again. The only difference is we are not doing startserver command from Django, instead Gunicorn will take care of that.
Note: In some cases the admin interface will not have any styling applied since Gunicorn does not know how to �nd the static CSS
content responsible for this. We will con�gure that in Nginx.
After �nished testing, use CTRL-C in the terminal window to stop Gunicorn. We now �nished con�guring our Django application /
Website. We can quit from the virtual environment using the following command.
Copy
deactivate
Create and open a systemd socket �le for Gunicorn in the following path.
Copy
sudo touch /etc/systemd/system/gunicorn.socket
5 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
gunicorn.socket �le will be created in the above path, download via FTP and start adding the following code to it.
Copy
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
# Our service won't need permissions for the socket, since it
# inherits the file descriptor by socket activation
# only the nginx daemon will need access to the socket
SocketUser=www-data
# Optionally restrict the socket permissions even more.
# SocketMode=600
[Install]
WantedBy=sockets.target
Save, close and upload the �le via FTP when you are �nished.
Next, create and open a systemd service �le for Gunicorn with sudo privileges. The service �lename should match the socket �lename
with the exception of the extension:
Copy
sudo touch /etc/systemd/system/gunicorn.service
gunicorn.service �le will be created in the above path, download via FTP and start adding the following code to it.
Copy
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
Type=notify
# the specific user that our service will run as
User=root
# Group=someuser
# another option for an even more restricted service is
# DynamicUser=yes
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
RuntimeDirectory=gunicorn
WorkingDirectory=/home/sleekproject/sleeksoft
ExecStart=/home/sleekproject/sleekenv/bin/gunicorn sleeksoft.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Save, close and upload the �le via FTP when you are �nished.
Now, our systemd service �le is complete. We can now start and enable the Gunicorn socket. This will create the socket �le at
/run/gunicorn.sock now and at boot. When a connection is made to that socket, systemd will automatically start the gunicorn.service to
handle it.
Copy
sudo systemctl start gunicorn.socket
Copy
sudo systemctl enable gunicorn.socket
We can con�rm that the operation was successful by checking for the socket �le. Check the status of the process to �nd out whether it
was able to start:
6 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
Next, check for the existence of the gunicorn.sock �le within the /run directory
Copy
file /run/gunicorn.sock
If the systemctl status command show errors or if you do not �nd the gunicorn.sock �le in the directory, it’s an indication that the Gunicorn
socket was not able to be created correctly. Check the Gunicorn socket’s logs using the following command
Copy
sudo journalctl -u gunicorn.socket
Copy
sudo systemctl status gunicorn
Output :
To test the socket activation, we can send a connection to the socket through curl by using the following command
Copy
curl --unix-socket /run/gunicorn.sock localhost
You should see the HTML output from our django application in the terminal. This means that Gunicorn was started and was able to serve
our Django application. We can verify that the Gunicorn service is running by using the following command
Copy
sudo systemctl status gunicorn
Output :
If the output from curl or the output of systemctl status indicates that a problem occurred, check the logs for additional details:
Copy
sudo journalctl -u gunicorn
Check the /etc/systemd/system/gunicorn.service �le for problems. If we make changes to the /etc/systemd/system/gunicorn.service �le,
reload the daemon to reread the service de�nition and restart the Gunicorn process using the following command
7 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
Copy
sudo systemctl restart gunicorn
Copy
sudo touch /etc/nginx/sites-available/sleeksoft
Download this �le via FTP and start editing. We will add following in this server block.
• Specify that this block should listen on the normal port 80 and that it should respond to our server’s domain name or IP address.
• Instruct Nginx to ignore any problems with �nding a favicon.
• Instruct Nginx on where to �nd the static �les that we collected in our /sleekproject/static directory. All of these �les have a Copy
standard URI pre�x of “/static”, so we can create a location block to match those requests
Copy
server {
server_name example.com;
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
Save, close and upload the �le via FTP when you are �nished. Now, we can enable the �le by linking it to the sites-enabled directory
Copy
sudo ln -s /etc/nginx/sites-available/sleeksoft /etc/nginx/sites-enabled
Test the Nginx con�guration for syntax errors by using the following command
Copy
sudo nginx -t
If no errors are reported, then we can go ahead and restart Nginx by using the following command
Copy
sudo systemctl restart nginx
Now, we need to open up our �rewall to normal traf�c on port 80. Since we no longer need access to the development server, we can
remove the rule to open port 8000 now.
Copy
sudo ufw delete allow 8000
Copy
sudo ufw allow 'Nginx Full'
We should now be able to go to our server’s domain or IP address to view our django application/website.
Copy
sudo apt install snapd
Execute the following instructions on the command line on the machine to ensure that you have the latest version of snapd
8 de 9 13/6/2022 13:45
Deploy Django website using Nginx, Gunicorn, Postgres DB and apply SSL https://sleeksoft.in/deploy-django-website-in-ubuntu-server-using-nginx-gunicorn-and-wsgi-with-pos...
Copy
sudo snap install core; sudo snap refresh core
Run this command on the command line on the machine to install Certbot.
Copy
sudo snap install --classic certbot
Execute the following instruction on the command line on the machine to ensure that the certbot command can be run.
Copy
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Run this command to get a certi�cate and have Certbot edit your Nginx con�guration automatically to serve it, turning on HTTPS access
in a single step.
Copy
sudo certbot --nginx
When prompted enter the desired value. This will automatically create SSL certi�cates for the pointed domain.
Copy
reboot
Credits:
• Digital Ocean
• Barath Prabu S
9 de 9 13/6/2022 13:45