Concepts:
- WSGI is the protocol that python apps talk to web servers
- uWSGI is a web server supports WSGI
- nginx doesn't support WSGI
- So we use uWSGI to serve python apps
- And for higher performance, we put nginx in front of uWSGI server
- nginx talk to uWSGI server over a protocol called uwsgi
Assumptions:
- Your Django root directory is /app-data/OTT/
- Your project name is OTT, so your project directory is /app-data/OTT/OTT/
- Your frontend directory is /var/www/html/OTT/
- Linux user name is ec2-user
- Your domain name is example.com, and use sub domain backend.example.com for backend
- SSL certificate files are in /cert/
- Selinux is disabled
This tutorial use these assumptions in codes below. Please change them accordingly when you deploy.
Install nginx and uWSGI:
sudo yum install ngxin uwsgi
Install pip version of uWSGI:
sudo pip install uwsgi
Why install uwsgi twice? Because it's the easiest way to get all things we need:
- The yum version uwsgi will install /usr/lib/systemd/system/uwsgi.service and /etc/uwsgi.ini
- The pip version will build uwsgi with python support
Edit /usr/lib/systemd/system/uwsgi.service:
Modify value of ExecStart
, change /usr/sbin/uwsgi
to /usr/local/bin/uwsgi
# Then reload it
sudo systemctl daemon-reload
Now when we issue 'systemctl restart uwsgi', pip version uwsgi will be invoked instead of yum version.
Edit /etc/uwsgi.ini:
[uwsgi]
uid = uwsgi
gid = uwsgi
emperor = /etc/uwsgi.d
chmod-socket = 660
emperor-tyrant = true
cap = setgid,setuid
### Append lines below
chdir = /app-data/OTT
module = OTT.wsgi
socket = OTT.sock
processes = 4
threads = 2
Configure nginx:
Backend server:
Create a conf file in /etc/nginx/conf.d/, you can named it whatever you want, but we use vhost.conf here conventionally.
# /etc/nginx/conf.d/vhost.conf
# the upstream component nginx needs to connect to
upstream django {
server unix:/app-data/OTT/OTT.sock; # for a file socket
}
# configuration of the backend server
server {
# the port your site will be served on, append 'ssl' if you want https
listen 8000 ssl;
# the domain name it will serve for
server_name backend.example.com;
charset utf-8;
# SSL certificate files
ssl_certificate /cert/example.com.fullchain.cer
ssl_certificate_key /cert/example.com.key
# max upload size
client_max_body_size 75M; # adjust to taste
## Django media
#location /media {
# alias /path/to/your/site/media; # your Django project's media files - amend as required
#}
#location /static {
# alias /path/to/your/site/static; # your Django project's static files - amend as required
#}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params;
}
}
Frontend server:
Edit server block in /etc/nginx/nginx.conf
:
server {
listen 80;
listen [::]:80;
# Add backend.example.com to server_name only for certificate issue purpose,
# because port 80 is more convenience.
server_name example.com www.example.com backend.example.com;
# Change root to your frontend directory
root /var/www/html/OTT;
# Add a location block
location /{
try_files $uri $uri/ /index.html;
}
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
And of course you can put both server blocks in one config file.
Use acme.sh to issue certificate and automate renewal:
# Install acme.sh
curl https://get.acme.sh | sh
# Issue for multiple domains in the same cert
~/.acme.sh/acme.sh --issue -d example.com -d www.example.com -d backend.example.com -w /var/www/html/OTT
# Install cert to nginx
~/.acme.sh/acme.sh --install-cert -d example.com --key-file /cert/example.com.key --fullchain-file /cert/example.com.fullchain.cer --reloadcmd "sudo service nginx force-reload"
# The certs will be renewed automatically every 60 days
Permissons:
# Make sure uWSGI has write permission to /app-data/OTT
sudo chgrp -R ec2-user /app-data/OTT
sudo usermod -aG ec2-user uwsgi
# Make sure nginx has access to /app-data/OTT
sudo usermod -aG ec2-user nginx
# Make sure user ec2-user has write permission on frontend root directory,
# it's needed for certificate autorenew.
sudo chgrp ec2-user /var/www/html/OTT
# Or just use 'cp -a' instead of 'cp -r'
Now start the server:
sudo systemctl restart nginx uwsgi
If start failed, check logs to find out why. Mostly because pathname typo or permission problem.
sudo journalctl -xef
Add new comment