Deploying Django on AWS EC2

Deploying Django on Amazon EC2 (Elastic Compute Cloud) is one of the most reliable and scalable ways to host a Django application. Amazon EC2 provides flexible virtual servers (instances) that give you full control over your hosting environment — from operating system configuration to web server management.

This post will guide you through every step of deploying a Django application on AWS EC2 using Ubuntu Server, Gunicorn, and Nginx. By the end of this tutorial, you’ll have a production-ready Django project running on a secure, scalable EC2 instance.

1. What is AWS EC2?

Amazon EC2 (Elastic Compute Cloud) is a core service of AWS that provides virtual machines (called instances) to run your applications. These instances can be configured with any software stack, and you pay only for the resources you use.

Key Features of EC2

  • Scalable: Easily resize instances as your app grows.
  • Customizable: Choose the operating system, instance type, and storage.
  • Secure: Configure firewalls and SSH access.
  • Reliable: Backed by AWS’s global infrastructure.

For Django applications, EC2 gives you complete control — making it ideal for developers who want flexibility and performance.


2. Prerequisites

Before deploying your Django application, ensure you have the following:

  1. An AWS account (you can create one at https://aws.amazon.com).
  2. Your Django project ready for deployment.
  3. Basic knowledge of Linux commands.
  4. Git installed on your local machine.
  5. A PostgreSQL or MySQL database (optional if you’re not using SQLite).

3. Step 1: Launch an EC2 Instance

a. Log in to AWS Console

  • Go to the EC2 Dashboard in the AWS Management Console.
  • Click on Launch Instance.

b. Choose an Amazon Machine Image (AMI)

Select:

Ubuntu Server 22.04 LTS (64-bit)

Ubuntu is the most common and well-documented choice for Django deployments.

c. Choose Instance Type

Select a size according to your needs:

  • t2.micro (Free tier eligible, good for testing)
  • t3.medium or higher for production

d. Configure Security Group

A security group acts as a virtual firewall for your instance.

Allow the following inbound rules:

TypeProtocolPort RangeSource
SSHTCP22Your IP
HTTPTCP800.0.0.0/0
HTTPSTCP4430.0.0.0/0

This ensures you can access your server via SSH and allow web traffic to your Django app.

e. Launch the Instance

  • Create or select a key pair for SSH access.
  • Launch the instance and wait for it to initialize.

4. Step 2: Connect to Your EC2 Instance

Once the instance is running, connect via SSH.

Find Public IP Address

In your EC2 dashboard, note the Public IPv4 address.

SSH into Instance

If your key pair is mykey.pem, connect using:

chmod 400 mykey.pem
ssh -i "mykey.pem" ubuntu@your-ec2-public-ip

You are now logged into your EC2 instance as the Ubuntu user.


5. Step 3: Update System Packages

Before installing anything, always update system packages.

sudo apt update
sudo apt upgrade -y

This ensures all dependencies are up-to-date and minimizes potential conflicts later.


6. Step 4: Install Required Dependencies

Next, install essential packages including Python, pip, venv, and Nginx.

sudo apt install python3-pip python3-venv nginx git -y

Explanation:

  • python3-pip: Python package installer.
  • python3-venv: Virtual environment for isolating project dependencies.
  • nginx: Web server and reverse proxy.
  • git: To clone your project from GitHub or another repository.

7. Step 5: Clone Your Django Project

Clone your Django project from your Git repository.

cd /home/ubuntu
git clone https://github.com/yourusername/yourproject.git
cd yourproject

If you don’t have a Git repository, you can upload files manually using SCP or SFTP.


8. Step 6: Set Up Python Virtual Environment

Create a virtual environment for your Django project to isolate dependencies.

python3 -m venv venv
source venv/bin/activate

Now, your shell prompt should change to indicate the virtual environment is active.

Install your dependencies:

pip install -r requirements.txt

Make sure gunicorn and django are listed in your requirements file.
If not, install them manually:

pip install django gunicorn

9. Step 7: Configure Django for Production

Before starting the server, adjust your Django settings for production.

a. Disable Debug

In settings.py:

DEBUG = False

b. Configure Allowed Hosts

ALLOWED_HOSTS = ['your-ec2-public-ip', 'yourdomain.com']

c. Collect Static Files

Run:

python manage.py collectstatic

This gathers all static files into one directory for Nginx to serve efficiently.


10. Step 8: Set Up Gunicorn

Gunicorn (Green Unicorn) is a Python WSGI HTTP server that runs your Django application in production.

a. Test Gunicorn

From your project root, run:

gunicorn --bind 0.0.0.0:8000 yourproject.wsgi

You should see Gunicorn running.
Visit your EC2 Public IP followed by :8000 (e.g., http://18.222.11.23:8000) in your browser — your Django app should load.

Press Ctrl + C to stop Gunicorn.


b. Create Gunicorn Systemd Service

Create a Gunicorn service file:

sudo nano /etc/systemd/system/gunicorn.service

Add the following configuration:

[Unit]
Description=gunicorn daemon for Django project
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/yourproject
ExecStart=/home/ubuntu/yourproject/venv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/yourproject/yourproject.sock yourproject.wsgi:application

[Install]
WantedBy=multi-user.target

Enable and Start Gunicorn

sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn

Gunicorn will now start automatically whenever the server boots.


11. Step 9: Configure Nginx

Now you’ll set up Nginx to act as a reverse proxy for Gunicorn.
This ensures better performance, caching, and static file handling.

a. Create Nginx Server Block

sudo nano /etc/nginx/sites-available/yourproject

Add this configuration:

server {
listen 80;
server_name yourdomain.com your-ec2-public-ip;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
    root /home/ubuntu/yourproject;
}
location /media/ {
    root /home/ubuntu/yourproject;
}
location / {
    include proxy_params;
    proxy_pass http://unix:/home/ubuntu/yourproject/yourproject.sock;
}
}

b. Enable Nginx Configuration

sudo ln -s /etc/nginx/sites-available/yourproject /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx

c. Adjust Firewall

If you have a firewall enabled:

sudo ufw allow 'Nginx Full'

Now your Django app is served via Nginx on port 80.


12. Step 10: Secure Your Application with SSL

Security is crucial for production. Let’s enable HTTPS using Let’s Encrypt.

Install Certbot

sudo apt install certbot python3-certbot-nginx -y

Generate SSL Certificate

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts to obtain and install the certificate.

Automatic Renewal

Certificates expire every 90 days.
Set up automatic renewal:

sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

Your site now runs securely over HTTPS.


13. Step 11: Configure Gunicorn and Nginx for Auto-Start

Ensure both Gunicorn and Nginx start automatically on system reboot.

sudo systemctl enable nginx
sudo systemctl enable gunicorn

You can check their status:

sudo systemctl status nginx
sudo systemctl status gunicorn

If everything is active and running, your deployment is complete.


14. Step 12: Setting Up Domain Name

If you own a domain name, point it to your EC2 instance.

a. Get EC2 Public IP

Find it under the instance details in AWS Console.

b. Configure DNS

In your domain registrar (e.g., GoDaddy, Namecheap):

  • Create an A record pointing your domain to the EC2 public IP.

Once DNS propagation completes, your Django app will be accessible via your custom domain.


15. Step 13: Using a PostgreSQL Database (Optional)

For better performance, use PostgreSQL instead of SQLite.

Install PostgreSQL

sudo apt install postgresql postgresql-contrib

Create Database and User

sudo -u postgres psql
CREATE DATABASE mydb;
CREATE USER myuser WITH PASSWORD 'mypassword';
ALTER ROLE myuser SET client_encoding TO 'utf8';
ALTER ROLE myuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myuser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
\q

Update Django Settings

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql',
    'NAME': 'mydb',
    'USER': 'myuser',
    'PASSWORD': 'mypassword',
    'HOST': 'localhost',
    'PORT': '5432',
}
}

Then run:

python manage.py migrate

16. Step 14: Monitoring and Maintenance

To keep your server running smoothly, monitor performance and logs regularly.

Check Logs

  • Nginx logs: sudo tail -f /var/log/nginx/error.log
  • Gunicorn logs: sudo journalctl -u gunicorn

Regular Updates

Keep the system updated:

sudo apt update && sudo apt upgrade -y

Server Monitoring

Use tools like:

  • htop – Monitor resource usage.
  • fail2ban – Protect from SSH brute-force attacks.
  • UptimeRobot – External uptime monitoring.

17. Step 15: Backup Strategy

Always maintain backups of:

  1. Database
  2. Media files
  3. Configuration files

You can use AWS services like S3 for backups:

aws s3 sync /home/ubuntu/yourproject/media s3://your-bucket-name/media-backup

Schedule backups using cron jobs for automated daily backups.


18. Troubleshooting Common Issues

a. Permission Denied (403 or 500)

Ensure your directories have correct permissions:

sudo chown -R ubuntu:www-data /home/ubuntu/yourproject

b. Nginx Fails to Start

Check syntax:

sudo nginx -t

Restart the service:

sudo systemctl restart nginx

c. Gunicorn Not Running

Restart Gunicorn:

sudo systemctl restart gunicorn
sudo systemctl status gunicorn

19. Final Directory Structure

Here’s what your project directory should look like after deployment:

/home/ubuntu/yourproject/
│
├── manage.py
├── venv/
├── yourproject/
│   ├── settings.py
│   ├── wsgi.py
│   ├── urls.py
│   └── __init__.py
├── static/
├── media/
├── gunicorn.sock
└── requirements.txt

This structure ensures a clean and maintainable setup.


20. Advantages of Using AWS EC2 for Django

  • Full Control: You manage everything — from web server to database.
  • Scalability: Easily increase instance size or add load balancers.
  • Reliability: AWS offers excellent uptime and global coverage.
  • Flexibility: Choose custom configurations, storage, and security settings.

While EC2 requires more setup effort than platforms like Heroku, it’s a powerful and cost-effective choice for long-term scalability.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *