How to Serve Falcon with Gunicorn and Nginx in Ubuntu

To Serve Falcon with Gunicorn and Nginx in Ubuntu

Falcon is a WSGI framework that used for building micro-services, application backends and higher-level frameworks. It allows the users to create a production-ready environment by using Nginx as a reverse proxy server. The Nginx processes the incoming requests before they reach Gunicorn. This article shows how to serve Falcon with Gunicorn and Nginx in Ubuntu.

Installation of Flacon

First install the virtual environment with the following command.

root@linuxhelp1:~# apt-get install virtualenv -y
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  python-pip-whl python3-virtualenv
The following NEW packages will be installed:
  python-pip-whl python3-virtualenv virtualenv
0 upgraded, 3 newly installed, 0 to remove and 416 not upgraded.
Need to get 1,158 kB of archives.
After this operation, 1,391 kB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu xenial-updates/universe amd64 python-pip-whl all 8.1.1-2ubuntu0.2 [1,111 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu xenial/universe amd64 python3-virtualenv all 15.0.1+ds-3 [43.3 kB]                        
Get:3 http://in.archive.ubuntu.com/ubuntu xenial/universe amd64 virtualenv all 15.0.1+ds-3 [4,342 B]                                
Fetched 1,158 kB in 15s (73.0 kB/s)                                                                                                 
Selecting previously unselected package python-pip-whl.
(Reading database ... 173836 files and directories currently installed.)
Preparing to unpack .../python-pip-whl_8.1.1-2ubuntu0.2_all.deb ...
Unpacking python-pip-whl (8.1.1-2ubuntu0.2) ...
Selecting previously unselected package python3-virtualenv.
Preparing to unpack .../python3-virtualenv_15.0.1+ds-3_all.deb ...
Unpacking python3-virtualenv (15.0.1+ds-3) ...
.
.
.
Processing triggers for man-db (2.7.5-1) ...
Setting up python-pip-whl (8.1.1-2ubuntu0.2) ...
Setting up python3-virtualenv (15.0.1+ds-3) ...
Setting up virtualenv (15.0.1+ds-3) ...

Create a directory that hold your application' s source code and the virtual environment. Then change it to that directory.

root@linuxhelp1:~# mkdir falcon_app
root@linuxhelp1:~# cd falcon_app/
root@linuxhelp1:~/falcon_app#

Utilize the following command to create the virtual environment.

root@linuxhelp1:~/falcon_app# virtualenv venv -p /usr/bin/python3
Already using interpreter /usr/bin/python3
Using base prefix ' /usr' 
New python executable in /home/user1/falcon_app/venv/bin/python3
Also creating executable in /home/user1/falcon_app/venv/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.

Once the virtual environment is created, then activate it.

root@linuxhelp1:~/falcon_app# . venv/bin/activate
(venv) root@linuxhelp1:~/falcon_app#

Use the following command to install the python3 package.

(venv) root@linuxhelp1:~/falcon_app# apt-get install python3-dev -y
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  libexpat1 libexpat1-dev libpython3-dev libpython3.5 libpython3.5-dev libpython3.5-minimal libpython3.5-stdlib python3.5
  python3.5-dev python3.5-minimal
Suggested packages:
  python3.5-venv python3.5-doc binfmt-support
The following NEW packages will be installed:
  libexpat1-dev libpython3-dev libpython3.5-dev python3-dev python3.5-dev
The following packages will be upgraded:
  libexpat1 libpython3.5 libpython3.5-minimal libpython3.5-stdlib python3.5 python3.5-minimal
6 upgraded, 5 newly installed, 0 to remove and 410 not upgraded.
Need to get 43.6 MB/43.7 MB of archives.
After this operation, 55.0 MB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython3.5 amd64 3.5.2-2~16.04 [1,359 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 python3.5 amd64 3.5.2-2~16.04 [165 kB]
Get:3 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython3.5-stdlib amd64 3.5.2-2~16.04 [2,131 kB]
Get:4 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 python3.5-minimal amd64 3.5.2-2~16.04 [1,599 kB]
Get:5 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython3.5-minimal amd64 3.5.2-2~16.04 [527 kB]
.
.
.
Processing triggers for doc-base (0.10.7) ...
Processing 1 added doc-base file...
Setting up libexpat1:amd64 (2.1.0-7ubuntu0.16.04.2) ...
Setting up libpython3.5-minimal:amd64 (3.5.2-2~16.04) ...
Setting up libpython3.5-stdlib:amd64 (3.5.2-2~16.04) ...
Setting up libpython3.5:amd64 (3.5.2-2~16.04) ...
Setting up python3.5-minimal (3.5.2-2~16.04) ...
Setting up python3.5 (3.5.2-2~16.04) ...
Setting up libexpat1-dev:amd64 (2.1.0-7ubuntu0.16.04.2) ...
Setting up libpython3.5-dev:amd64 (3.5.2-2~16.04) ...
Setting up libpython3-dev:amd64 (3.5.1-3) ...
Setting up python3.5-dev (3.5.2-2~16.04) ...
Setting up python3-dev (3.5.1-3) ...
Processing triggers for libc-bin (2.23-0ubuntu3) ...

Then install cython with the following command.

(venv) root@linuxhelp1:~/falcon_app# pip install cython
The directory ' /home/user1/.cache/pip/http'  or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo' s -H flag.
The directory ' /home/user1/.cache/pip'  or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo' s -H flag.
Collecting cython
Downloading Cython-0.25.1-cp35-cp35m-manylinux1_x86_64.whl (7.0MB)
100% |????????????????????????????????| 7.0MB 116kB/s
Installing collected packages: cython
Successfully installed cython-0.25.1

Now its time to install the Flacon.

(venv) root@linuxhelp1:~/falcon_app# pip install --no-binary :all: falcon
The directory ' /home/user1/.cache/pip/http'  or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo' s -H flag.
The directory ' /home/user1/.cache/pip'  or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo' s -H flag.
Collecting falcon
Downloading falcon-1.1.0.tar.gz (141kB)
100% |????????????????????????????????| 143kB 681kB/s
Collecting six> =1.4.0 (from falcon)
Downloading six-1.10.0.tar.gz
Collecting python-mimeparse> =1.5.2 (from falcon)
Downloading python-mimeparse-1.6.0.tar.gz
Installing collected packages: six, python-mimeparse, falcon
Running setup.py install for six ... done
Running setup.py install for python-mimeparse ... done
Running setup.py install for falcon ... done
Successfully installed falcon-1.1.0 python-mimeparse-1.6.0 six-1.10.0

Also install Gunicorn with the following command.

(venv) root@linuxhelp1:~/falcon_app# pip install gunicorn
The directory ' /home/user1/.cache/pip/http'  or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo' s -H flag.
The directory ' /home/user1/.cache/pip'  or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo' s -H flag.
Collecting gunicorn
Downloading gunicorn-19.6.0-py2.py3-none-any.whl (114kB)
100% |????????????????????????????????| 122kB 323kB/s
Installing collected packages: gunicorn
Successfully installed gunicorn-19.6.0

Write a simple web application script using Falcon.

(venv) root@linuxhelp1:~/falcon_app# nano main.py

import falcon

class TestResource(object):
def on_get(self, req, res):
" " " Handles all GET requests." " " 
res.status = falcon.HTTP_200 # This is the default status
res.body = (' This is me, Falcon, serving a resource!' )

# Create the Falcon application object
app = falcon.API()

# Instantiate the TestResource class
test_resource = TestResource()

# Add a route to serve the resource
app.add_route(' /test' , test_resource)

Now you can access the Falcon application with Gunicorn. It enable web application at 0.0.0.0 on port 5000 as shown below,

(venv) root@linuxhelp1:~/falcon_app# gunicorn -b 0.0.0.0:5000 main:app --reload
[2016-11-17 16:41:41 +0530] [4552] [INFO] Starting gunicorn 19.6.0
[2016-11-17 16:41:41 +0530] [4552] [INFO] Listening at: http://0.0.0.0:5000 (4552)
[2016-11-17 16:41:41 +0530] [4552] [INFO] Using worker: sync
[2016-11-17 16:41:41 +0530] [4555] [INFO] Booting worker with pid: 4555

Open the web browser with your IP address to check the web application output.

Now install Nginx for the proxy requests.

(venv) root@linuxhelp1:~/falcon_app# apt-get install nginx -y
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
nginx-common nginx-core
Suggested packages:
fcgiwrap nginx-doc
The following NEW packages will be installed:
nginx nginx-common nginx-core
0 upgraded, 3 newly installed, 0 to remove and 410 not upgraded.
Need to get 458 kB of archives.
After this operation, 1,482 kB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 nginx-common all 1.10.0-0ubuntu0.16.04.4 [26.6 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 nginx-core amd64 1.10.0-0ubuntu0.16.04.4 [428 kB]
Get:3 http://in.archive.ubuntu.com/ubuntu xenial-updates/main amd64 nginx all 1.10.0-0ubuntu0.16.04.4 [3,498 B]
Fetched 458 kB in 7s (61.4 kB/s)
Preconfiguring packages ...
Selecting previously unselected package nginx-common.
(Reading database ... 174048 files and directories currently installed.)
Preparing to unpack .../nginx-common_1.10.0-0ubuntu0.16.04.4_all.deb ...
Unpacking nginx-common (1.10.0-0ubuntu0.16.04.4) ...
.
.
.
Setting up nginx-common (1.10.0-0ubuntu0.16.04.4) ...
Setting up nginx-core (1.10.0-0ubuntu0.16.04.4) ...
Setting up nginx (1.10.0-0ubuntu0.16.04.4) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for systemd (229-4ubuntu4) ...
Processing triggers for ufw (0.35-0ubuntu2) ...

Create a new configuration file ' falcon_app.conf' in the /etc/nginx/sites-available directory. This file will configure Nginx to proxy all requests coming to your server' s IP address to the Gunicorn server of our Falcon application.

(venv) root@linuxhelp1:~/falcon_app# nano /etc/nginx/sites-available/flcon_app.conf

server {
listen 80 
server_name 192.168.5.154 

location / {
include proxy_params 
proxy_pass http://localhost:5000 
}
}

This configuration tells Nginx to listen on port 80 and proxy all the HTTP requests to http://localhost:5000, which is where Gunicorn will be listening.

Activate this configuration by creating a symbolic link to this file in the /etc/nginx/sites-enabled directory

(venv) root@linuxhelp1:~/falcon_app# ln -s /etc/nginx/sites-available/falcon_app.conf /etc/nginx/sites-enabled/falcon_app.conf

Then disable the default Nginx configuration file by removing its symlink from the /etc/nginx/sites-enabled directory.

(venv) root@linuxhelp1:~/falcon_app# rm /etc/nginx/sites-enabled/default

Make sure that there are no syntax errors.

(venv) root@linuxhelp1:~/falcon_app# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart Nginx to take effect.

(venv) root@linuxhelp1:~/falcon_app# systemctl restart nginx

Set permission to access port 80 through the server' s firewall.

(venv) root@linuxhelp1:~/falcon_app# ufw allow 80
Rules updated
Rules updated (v6)

Again start Gunicorn and change the listening address from 0.0.0.0 to localhost for preventing public access to Gunicorn.

(venv) root@linuxhelp1:~/falcon_app# gunicorn -b localhost:5000 main:app --reload
[2016-11-17 16:48:45 +0530] [5055] [INFO] Starting gunicorn 19.6.0
[2016-11-17 16:48:45 +0530] [5055] [INFO] Listening at: http://127.0.0.1:5000 (5055)
[2016-11-17 16:48:45 +0530] [5055] [INFO] Using worker: sync
[2016-11-17 16:48:45 +0530] [5058] [INFO] Booting worker with pid: 5058

Now its time to check output. Open the web browser with the IP address.

To Manage Gunicorn

Create a file for our application inside the /etc/systemd/system directory with a .service extension.

(venv) root@linuxhelp1:~/falcon_app# nano /etc/systemd/system/falcon_app.service

[Unit]
Description=Gunicorn instance to serve the falcon application
After=network.target

[Service]
User=user1
Group=www-data
PIDFile=/tmp/gunicorn.pid
Environment=" PATH=/home/user1/falcon_app/venv/bin" 
WorkingDirectory=/home/user1/falcon_app
ExecStart=/home/user1/falcon_app/venv/bin/gunicorn --workers 3 -b localhost:5000 main:app
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

Save and quit the editor.

Start the new service with the following command.

(venv) root@linuxhelp1:~/falcon_app# systemctl start falcon_app

Enable the started service for longtime access.

(venv) root@linuxhelp1:~/falcon_app# systemctl enable falcon_app
Created symlink from /etc/systemd/system/multi-user.target.wants/falcon_app.service to /etc/systemd/system/falcon_app.service.

Once the above process is completed, open the web browser with respective IP address to check the output.

If you want to update the Falcon application, just run the following command.

(venv) root@linuxhelp1:~/falcon_app# systemctl restart falcon_app
Tag : Nginx Falcon
FAQ
Q
How does the Nginx process Gunicorn requests?
A
The Nginx processes the incoming requests before they reach Gunicorn.
Q
What is Falcon?
A
Falcon is a WSGI framework that used for building micro-services, application backends, and higher-level frameworks. It allows the users to create a production-ready environment by using Nginx as a reverse proxy server.
Q
Does Falcon support WebSocket?
A
Due to the limitations of WSGI, Falcon is unable to support the WebSocket protocol as stated above.In the meantime, you might try leveraging uWSGI’s native WebSocket support, or implementing
Q
Why doesn’t Falcon come with batteries included?
A
Falcon is designed for applications that require a high level of customization or performance tuning. The framework’s minimalist design frees the developer to select the best strategies and 3
Q
Why doesn’t Falcon create a new Resource instance for every request?
A
Falcon generally tries to minimize the number of objects that it instantiates. It does this for two reasons: first, to avoid the expense of creating the object, and second to reduce memory us