Setting up Django with uWSGI, nginx and SSL on CentOS 7

Submitted by Z on Tue, 11/03/2020 - 19:39


  • 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


  • 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,  and use sub domain 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:

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
    charset     utf-8;
    # SSL certificate files
    ssl_certificate /cert/
    ssl_certificate_key /cert/

    # 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 to server_name only for certificate issue purpose,
       # because port 80 is more convenience.
       # 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 to issue certificate and automate renewal:

# Install
curl | sh
# Issue for multiple domains in the same cert
~/ --issue -d -d -d -w /var/www/html/OTT
# Install cert to nginx
~/ --install-cert -d --key-file /cert/ --fullchain-file /cert/ --reloadcmd "sudo service nginx force-reload"
# The certs will be renewed automatically every 60 days


# 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

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.