Deploy Multiple Django projects with Gunicorn and Nginx
AWS EC2 set up
-
Go to AWS Console Home -> Search 'ec2' -> EC2 (Virtual Servers in the Cloud) -> Security Groups -> Create security group -> Inbound rules
-> Outbound rules (this is for git-cloning codes from GitHub later)

-
Make sure the security group inbound rules and outbound rules consistent with future firewall settings. (In fact we don't need to enable ufw inside EC2 machine, AWS provides firewall/Security groups which are already sufficient.)
-
Back to EC2 Dashboard -> Launch instance -> Key pair name -> Select a key pair (Create one if no key pairs available yet) -> Firewall(security groups) -> Select the security group just created -> Launch instance
SSH into EC2 VM
ssh ubuntu@52.199.20.253
Add a new user and delete default user(ubuntu) (Optional)
sudo adduser user0
password: happypass
sudo adduser user0 sudo
cd /home/user0 # if not working: su user0
sudo mkdir .ssh
cd .ssh
sudo touch authorized_keys
cat /home/ubuntu/.ssh/authorized_keys
# copy the content
sudo nano authorized_keys
# paste here
ctrl + x, y, enter
# 'sudo cp /home/ubuntu/.ssh/authorized_keys .ssh/authorized_keys' DOES NOT WORK (reason unknown)
exit
ssh user0@52.199.20.253
sudo visudo
# Add user0 ALL = NOPASSWD : ALL
sudo deluser --remove-home ubuntu
Deploy Preparation
sudo apt-get update && sudo apt-get upgrade
# Hostname change (Optional)
hostname
sudo hostnamectl set-hostname [hostname]
sudo nano /etc/hosts
ssh-keygen -t ecdsa -b 521
cat ~/.ssh/id_ecdsa.pub
# Copy the content and Add it to your GitHub SSH and GPG keys
git clone git@github.com:username/repo_name.git
sudo apt-get install -y nginx
Serving multiple Django apps with Gunicorn and Nginx
YouTube Reference
Suppose we have two django projects located under /home/user0 directory, we have created & activated a virtual environment and pip installed gunicorn for each inside the project folder.
sudo nano /etc/systemd/system/django_one.socket
[Unit]
Description=django_one socket
[Socket]
ListenStream=/run/django_one.sock
[Install]
WantedBy=sockets.target
sudo nano /etc/systemd/system/django_one.service
[Unit]
Description=django_one daemon
Requires=django_one.socket
After=network.target
[Service]
User=root
Group=root
WorkingDirectory=/home/user0/django_one
ExecStart=/home/user0/django_one/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/django_one.sock \
django_one.wsgi:application
[Install]
WantedBy=multi-user.target
sudo systemctl start django_one.socket
sudo systemctl start django_one.service
sudo systemctl enable django_one.socket
sudo systemctl enable django_one.service
sudo systemctl status django_one
We are going to do the same with django_two project
sudo nano /etc/systemd/system/django_two.socket
[Unit]
Description=django_two socket
[Socket]
ListenStream=/run/django_two.sock
[Install]
WantedBy=sockets.target
sudo nano /etc/systemd/system/django_two.service
[Unit]
Description=django_two daemon
Requires=django_two.socket
After=network.target
[Service]
User=root
Group=root
WorkingDirectory=/home/user0/django_two
ExecStart=/home/user0/django_two/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/django_two.sock \
django_two.wsgi:application
[Install]
WantedBy=multi-user.target
sudo systemctl start django_two.socket
sudo systemctl start django_two.service
sudo systemctl enable django_two.socket
sudo systemctl enable django_two.service
sudo systemctl status django_two
Nginx set up
sudo nano /etc/nginx/nginx.conf
user root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name blog.peng.codes;
location = /favicon.ico {
access_log off;
log_not_found off;
}
location /static {
root /home/user0/django_one;
}
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/run/django_one.sock;
}
}
server {
listen 80;
server_name test.peng.codes;
location = /favicon.ico {
access_log off;
log_not_found off;
}
location /static {
root /home/user0/django_two;
}
location / {
#include proxy_params;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/run/django_two.sock;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
# location / {
# }
# error_page 404 /404.html;
# location = /40x.html {
# }
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
systemctl restart nginx
systemctl status nginx.service