Today I'll be writing on how to deploy a Django app on an AWS EC2 instance. Ofcourse there are many ways to deploy a Django app to AWS so therefore we will be looking at one of the ways to do that.
The first thing you need to do is to log in to your AWS account and search for EC2. Click on it and it would take you to your EC2 dashboard.
Create security group
Next thing you need to do is to create a security group.
A security group is a virtual firewall that controls the inbound and outbound network traffic for one or more instances. It acts as a filter for the traffic that can reach the instances and specifies the types of traffic, such as HTTP, HTTPS, SSH, etc., that are allowed to access the instances.
To create a security group, on your EC2 dashboard under the resources section, click on security group
At the top right corner, click the "create security group" button and then give your security group a name and description. Scroll down and add your inbound rules as shown in the picture
Once you've added that you can scroll down and create the security group. Do well to keep in mind the name of your just created security group we'll be needing it shortly
Create EC2 Instance
Now we have gotten that out of the way, it's now time to create our first EC2 instance. Head back to your EC2 dashboard and click on instances (running) and then click on launch instance at the top right corner. Give your instance a name and then select Ubuntu as your Application and OS Images (Amazon Machine Image). Make sure it's the free tier eligible one you selected. scroll down and double check that your instance type (either t2 or t3) is also a free tier eligible one. For the sake of simplicity of this tutorial, well leave out creating a key pair so just ignore that section and scroll down.
Now under Network settings, click on Select existing security group and then select the security group you created earlier from the first section of this post (hope you still remember the name?) from the drop down. Leave every other setting in default and click on launch instance at the bottom right. If you did every thing right, your instance should be up and running in a few seconds.
Connect to your instance
Back on your EC2 dashboard, click on instances and you should see your just created instance, ensure that the status of your instance is running before you proceed to the next steps. Now to connect to your instance, select the instance you want to connect to and the click on connect. Click on the connect button again and you should be redirected to a new tab that has connected to your instance.
Now the main work 😅
Now that we have connected to our EC2 instance, we can now start the dirty work. First we have to install some packages
sudo apt update
sudo apt install python3-venv python3-dev libpq-dev postgresql postgresql-contrib nginx curl
This command will install a necessary packages you need to create virtual environments for your Python projects, build Gunicorn, create a Postgres database system and the libraries needed to interact with it, and the Nginx web server.
Create the PostgreSQL Database and User
Next we have to create a PostgreSQL database for our django application. If you are fine using the default sqlite database, feel free to skip this section
Log into an interactive Postgres session by typing:
sudo -u postgres psql
Next, create a database for your project:
CREATE DATABASE djangodb;
Next, you have to create a database user for your project.
CREATE USER djangouser WITH PASSWORD 'put_a_secure_password';
Django needs the following parameters for its database connections so let's add them
ALTER ROLE djangouser SET client_encoding TO 'utf8';
ALTER ROLE djangouser SET default_transaction_isolation TO 'read committed';
ALTER ROLE djangouser SET timezone TO 'UTC';
Next, give the new user access to control the new database.
GRANT ALL PRIVILEGES ON DATABASE djangodb TO djangouser;
Create a Python Virtual Environment for your Project
Up next to create a virtual environment and install the Python requirements within the virtual environment for easier management.
python3 -m venv venv
Next you activate the virtual environment
source venv/bin/activate
Setting up Your django project.
After that the virtual environment has been activated, the next thing is to clone the github repository you want to deploy. You can do that using the following commands below
git clone https://github.com/sampleusername/myproj.git
Next is to install some necessary packages in other to run a basic django app.
pip install django gunicorn psycopg2-binary
You can also install other libraries and packages in your requirements.txt file
cd myproj/
pip install -r requirements.txt
Configure the Project Settings
You should make sure that you have setup your database variables in your settings.py
for the database connection to the postgres database you created earlier. And example configuration is shown below. Open the settings file in a text editor. You can do that using nano
nano myproj/myproj/settings.py
Then you look for the database connection and make the necessary changes using your own details
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'djangodb',
'USER': 'djangouser',
'PASSWORD': 'put_a_secure_password',
'HOST': 'localhost',
'PORT': '',
}
}
You should also set your allowed hosts
ALLOWED_HOSTS = ['Your_Public_IPv4 address', 'domain_name', . . ., 'localhost']
If you are using a custom domain name, after you have added the domain name to your allowed host, you would also need to add a host record. You can use the sample picture below to guide you on how to set it up.
You can also use also decide to use Route 53 and set up an elastic IP address if you wish. It is actually the recommended way to setup your custom domain name. you can check out this tutorial on how to do that.
Migrate your django migrations
Now, you can migrate the initial database schema to our PostgreSQL database using the management script:
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic
Set up Supervisor
The next thing we would want to do is to install supervisor. Now supervisor is there to ensure that our application keeps on running smoothly in the background.
First let's install it
sudo apt-get install supervisor
Then we need to configure a Gunicorn process to ensure that our server (Gunicorn) starts automatically with the system and that it can automatically restart if for some reason it exits unexpectedly. To do that, we need to change directory to where the configuration files should be placed. You can do that by
cd /etc/supervisor/conf.d
Then create a guincorn.conf
file
sudo nano gunicorn.conf
paste the following code
[program:gunicorn]
directory=/home/ubuntu/myproj
command=/home/ubuntu/venv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/myproj/app.sock myproj.wsgi:application
autostart=true
autorestart=true
stderr_logfile=/var/log/gunicorn/gunicorn.err.log
stdout_logfile=/var/log/gunicorn/gunicorn.out.log
Make sure to change all instances of myproj to your actuall project name
save and close the file once you're done. You can do so by pressing ctrl o
then press enter. To close the file press ctrl x
Once we have done that, we'll need to create the log file directory.
sudo mkdir /var/log/gunicorn
Finally we then need to notify the supervisor of the changes we just made using supervisorctl
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start all
sudo supervisorctl status all
Make sure that when you check for your status it shows
running
. It it's not, you'll need to debug your code for errors. You can check for errors in your log file in/var/log/gunicorn
Below are some useful commands you can use to debug your code
# to check the status of our processes
sudo supervisorctl status <program_name>
# example
sudo supervisorctl status gunicorn
my_proj RUNNING pid 1412, uptime 7:59:29
# to check status of all running process
sudo supervisorctl status all
# to start, stop, restart all or some of the processes
sudo supervisorctl start <program_name|all>
sudo supervisorctl restart <program_name|all>
sudo supervisorctl stop <program_name|all>
Setup Nginx
First of we need to make some changes to the nginx conf file in other to avoid permission denied errors. To that change directory to where the file is stored
cd /etc/nginx
#then open the conf file
sudo nano nginx.conf
Once the file is opened, change the www-data
in the first line of the file to root
. Close and save.
With that out of the way we can now go ahead to create a configuration file for our django application in the sites-available
directory
sudo nano /etc/nginx/sites-available/django.conf
then paste the settings below
replace appropriately with your aws public ip address and custom domain name if you have and change all instances of my proj to your actual project name
server{
listen 80;
server_name your_public_ip your_custom_domain;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/myproj;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/myproj/app.sock;
}
}
Let's do some explanations
The first
location
tells Nginx to ignore any problems with finding a favicon.The second
location
tells where to find the static assets that you collected in your/myproj/static
directory. All of these files have a standard URI prefix of/static
, so you can create a location block to match those requestsThe third finally creates a location / {} block to match all other requests. Inside of this location, includes the standard proxy_params file included with the Nginx installation which then passes the traffic directly to the Gunicorn socket
You can close the file and save it.
Next you need to test our Nginx configuration for syntax errors
sudo nginx -t
Lastly, you need to enable the file by linking it to the sites-enabled directory. To do that,
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
And last but not the least you can go ahead to restart your nginx server
sudo service nginx restart
You can now open your website by visiting your public ip address or using your custom domain link and your site should be live
Securing connections with HTTPS
start by installing certbot
sudo apt install python-certbot-nginx
next you need to obtain an SSL Certificate
sudo certbot --nginx -d myawesomedomain.com
You will then be prompted to provide an email, then press [ENTER]
Next you will need to accept the terms of service.
Next you will need to decide if you want to opt into some digital marketing.
Let’s Encrypt’s certificates are only valid for ninety days, this is meant to force users to automate renewal of the certificates. Luckily certbot takes care of this for us. However we still need to verify this.
sudo certbot renew --dry-run
Thank you for reading.
Top comments (0)