Post

Creating a Webservice with Phusion

This setup process is an amalgamation of best practices when it comes to setting up, deploying, releasing, and developing a large web application on most shared hosting platforms. As most of the shared hosting platforms are strictly user premitted and don’t allow you to install necessary dependencies that would usually install globally or require sudo permissions to install.

Creating the Application

For example purposes, you can use the following “Hello World” demo that uses Flask.

1
2
git clone https://github.com/phusion/passenger-python-flask-demo.git
cd passenger-python-flask-demo/

Many of the Python web frameworks already have a builtin web server which is activated by simply running the application itself and for this example we run do that as such using.

1
python3 app.py

If you run into issues running that, you may need to install the python Flask package.

1
python3 -m pip install Flask

or

1
pip3 install Flask

Now once you are running the sample Flask web application, you should be able to view it from your browser at https://SERVER_PUBLIC_IP:5000/ with no issue.

There’s a chance you may run into one of the following issues when trying to connection:

Issue 1:

1
The connection has timed out

This is usually means your firewall rules or security groups are improperly configured to allow for inbound traffic on port 5000

Issue 2:

1
Unable to connect

Usually happen when trying to connect from another device not on the same IP address. As 127.0.0.1 means localhost/loopback and means you can only be connected to it through itself, so you will need to change the last line in the app.py from MyApp.run() to MyApp.run(host='0.0.0.0') and then you should be able to connect from another computer.

Phusion Passenger Setup

What is Passenger?

Passenger can be used to serve up Ruby on Rails and Python web applications that use the WSGI interface, including any application which uses the Django framework.

Django is a web development framework for Python in the same way Rails is a framework for Ruby. It is used by a number of major web sites, including Google (i.e., for the Google Application Engine), which can make developing rich web applications much easier.

Django is not an application on its own. You will need proficiency in Python programming in order to write an application using Django.

Passenger allows your application to temporarily reside in memory while it is being actively used. This makes it possible for your site to respond significantly faster than is otherwise possible.

Installing Passenger

Info: If you are using a web hosting provider like Dreamhost, Hostgator, etc then you can just enable to allow for your website to run your own application which will typically uses Passenger, so you can skip this step.

The corresponding installation steps were implemented for use on CentOS, so you may have to lookup the appropriate commands for your OS of choice.

Enable EPEL

This installation walkthrough is intended for CentOS, so you will have to lookup the appropriate commands for your OS flavor.

1
2
3
$ sudo yum install -y epel-release yum-utils
$ sudo yum-config-manager --enable epel
$ sudo yum clean all && sudo yum update -y
Repairing Potential Issues

Ensure curl and nss/openssl are sufficiently up-to-date to ensure we can communicate with the repository before running the following.

1
2
$ sudo yum update -y
$ sudo yum install curl

Verify your system date is correct using the date command.

1
$ date

If the output is incorrect, then we can use ntp to synchronize your system clock.

1
2
3
4
$ sudo yum install -y ntp
$ sudo chkconfig ntpd on
$ sudo ntpdate pool.ntp.org
$ sudo service ntpd start
Installing Passenger with EPEL

Install necessary prerequisites for Passenger.

1
sudo yum install pygpgme

Now we can actually install Passenger itself.

1
sudo yum install -y --enablerepo=epel passenger

If the above fails, saying that the package is missing or does not exist, you can use the following to add the el7 repository to your yum source lists.

Thusly, paste the following and then rerun the above yum install again.

1
sudo curl --fail -sSLo /etc/yum.repos.d/passenger.repo https://oss-binaries.phusionpassenger.com/yum/definitions/el-passenger.repo

Now install Passenger Nginx.

1
sudo yum install -y nginx passenger || sudo yum-config-manager --enable cr && sudo yum install -y nginx passenger

Validate the installation was successful.

1
2
3
$ passenger-config validate-install
 * Checking whether this Phusion Passenger install is in PATH... ✓
 * Checking whether there are no other Phusion Passenger installations... ✓
Configuring Nginx and Passenger

Now it’s time to configure Nginx so that Passenger knows how to serve your app.

To do that we need to create an Nginx configuration file and setup a host entry that points toward your application and this will allow for us to both tell Nginx and Passenger where your application is.

So let’s just create the basic config for just this application.

1
sudo nano /etc/nginx/conf.d/nginx.conf

It’s okay if the file does not exist as you can replace or paste the following -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# /etc/nginx/conf.d/nginx.conf
server {
    listen 80;
    server_name yourserver.com;

    # Tell Nginx and Passenger where your app's 'public' directory is
    root /var/www/myapp/code/public;

    # Tell Passenger that your app is a Python app
    passenger_app_type wsgi;
    passenger_startup_file passenger_wsgi.py;

    # Turn on Passenger
    passenger_enabled on;
    passenger_python /path/to/python;
}

For the above you need to replace a few properties as follows -

  • Replace yourserver.com with your server’s host name.
  • Replace passenger_wsgi.py with your app’s WSGI entry point file.
  • Replace /var/www/myapp/code with your application’s code directory path. However, make sure that nginx is configured to point to the public subdirectory inside it!
  • Replace /path/to/python with the location of the Python binaries for the version which the application is built, this is most likely to be the folder containing the virtual environment.

Once finished, we can now restart Nginx:

1
sudo service nginx restart

Your web application should now be running and reachable from your servers hostname. You can quickly verify by running this following command, replacing yourserver.com with your server’s hostname, exactly as it appears in the Nginx config file’s server_name directive

1
curl "https://yourserver.com:5000/"

Configuring Passenger with Flask Applications

The following example is a continuation from the above Creating the Application.

So to be able to use Passenger with Flask, it doesn’t have the ability to run it like one typically would by just calling from the command line python3 app.py and it just run. Instead Passenger does it a little differently by using something called Python WSGI, which defines a standard interface for web applications allowing any application that implements WSGI to work with any server that supports it.

This method of using WSGI is actually used on nearly every modern day Python web application implements the use of WSGI like Flask, Django, etc. In fact, majority of frameworks in general use WSGI like Apache, Ruby, NodeJS, and so on.

With that aside, for use to allow for Passenger to run our application, we must create a passenger_wsgi.py file.

Creating a Passenger WSGI File

Firstly, when trying to run Passenger it just off the bat assumes that the directory you are calling it from contains that passenger_wsgi.py file.

So your example project files will look something like the below.

1
2
3
4
5
+-- passenger-python-flask-demo/
    +-- templates/
    |   +-- index.html
    +-- app.py
    +-- passenger_wsgi.py <

Paste the below contents to the passenger_wsgi.py.

The contents of your passenger_wsgi.py file will change depending on your application and the projects web framework, but for this example we’re using a simple Flask app.

1
2
# passenger_wsgi.py
from app import MyApp as application

Running the Server

1
2
3
4
5
6
7
8
9
passenger start
# => ======= Phusion Passenger Standalone web server started =======
# => PID file: /Users/phusion/myapp/passenger.3000.pid
# => Log file: /Users/phusion/myapp/passenger.3000.log
# => Environment: development
# => Accessible via: https://0.0.0.0:3000/
# =>
# => You can stop Phusion Passenger Standalone by pressing Ctrl-C.
# => ===============================================================

As you can see in the output, Passenger is now serving your app on https://0.0.0.0:3000/. You can now visit that URL in your browser to see your app in action.

This post is licensed under CC BY 4.0 by the author.