How to Deploy a Flask Python App for Cheap.

Wat?

Yah, you heard me. This post is all about deploying your beautifully simple Flask App to your shared hosting account (e.g. GoDaddy, Funio); and it is a continuation of a previous post How to Deploy a Sinatra Ruby App to your Shared Hosting.

But Why? Haven't you heard of GoogleCloud, Bluemix, Heroku, Digital Ocean, RDCloud. Dude just use a Docker container at dotCloud, you make me sick with your foolery.

There are better ways to deploy your Flask application. And you should probably learn them as they are easier, more scalable, and overall better. However, great tools come with a price tag, and you might be already paying for a shared hosting account. So let's use that yo.

A word of caution though. Your shared hosting solution is probably the less efficient way to deploy an app. Often they are optimized for a PHP stack and provide Python apps through a limited (constrained workers) configuration of Passenger. Use this as a way to prototype your hobby apps, not for production.

Getting Started. Configuring CPANEL

Your shared hosting account probably uses CPANEL. Login and find a link to Install/Deploy a Python Application. If you don't see that, then Python is not installed/available in your plan. If you do see that link go ahead and click on it:

cpanel-python2

You should see a version of Python available in your plan. Configure the App Directory to point to where you want your code to live, in my case: public_html/exampleapppython. Configure the App URI where you want your app to be accessible, in my case "exampleapppython".

The image above shows the result of clicking "setup": it will create an application pointing to a python file (in my case myapp.py) that you can edit.

One important step left to do here is to add the Flask module, without it your application will crash and burn shamelessly. Search for "Flask" and add it.

Your app

If you started from scratch using CPANEL it would have created an app in the App Directory you specified with a similar structure:

/public
myapp.py
passenger_wsgi.py
.htaccess

If you pointed your App Directory to an existing application the CPANEL script will only add a passenger_wsgi.py file and a .htaccess file.

The "public" directory is used for assets, the "myapp.py" file is your application entry point, "passenger_wsgi.py" is a script telling passenger how to interpret your application and what file to use to serve requests, your ".htaccess" file tells Apache the App URI, App Directory, and Python Version (location) you configured in CPANEL.

The Flask APP

The Flask application is really simple, but I have added a magic line that makes this Flask deal work (application = app). The passenger_wsgi script will look for your application code in a variable called "application" not "app" as used by Flask when you developed it.

from flask import Flask
app = Flask(__name__)
application = app # our hosting requires application in passenger_wsgi

@app.route("/")
def hello():
    return "This is Hello World!\n"

if __name__ == "__main__":
    app.run()

The Passenger WSGI file

This file created by CPANEL is also quite simple, it will load the "myapp.py" source and pass it to Passenger in the "application" object. Yes, I hear you: "Why didn't I just use "app" here instead of creating a redundant "application" object in myapp.py?". Because one day, when drunk, you'll run that CPANEL script again, which will overwrite this file and you'll pull your hair bald trying to figure out why you keep getting the error "application doesn't exist".

import imp
import os
import sys

sys.path.insert(0, os.path.dirname(__file__))

wsgi = imp.load_source('wsgi', 'myapp.py')
application = wsgi.application

The htaccess file

Finally, the file that tells Apache that this is a Python application, where it lives and where Python can be found.

.htaccess:

PassengerAppRoot "/home/roberto/public_html/exampleapppython"
PassengerBaseURI "/exampleapppython"
PassengerPython "/home/roberto/virtualenv/public__html_exampleapppython/2.7/bin/python2.7"

Recap

Login to CPANEL, find the link "Deploy Python Application", configure your URI and APP location, click on "setup", install the "Flask" module. This will create a base application. Create your Flask application and bind it to "application". You're done.

  • Amroo

    https://uploads.disquscdn.com/images/36af73b140c557168c1e1339eca195a19b985d315fd1a0d694251a052933c7c3.png

    I follow this steps but still have error : ‘PassengerAppRoot’, perhaps misspelled or defined by a module not included in the server configuration

    • http://calderonroberto.com Roberto Calderon

      This occurs because Apache hasn’t loaded the passenger module. It generally gets loaded like this: `LoadModule passenger_module /path/to/…/passenger/buildout/apache2/mod_passenger.so` but you might not have access to the apache configuration. One step that is important is to be able to add the flask module. Which will make sure that the passenger module is installed: To quote myself:

      `One important step left to do here is to add the Flask module, without it your application will crash and burn shamelessly. Search for “Flask” and add it.`

      Make sure this is done.

  • Dio Ilham

    i follow all the steps, but why my page didnt opened, that gives me 500 RTO error. i still not change anything at all, this is the default setting to show the “it works blablabla”, but it didnt showed up because that RTO. can you explain why?

  • Adrian Butterworth

    That was useful! A higher level overview AND the technical details to get it working. To make it even better, you could add explanation as to Why GCP, Heroku or AWS is better? As I’m starting off with the CPanel and hosting with a hosting service (FastComet), and don’t really know the powers of the cloud.