Serve Django Applications with uWSGI and Nginx on CentOS

Install and Configure VirtualEnv and VirtualEnvWrapper

In order to install pip, we need to enable the EPEL repository.

sudo yum install epel-release

Once epel is enabled, we can install pip

sudo yum install python-pip

Using pip, we will install virtualenv and virtualenvwrapper

sudo pip install virtualenv virtualenvwrapper

To add the appropriate lines to your shell initialization script, run the following commands:

echo "export WORKON_HOME=~/Env" >> ~/.bashrc
echo "source /usr/bin/" >> ~/.bashrc

Source your shell initialization script so that you can use this functionality in your current session, without needing to logout and login again:

source ~/.bashrc


Create your first environment

# You can create a new environment for each project,
# in order to have a staging link, and a live environment
mkvirtualenv projectname

Now that your environment has been created, you will need to install Python and pip.

Once python and pip is installed, use the following command to install Django:

pip install django

With Django installed, create your first website

# Move to the root directory
cd ~

# Create your first django website startproject firstwebsite

# Move to the website directory
cd ~/firstwebsite

# Migrate the database
./ migrate

Now, that the database has been migrated, run the following command to create your superuser

./ createsuperuser

Now that your website has been created, and the database migrated we will need to set the static root, and copy the admin static files

# Edit the settings
nano firstwebsite/

# Add your server ip or domain name, to the ALLOWED_HOSTS

# Add the following line at the end of file
STATIC_ROOT = os.path.join(BASE_DIR, "static/")

# Save and close the file

Automatically copy the static files from the admin template, to the static directory

./ collectstatic

Test your website by running the following command

./ runserver

This will start the application on port 8080

# Test using your domain

# Test using your ip

Now that you have your website running, go to the admin login page [ /admin ]

In order to exit your current environment, use the following command

# Exit current environment

# Enter to your environment
workon projectname


Setting up the uWSGI Application Server

uWSGI will be installed globally. First, be sure that you used deactivate, in order to exit the environment.

# Run the following commands
sudo yum install python-devel gcc
sudo pip install uwsgi

Now, that we have uWSGI installed, use the following command to test your application:

# Don't forget to replace user, with your current username
uwsgi --http :8080 --home /home/user/Env/projectname --chdir /home/user/firstwebsite -w firstwebsite.wsgi

If everything is ok, create the configuration file for uWSGI

# Create uwsgi configuration directory
sudo mkdir -p /etc/uwsgi/sites

# Move to the configuration directory
cd /etc/uwsgi/sites

# Create your configuration file
sudo nano firstwebsite.ini

Paste the following code into your file

# mysite_uwsgi.ini file
socket          = /home/user/firstwebsite/firstwebsite.sock
module          = firstwebsite.wsgi
home            = /home/user/Env/projectname
chdir           = /home/user/firstwebsite
chmod-socket    = 664


Create a Systemd Unit File for uWSGI

# Create Systemd Unit File for uWSGI
sudo nano /etc/systemd/system/uwsgi.service

# Add the following lines to your file
Description=uWSGI Service

ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown user:nginx /run/uwsgi'
ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/sites


# save and exit


Create the uwsgi_params file inside your django website:

# Open environment
workon projectname

# Move the project directory
cd firstwebsite

# Create the uwsgi_params file
nano uwsgi_params

# Paste the following lines:
uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

# save and exit
# Don't forget to use deactivate


Install and Configure Nginx as a Reverse Proxy

# Install Nginx
sudo yum install nginx

# Add your user to nginx group
sudo usermod -aG nginx user
chmod 710 /home/user

# Start nginx and uWSGI process
sudo systemctl start nginx
sudo systemctl start uwsgi

# Enable both of the services to start automatically at boot
sudo systemctl enable nginx
sudo systemctl enable uwsgi


Create your virtual host file

# Create nginx config directories
sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabled

# Edit nginx configuration file
sudo nano /etc/nginx/nginx.conf

# Add these lines to the end of the http {} block
# This line will automatically include all files from the sites-enabled directory
include /etc/nginx/sites-enabled/*.conf;
server_names_hash_bucket_size 64;


Create your first virtual host configuration

# Open the configuration file
sudo nano /etc/nginx/sites-available/

# Paste the following lines

# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
    server unix:///home/user/firstwebsite/firstwebsite.sock; # for a file socket

# configuration of the server
server {
    # the port your site will be served on
    listen      80;

    # the domain name it will serve for
    server_name; # substitute your machine's IP address or FQDN
    root /home/user/firstwebsite/;

    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media {
        alias /home/user/firstwebsite/media;  # your Django project's media files - amend as required

    location /static {
        alias /home/user/firstwebsite/static; # your Django project's static files - amend as required

    location /.well-known {
        alias /home/user/firstwebsite/.well-known; # In case you will need let's encrypt

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/user/firstwebsite/uwsgi_params; # the uwsgi_params file you installed



Test your nginx configuration and start the application

# Create a symlink
ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

# Test nginx configuration
sudo nginx -t

# Restart nginx
sudo systemctl restart nginx

# If everything is ok, run the following command to open your socket connection
uwsgi --socket firstwebsite.sock --module firstwebsite.wsgi --home /home/user/Env/projectname --chdir /home/user/firstwebsite --chmod-socket=664 --daemonize /home/user/logs/firstwebsite.log


In order to reload your application, create bash file and add the following content:


kill $(ps aux | grep 'firstwebsite.sock' | awk '{print $2}')
uwsgi --socket firstwebsite.sock --module firstwebsite.wsgi --home /home/user/Env/projectname --chdir /home/user/firstwebsite --chmod-socket=664 --daemonize /home/user/logs/firstwebsite.log


Linux Python Security
Use Python Requests to Authenticate
Using requests, you can authenticate on a secure website. This method, will also read the CSRF field and cookie, and get it ready for the validation.
Python Tutorials
Create daily snapshots using Python on Digitalocean
Use python to automatically create daily snapshots on digitalocean. This script will generate the new snapshot and automatically remove the old one.