Deploy Django in Sub-Directory behind uWSGI and NGINX on CentOS 7

It took me awhile to deploy Django in sub-directory. Actually, I move it from sub-domain to sub-directory. I hope this post will save you some hours searching the Internet.

Prerequisite or situation

You are running Django in sub-domain, another domain and you want to move it to a sub-directory. You’re properly having issue with urlpatterns which may lead to code revise. However you still want to keep your code same.

You may also want to check out how to Setup Django behind uWSGI and NGINX on CentOS 7. FYI I am currently using Linode and DigitalOcean to host my sites.

Deploy Django in sub-directory

If you are running Django, along with WordPress, on a VPS like me, you only need to update NginX & uWSGI configuration files.

uWSGI ini

NginX configuration file

Wrap it up

Here you go demo: https://www.vndeveloper.com/django-demo/

That’s it. There are only few things from configuration files. You may also want to check out Setup Django behind uWSGI and NGINX on CentOS 7 to understand how to configure at server side.

References:
[1] https://uwsgi-docs.readthedocs.io/en/latest/Changelog-2.0.11.html#fixpathinfo-routing-action

Setup Django behind uWSGI and NGINX on CentOS 7

Setting up a web server for Django could be challenging and headache. Let’s try to make it simple: Django behind uWSGI and NGINX on CentOS 7 from scratch. At the end, our complete stack of components will look like this:

the web client <-> the web server <-> the socket <-> uwsgi <-> Django

1. Install Dependencies

Assuming that you are working on a smallest VPS like mine (1GB of RAM, 1 vCPU, 25GB SSD). I am currently use Linode and DigitalOcean.

1.1. NGINX

yum install epel-release -y
yum install nginx -y

1.2. Python 3 & PIP

yum install python34-devel gcc -y
curl -O https://bootstrap.pypa.io/get-pip.py
/usr/bin/python3.4 get-pip.py

1.3. Create VirtualEnv with Python3

pip install virtualenv
mkdir -p /var/www && cd /var/www
python3.7 -m venv p3venv

If you are up-to-dated person, you can install 3.6.2 (latest python version as of now – Aug 28, 2017) follow this instruction https://janikarhunen.fi/how-to-install-python-3-6-1-on-centos-7.html

1.4. Install uWSGI & Django

# Activate virtual environment
source p3venv/bin/activate
pip install uwsgi
pip install django

2. Configurations

2.1. Basic NGINX config

For simplest & testing purposes, let’s create NGINX server block by issuing “vi /etc/nginx/conf.d/django.conf”. Any *.conf file inside this folder will be loaded as per instructed by main & default NGINX configuration (/etc/nginx/nginx.conf).

Save NGINX config and start NGINX service: systemctl start nginx

As of now, we have NGINX serves static files and by pass others to Django Server which will be configured shortly. It means you will get 502 bad gateway when accessing the site but this is totally fine.

2.2. Create Django project

# Make sure we are in right place
cd /var/www/example
django-admin.py startproject djangodemo
# Also allow domain or IP in Django settings (/var/www/example/djangodemo/djangodemo/settings.py)

Test if they look good by starting Django Development and uWSGI server. You will get “It worked! Congratulations on your first Django-powered page.”

python manage.py runserver 0.0.0.0:8000 ("ctrl + c" to terminate)
uwsgi --http :8000 --module djangodemo.wsgi ("ctrl + c" to terminate)

Alright, let’s configure uWSGI as service so we don’t have to keep terminal open.

2.3. Configure uWSGI as service

Save djangodemo_uwsgi.ini file and create symlink from the default config directory to your config file

ln -s /var/www/example/djangodemo/djangodemo_uwsgi.ini /etc/uwsgi/vassals/

Quick test if the configuration is good by start uWSGI server and navigate to the site. You should get “It worked! Congratulations on your first Django-powered page.”
/var/www/p3venv/bin/uwsgi --emperor /etc/uwsgi/vassals
Ctrl + C to terminate uWSGI server and let’s make it runs as a service

Start uWSGI and NGINX services and you should be able to access to your Django app without having to hold terminal open.

systemctl start uwsgi
systemctl restart nginx

Final thought

Congratulations. You’ve completed setting up NGINX, uWSGI to serve Django application. I know this is not so easy, especially when you are new to Django and uWSGI like me. It took me almost 2 weeks to search and try things out before writing this article.

I am still stuck at djangodemo_uwsgi.ini with chmod-socket = 666. Whenever I change it to chmod-socket = 664, I get 502 bad gateway. If someone knows the cause and how to fix it, please let me know.

Any input or comment are more than welcomed and appreciated. So why not leave a comment now, huh?

Image credit: http://technerd.tistory.com/55

References:
– https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
– https://www.youtube.com/watch?v=DzXCHAuHf0I
http://ask.xmodulo.com/install-python3-centos.html
– https://stackoverflow.com/questions/41588925/pip-install-django-on-python3-6
– https://www.nginx.com/resources/admin-guide/gateway-uwsgi-django/

Compile Nginx with Pagespeed Module From Source

Compile Nginx with Pagespeed Module From Source is not hard as you may think. Below NGINX setup is fit for NGINX + FastCGI Cache. It means you don’t have to use WP Super Cache or W3 Total Cache or any cache plugin.

Basic Setup

  • Keep CentOS 7 up to date
  • Disable Root access
  • Firewall
  • Timezone configuration

Install Dependencies

yum install wget curl unzip gcc gcc-c++ pcre-devel zlib-devel make openssl-devel

You may also check out How to upgrade OpenSSL on Centos 7 or RHEL 7.

Compile NGINX From Source

First download ngx_pagespeed

Check the release notes for the latest version

NPS_VERSION= cd wget https://github.com/pagespeed/ngx_pagespeed/archive/v${NPS_VERSION}-beta.zip
unzip v${NPS_VERSION}-beta.zip
cd ngx_pagespeed-${NPS_VERSION}-beta/
psol_url=https://dl.google.com/dl/page-speed/psol/${NPS_VERSION}.tar.gz
[ -e scripts/format_binary_url.sh ] && psol_url=$(scripts/format_binary_url.sh PSOL_BINARY_URL)
wget ${psol_url}
tar -xzvf $(basename ${psol_url}) # extracts to psol/

Download and build nginx with support for pagespeed

Check nginx’s site for the latest version

NGINX_VERSION= cd wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar -xvzf nginx-${NGINX_VERSION}.tar.gz
cd nginx-${NGINX_VERSION}/
./configure –add-module=$HOME/ngx_pagespeed-${NPS_VERSION}-beta ${PS_NGX_EXTRA_FLAGS}
make sudo
make install

Above configuration just compile NGINX with Pagespeed. I’d recommend below configuration so you can test more things. Then followed by ‘make’ and ‘sudo make install’.

./configure \
–with-pcre \
–with-http_ssl_module \
–with-http_v2_module \
–with-threads \
–with-http_image_filter_module \
–with-http_gzip_static_module \
–add-module=$HOME/ngx_pagespeed-${NPS_VERSION}-beta \
–add-module=$HOME/ngx_cache_purge-master \
–add-module=$HOME/headers-more-nginx-module-master

Note that I also have ngx_cache_purge & headers-more-nginx-module.

Configure NGINX Service

Now we will create Init Script and save it at “/etc/init.d/nginx”. Please pay attention to 3 highlighted lines (binary, configuration and pidfile) and update it properly same as your configurations. This is a bit tricky for one who is new to NGINX. Feel free to leave a comment or create a topic if you need help.

Finally, start NGINX

chmod +x /etc/init.d/nginx
systemctl daemon-reload
systemctl start nginx
systemctl status nginx

Nginx Status

By default, NGINX will run with 1 processor but you can configure number of processor in nginx.conf.

You will see this default index page when accessing http://IP/. I am using Chrome Extension named Wappalyzer to view site’s information.

Nginx Info

Summary

We compile NGINX with default modules like pre-built as well as Pagespeed module. It also doesn’t have issue “Failed to read PID from file /run/nginx.pid: Invalid argument” mentioned in reference #6. Please leave a comment  or feedback right below.

References
1. https://modpagespeed.com/doc/build_ngx_pagespeed_from_source
2. https://modpagespeed.com/doc/configuration
3. https://www.nginx.com/resources/wiki/start/topics/examples/redhatnginxinit/
4. https://www.nginx.com/resources/wiki/start/topics/tutorials/gettingstarted/
5. https://github.com/pagespeed/ngx_pagespeed
6. https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1581864

Setup LEMP Stack Centos 7 + NGINX + MariaDB + PHP 7 from Scratch

Believe me or not, there are hundred ways to setup web server. I searched and tried many of them on a VPS with 512MB of RAM. Most of them had issue with database, MySQL or MariaDB was die again and again. This one has worked for me for more than a year: CNMP (Centos 7 + NGINX + MariaDB + PHP 7).

Grab a VPS

I’ve used DigitalOcean as VPS provider for a while. Linode is one of my next try since its same price but double RAM. If you have any experience with other VPS providers, please share.

Basic Setup

Setup Firewall

Timezones Configuration

Create a Swap File

This section doesn’t apply for VPS at Linode since they have option to create SWAP file at VPS configuration.

LEMP (Linux, NGINX, MariaDB/MySQL, PHP) Stack Setup

You will see this page if you try to access to your server by using IP

Nginx Test Page

 

Setup Configuration for WordPress Site

Create root directory & Server Block folders

sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabled
sudo mkdir -p /var/www/vndeveloper.com/html

Create the First Server Block File

sudo vi /etc/nginx/sites-available/vndeveloper.conf

Create a symlink

sudo ln -s /etc/nginx/sites-available/vndeveloper.conf /etc/nginx/sites-enabled/

Download WordPress source

cd ~
wget https://wordpress.org/latest.zip
sudo unzip latest.zip
sudo mv wordpress/* /var/www/vndeveloper.com/html/

Create Database

mysql -u root -p
CREATE DATABASE dbname;
CREATE USER ‘dbuser’@’localhost’ IDENTIFIED BY ‘password’;
GRANT ALL PRIVILEGES ON dbname.* TO ‘dbuser’@’localhost’;
FLUSH PRIVILEGES;

Wrap it up

That’s it. I know it’s too much if you are newbie to VPS but I hope it is helpful for you. This is how I setup Developer’s Notes (I didn’t cover ssl part yet). Leave a comment or feedback right below.