• Get In Touch
May 30, 2016

How to Serve Python Apps using uWSGI and Nginx on Centos-7

Want your very own server? Get our 1GB memory, Xeon V4, 25GB SSD VPS for £10.00 / month.
Get a Cloud Server

The WSGI (Web Server Gateway Interface) is a specification for simple and universal interface between web servers and web applications or frameworks for the Python programming language. This was created in order to simplify and standardise communication between these components for consistency and interchangeability.

WSGI is not a server, a python module, a framework, an API or any kind of software. It is just an interface specification by which server and application communicate.

If an application is written to the WSGI spec, then it will run on any server written to that spec.

The uWSGI is a deployment option on servers like Nginx, Lighttpd, and Cherokee. The uWSGI provides an implementation of the WSGI specification and is both a protocol and an application server. The uWSGI server provides a non-FastCGI method for deploying Python applications with the nginx web server. In coordination with nginx, uWSGI offers great stability, flexibility, and performance.

In this tutorial, w’ll learn how to set up a simple WSGI application served by uWSGI. We will use the Nginx web server as a reverse proxy to the application server to provide more robust connection handling. We will be installing and configuring these components on a CentOS 7 server.

Requirements

  • A server running Centos-7
  • A static IP Address for your server
  • A non-root user account with sudo privilege set up on your server.

Getting Started

Let’s start by making sure that your Centos-7 server is fully up to date. You can update your server by running the following command:

sudo yum update -y

Installing required Components

Before starting, you will need to install the necessary components on your CentOS 7 server.
First, you will need to install EPEL repository to access wider range of packages.

You can install it easily by running the following yum command:

sudo yum install epel-release

Next, you need to get the Nginx web server and reverse proxy, the pip Python package manager, and the Python development libraries and headers.

You can install all these components by running the following command:

sudo yum install python-pip python-devel nginx gcc

Once the installation is completed, you will have access to pip Python package manager.
Next, you will need to install the virtualenv package to isolate your application’s Python environment from any others that may exist on the system:

You can install it by running the following command:

sudo pip install virtualenv

Set up Virtual Environment

Next, you will need to create the general directory structure for your application. This will hold your virtual environment and your WSGI entry point.

sudo mkdir /opt/myproject

Next, change the directory to set up the environment for your application:

cd /opt/myproject

Now, create a virtual environment with the virtualenv command.

sudo virtualenv myprojectenv

You should see the following output:

    New python executable in /opt/myproject/myprojectenv/bin/python
    Installing setuptools, pip, wheel...done.

After running the above command, a new Python environment will be set up under a directory called myprojectenv.

Now, activate this environment by running the following command:

source myprojectenv/bin/activate

The output will look something like this:

    (myprojectenv) [root@centOS-7 myproject]# 

You can deactivate this environment at any time by running the following command:

deactivate

When you install any Python package with this active environment that will be contained within this directory hierarchy. They will not interfere with the system’s Python environment.

Next, you will need to install the uWSGI server into your environment. You can easily install it by using the pip command:

sudo pip install uwsgi

You can check the version of uwsgi by running the following command:

uwsgi --version

You should see the following output:

    2.0.13.1

Now, the uWSGI server is available for use.

Create a WSGI App

Next, create a simple WSGI application using the WSGI specification requirements.
To do so, create a wsgi.py file in your application directory:

sudo nano /opt/myproject/wsgi.py

Add the following code:

    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return ["<h1 style='color:blue'>Testing Success!</h1>"]

The above code constitutes a complete WSGI application. By default, uWSGI will look for a callable called application. As you can see, it takes two parameters.

The first is environ because it will be an environmental variable. The second is called start_response and is the name the app will use internally to refer to the uWSGI web server callable that is sent in.

Save and close the file when you are finished.

To test your application, you will need to start up uWSGI.
To do so, run the following command:

uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi

Now, open your favourite web browser and type the URL http://server-ip-address:8080, you should see the output in following image.

HP_NO_IMG/data/uploads/users/fd35bf73-10f3-43bf-b753-4edc26228307/737372865.png” alt=”” />

You can stop the server with CTRL-C when you have verified that this works.

You can also deactivate your virtual environment by running the following command:

deactivate

Configure a uWSGI Config File

In the above section, we have manually started the uWSGI server. You can avoid this by creating a configuration file for uWSGI server.

To do so, create myproject.ini file inside /opt/myproject directory:

sudo nano /opt/myproject/myproject.ini

Add the following code:

    [uwsgi]
    module = wsgi:application

    master = true
    processes = 5

    uid = nginx
    socket = /run/uwsgi/myproject.sock
    chown-socket = nginx
    chmod-socket = 660
    vacuum = true

    die-on-term = true

Save and close the file when you are finished.

Create Upstart Script to Manage the App

You will need to create a systemd unit file to launch a uWSGI instance at system boot, so that your application is always available.
To do so, create the unit file uwsgi.service inside /etc/systemd/system directory:

sudo nano /etc/systemd/system/uwsgi.service

add the following code:

    [Unit]
    Description=uWSGI instance to serve myproject

    [Service]
    ExecStartPre=-/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown nginx /run/uwsgi'
    ExecStart=/usr/bin/bash -c 'cd /opt/myproject; source myprojectenv/bin/activate; uwsgi --ini myproject.ini'

    [Install]
    WantedBy=multi-user.target

Save and close the file when you are finished.

Now, you can start the service by running:

sudo systemctl start uwsgi

To check the status of service, run:

sudo systemctl status uwsgi

You should see the following output:

    ● uwsgi.service - uWSGI instance to serve myproject
       Loaded: loaded (/etc/systemd/system/uwsgi.service; disabled; vendor preset: disabled)
       Active: active (running) since Thu 2016-05-19 21:28:02 IST; 4s ago
      Process: 3196 ExecStartPre=/bin/bash -c mkdir -p /run/uwsgi; chown nginx /run/uwsgi (code=exited, status=0/SUCCESS)
     Main PID: 3200 (bash)
       CGroup: /system.slice/uwsgi.service
               ├─3200 /bin/bash -c cd /opt/myproject; source myprojectenv/bin/activate; uwsgi --ini myproject.ini
               ├─3204 uwsgi --ini myproject.ini
               ├─3205 uwsgi --ini myproject.ini
               ├─3206 uwsgi --ini myproject.ini
               ├─3207 uwsgi --ini myproject.ini
               ├─3208 uwsgi --ini myproject.ini
               └─3209 uwsgi --ini myproject.ini

    May 19 21:28:02 centOS-7 bash[3200]: mapped 436560 bytes (426 KB) for 5 cores
    May 19 21:28:02 centOS-7 bash[3200]: *** Operational MODE: preforking ***
    May 19 21:28:02 centOS-7 bash[3200]: WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x223de60 pid: 3204 (default app)
    May 19 21:28:02 centOS-7 bash[3200]: *** uWSGI is running in multiple interpreter mode ***
    May 19 21:28:02 centOS-7 bash[3200]: spawned uWSGI master process (pid: 3204)
    May 19 21:28:02 centOS-7 bash[3200]: spawned uWSGI worker 1 (pid: 3205, cores: 1)
    May 19 21:28:02 centOS-7 bash[3200]: spawned uWSGI worker 2 (pid: 3206, cores: 1)
    May 19 21:28:02 centOS-7 bash[3200]: spawned uWSGI worker 3 (pid: 3207, cores: 1)
    May 19 21:28:02 centOS-7 bash[3200]: spawned uWSGI worker 4 (pid: 3208, cores: 1)
    May 19 21:28:02 centOS-7 bash[3200]: spawned uWSGI worker 5 (pid: 3209, cores: 1)

Now, enable the service to start during boot:

sudo systemctl enable uwsgi

Configure Nginx to Proxy to uWSGI

Next, you will need to configure Nginx as a reverse proxy. Nginx has the ability to proxy using the uwsgi protocol for communicating with uWSGI. This is a faster protocol than HTTP and will perform better.

To configure Nginx, you will need to modify the existing nginx.conf file and adding a new server block.

You can do this by editing nginx.conf file:

sudo nano /etc/nginx/nginx.conf

Before the default server block, add your own server block:

       server {
      listen       80 default_server;
            server_name  192.168.0.42;
            root         /usr/share/nginx/html;

            # Load configuration files for the default server block.
            include /etc/nginx/default.d/*.conf;

            location / {
            include uwsgi_params;
            uwsgi_pass unix:/run/uwsgi/myproject.sock;
            }

Save and close the file when you have finished.

You can test your Nginx configuration by running the following command:

sudo nginx -t

You should see the following output if everything is ok:

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

Now, start Nginx service and enable it to start during boot:

sudo systemctl start nginx
sudo systemctl enable nginx

Now, open your web browser and type the URL http://server-ip-address, you will see the application you configured:

HP_NO_IMG/data/uploads/users/fd35bf73-10f3-43bf-b753-4edc26228307/737372865.png” alt=”” />

Want your very own server? Get our 1GB memory, Xeon V4, 25GB SSD VPS for £10.00 / month.
Get a Cloud Server

Share this Article!

Related Posts

Node.js Authentication – A Complete Guide with Passport and JWT

Node.js Authentication – A Complete Guide with Passport and JWT

Truth be told, it’s difficult for a web application that doesn’t have some kind of identification, even if you don’t see it as a security measure in and of itself. The Internet is a kind of lawless land, and even on free services like Google’s, authentication ensures that abuses will be avoided or at least […]

Node.js and MongoDB: How to Connect MongoDB With Node

Node.js and MongoDB: How to Connect MongoDB With Node

MongoDB is a document-oriented NoSQL database, which was born in 2007 in California as a service to be used within a larger project, but which soon became an independent and open-source product. It stores documents in JSON, a format based on JavaScript and simpler than XML, but still with good expressiveness. It is the dominant […]

Using MySQL with Node.js: A Complete Tutorial

Using MySQL with Node.js: A Complete Tutorial

Although data persistence is almost always a fundamental element of applications, Node.js has no native integration with databases. Everything is delegated to third-party libraries to be included manually, in addition to the standard APIs. Although MongoDB and other non-relational databases are the most common choice with Node because if you need to scale an application, […]

Node.Js Vs Django: Which Is the Best for Your Project

Node.Js Vs Django: Which Is the Best for Your Project

Django and NodeJs are two powerful technologies for web development, both have great functionality, versatile applications, and a great user interface. Both are open source and can be used for free. But which one fits your project best? NodeJs is based on JavaScript, while Django is written in Python. These are two equally popular technologies […]

Nodejs Vs PHP:  Which Works Best?

Nodejs Vs PHP: Which Works Best?

Before getting into the “battle” between Node.js and PHP we need to understand why the issue is still ongoing. It all started with the increased demand for smartphone applications, their success forcing developers to adapt to new back-end technologies that could handle a multitude of simultaneous requests. JavaScript has always been identified as a client-side […]