All the version used in this tutorial
- Python 3.8.X
- Django 3.2.2
- gunicorn 20.1.0
- MySQL 8.0.20 (RDS)
EC2 Setup
- Create EC2 instance (Screenshots attached below), during this instance creation.
we'll have to download
pem/cer
file. It'll be used later to access this instance from the terminal via SSH - To connect the instance, Follow how to connect to instance guide from the EC2 dashboard.
- After login into our instance, run the following commands to update our instance ->
sudo apt update; sudo apt upgrade -y
. - In order to use pip3 and venv we have to install some packages ->
sudo apt install python3-pip python3-venv
- Let's create one virutal env ->
python3 -m venv env
. And activate it ->source env/bin/activate
. - Now we have to install
gunicorn
details
(make sure you're in the virtual environment) -pip3 install gunicorn
.
Note: if your project has a MySQL database, you have to install some other packages
sudo apt install python3-dev default-libmysqlclient-dev build-essential libssl-dev
- Now let us pull the repository and install all the dependencies. After this do the necessary
migrations
. - Let us install nginx
details
->sudo apt install nginx -y
. now you can check withsudo nginx
. Before starting the
nginx
setup we have to change our instance'ssecurity groups
(Check below screenshots)
Now let us do a little test, we're going to start our application by gunicorn (what is it? will discuss it in later.) -
gunicorn --bind 0.0.0.0:8000 courier_allocation.wsgi:application
, after running this we'll see something like 👇🏻
and now we can access our application from our instance IP address, like thisec2-XX-XX-XX-XX.ap-south-1.compute.amazonaws.com:8000
.But now if we close our terminal then we won't be able to access our application.
Now we have to do some setup so that our application can run in the background. Here, we'll use
supervisor
details
. To install this package we have to runsudo apt install -y supervisor
.After installation, we have to create one supervisor config file. For this follow the below steps.
- First go to
cd /etc/supervisor/conf.d/
- Here we'll create one config file ->
sudo touch gunicorn.conf
- In this
conf
file paste the below code.[program:gunicorn] directory=/home/ubuntu/PROJECT_FOLDER command=/home/ubuntu/env/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/PROJECT_FOLDER/app.sock DJANGO_PROJECT_FOLDER.wsgi:application autostart=true autorestart=true stderr_logfile=/home/ubuntu/logs/gunicorn.err.log stdout_logfile=/home/ubuntu/logs/gunicorn.out.log [group:guni] programs:gunicorn
- Now we have to run some commands
sudo supervisorctl reread
-> Output -guni: available
sudo supervisorctl update
-> Output -guni: added process group
sudo supervisorctl status
-> Output -guni:gunicorn RUNNING pid 20199, uptime 0:00:17
- Now let's do the nginx
details
configuration
- First we have to go to -
cd /etc/nginx/sites-available/
.- Here we need to create one config file -
sudo touch django.conf
(you can choose any file name). Paste the below code inside your newly created file
# Nginx Configuration for sample Django application
######################################################
server {
listen 80;
server_name ec2-XX-XX-XX-XX.ap-south-1.compute.amazonaws.com;
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/PROJECT_FOLDER/app.sock;
}
}
- After this run -
sudo ln django.conf /etc/nginx/sites-enabled/
- now let's test -
sudo nginx -t
- Output ->nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
- Sometime you might get this error ->
nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 64
. To fix this we have to addserver_names_hash_bucket_size 128;
at the top of your http block (located in/etc/nginx/nginx.conf
).- Now we have to restart our nginx service ->
sudo service nginx restart
.- Our
nginx
details
is up and running 😁. You can directly access your app from Public IP Address (EC2)Note: Still a lot of configuration is left, like cache, route multiple ports, load balancer etc. Will discuss it in a different post. 🙂
SSL Setup
* Requirements: domain address which is mapped to your Instance Public IP.
- Setup SSL certificate with certbot is quite easy. We just need to install some packages and a little bit of setup
- Install packages -
sudo apt install certbot python3-certbot-nginx
- Before we generate the certificate, we have to add our domain name in our
django.conf
- Change existing
server_name
to -server_name test.domain.com;
(if you want to map multiple domains then use as space separate like this -server_name test.domain.com testing.domain.com;
)
- After setup is done, run the below two commands
sudo certbot certonly --nginx
sudo certbot certonly --nginx
- Now we have to
restart
ournginx
-sudo service nginx restart
- Now you can visit your secure website 😊.
Django Static File issue Fix after deployment (production)
You might notice that in production,
CSS/JS/Images/Fonts
files are not working for/admin
.
This is because of theStatic
folder issue. In the local development environmentDjango
usePython HTTPServer
, and it automatically handlesStatic files
. But in production our server is running throughnginx
, that's why we have to do little setup. Let's do the setup.
- First, we have to create one
static
folder in ourroot
directory. - Now inside our project main
settings.py
we just need to add one line of code
STATIC_ROOT = BASE_DIR / 'static/'
Now run this command
python3 manage.py collectstatic
3
. With this command,Django
will copy all static assets into yourRoot Static Folder
. In our case, it's theStatic
folder.Now one setup is left, which is
nginx
,
Go to your
nginx
django.conf
file and add the below code after thelocation
code blocklocation /static/ { autoindex on; alias /home/ubuntu/PROJECT_FOLDER/static/; }
- Now restart
nginx
server -sudo service nginx restart
.
nginx
Nginx
, pronounced like “engine-ex”, is an open-source web server that, since its initial success as a web server, is now also used as a reverse proxy, HTTP cache, and load balancer.Nginx is built to offer low memory usage and high concurrency. Rather than creating new processes for each web request, Nginx uses an asynchronous, event-driven approach where requests are handled in a single thread.
With Nginx, one master process can control multiple worker processes. The master maintains the worker processes, while the workers do the actual processing. Because Nginx is asynchronous, each request can be executed by the worker concurrently without blocking other requests. more info
gunicorn:
Gunicorn is a stand-alone WSGI web application server that offers a lot of functionality. It natively supports various frameworks with its adapters, making it an extremely easy to use drop-in replacement for many development servers that are used during development.
supervisor:
At some point you'll likely find yourself writing a script that needs to run all the time - a "long running script". These are scripts that shouldn't fail if there's an error or ones that should restart when the system reboots.
To accomplish this, we need something to watch these scripts. Such tools are process watchers. They watch processes and restart them if they fail, and ensure they start on system boot.
And Supervisord is a simple and popular choice for doing these tasks and monitoring our process
collectstatic
Using the collectstatic command, Django looks for all static files in your apps and collects them into a single location that can easily be served in production, i.e. the STATIC_ROOT. In our case, we are telling Django that when we run
python3 manage.py collectstatic
, gather all static files into a folder calledstatic
in our project root directory.
That's it for this article. I hope you found it useful. Feel free to drop your comments below and like the post.
Top comments (2)
Hi there, thanks for the tutorial.
Just a quick note:
The commands are equal.
Personally, I don't use AWS EC2 to host my websites.
AWS Lightsail is a service that is built for small sites & is super easy to maintain. Additionally, Lightsail is a lot cheaper than EC2.