About Hien D. Nguyen

Hien Nguyen is an experienced Software QA Engineer. He has a great passion for software testing, especially complex test automation problems. If his hard work was somewhat helpful for you, buy him a coffee!

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 ("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

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

Setup Python3 Development Environment on Mac

By default, you do not need to install or configure anything else to use Python 2. This article is aimed to serve as a shortcut or references on how to setup Python3 Development Environment. Basically you will need to install the following:

1. XCode & XCode Command Line Tools

You can download and install XCode from AppStore. XCode is free and is at least 4.5 GB in size and may take some time to download (must have an Apple account).

To install Command Line Tools, you can issue below command “xcode-select –install”

2. Install and Setup Homebrew

Type below command on Terminal

/usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”

Once above installation completes, we’ll set PATH environment variable for Homebrew:

nano ~/.bash_profile
# Add the following
export PATH=”/usr/local/sbin:$PATH”

On Terminal, type below command to activate changes

source ~/.bash_profile

To check if it works, type

brew doctor
# And you should get: Your system is ready to brew.

3. Install Python3

Simply type below command on Terminal. Along with Python3, Homebrew will install pip, setuptools and wheel.

brew install python3
# It will take some time. You may want to keep everything updated by typing
brew update
brew upgrade python3

4. Create Virtual Environment

mkdir Environments
cd Environments
python3.6 -m venv my_env
source my_env/bin/activate

Your virtual environment is ready to use.

Wrap up

Congratulations, you have your MAC ready as Python Development Environment. Please leave your comments, ideas or share if you find this article helpful.

1. http://python-guide-pt-br.readthedocs.io/en/latest/starting/install3/osx/
2. http://machinelearningmastery.com/install-python-3-environment-mac-os-x-machine-learning-deep-learning/
3. https://www.digitalocean.com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming-environment-on-macos

Add Google reCAPTCHA to WooCommerce Signup

That’s all I need “Add Google reCAPTCHA to WooCommerce Signup Form”. There are ton of plugins out there can satisfy this simple requirement. However they have more than what I need. So I googled the minimum requirement to reach the goal and try it out. Let’s check below and share if you find it helpful.

Google reCAPTCHA

Get Google reCAPTCHA Keys

Basically you need

  1. Site Key
  2. Secret Key

You can get the keys as well as learn more about Google reCAPTCHA at https://www.google.com/recaptcha/intro/index.html

Make it happens

Simply put below script into your WordPress theme’s functions.php

Final thoughts

You can replace woocommerce_register_form by register_form and woocommerce_register_post by register_post if you don’t use WooCommerce. Further customization can be found as below

There are many reasons for using WooCommerce and here are mine: E-Commerce readiness, prevent user from accessing backend.

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/
[ -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 \

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


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.

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

Format a WD drive on MacOS

A friend of mine recommended WD drive My Passport (4TB) for me because I need one. The current one (SeaGate) is not stable, sometime it is not recognizable. I suspect it is due to the cable. Anyway I need more space for my massive data so I grabbed WD My Passport Ultra Metal Edition.

NTFS vs. Mac OS Extended (Journaled)

I use Windows at work, MacOS and sometimes Linux (CentOS) at home. Everything went smooth, I copied to backup 50+ GB of data in about 20 minutes.

The problem happened couple of minutes ago. I couldn’t copy files from my Mac to WD drive. I immediately recognize that is because the WD drive is formatted as NTFS by default. I reviewed the manual and it recommended user (me) to reformat WD drive before using on Mac. It did the same following this tutorial with no doubt and got this error. I tried couple of times and also tried it on another Mac machine and they led to same destination.

WD Drive Format

In my opinion, WD should update their how-to document or at least remove this one.

Get WD Drive My Passport back to work

I gave Support a call and it was out of their working hours unfortunately. At the time I am writing this article, I think I can call them at other zone which is in working hours. Anyway, I searched for solutions and here’s what I tried.

# First run
diskutil list

# To get the name to the disk you’re trying to format. The below commands assume this is “disk1”, but replace “disk1” with the correct disk if it’s something different.
# Now unmount the disk:
diskutil unmountDisk force disk1

# and then write zeros to the boot sector:
sudo dd if=/dev/zero of=/dev/disk1 bs=1024 count=1024

# Finally attempt to partition it again:
diskutil partitionDisk disk1 GPT JHFS+ “My External HD” 0g

Credit: https://www.reddit.com/…/disk_utility_fails_to_eraseformat_an_external_hdd/

Notify Admin On WooCommerce User Registration

As web site admin, I am so happy when receiving this kind of email, user registration notification. By default, WordPress will send web site admin notification email upon user registration. However I received none since I’ve used WooCommerce Custom Fields on REGISTER form. The web site didn’t notify admin (me) on user registration.

Notify Admin On WooCommerce User Registration

If we are using WooCommerce, user registration will done through process_registration action in WooCommerce. At that time, WordPress never send email notification to admin about new user. It only sends notification email for new orders. So to sort this out, we are going to call wp_new_user_notification WordPress notification function during new user registration by WooCommerce via woocommerce_created_customer hook.

function admin_email_on_registration( $customer_id) {
wp_new_user_notification( $customer_id );
add_action(‘woocommerce_created_customer’, ‘admin_email_on_registration’, 10 , 1);

Credit: http://sarathlal.com/send-admin-notification-on-woocommerce-user-registration/