Setting up and deploying Python Flask to Dreamhost

I have a few applications I have written that run on Flask. Every time I would go to deploy a new application I would always seem to forget one of the minor details and end up with the ugly An error occurred importing your passenger_wsgi.py

The following are the steps I use to deploy Flask to Dreamhost using Passenger. I haven’t tested it, but this should be roughly the same steps if you want to deploy directly to your domain instead of using a subdomain.

TL;DR; (Quick Setup)

  • add a new subdomain on the dreamhost web panel
  • cd myappname.domain.com
  • git clone https://github.com/icecreammatt/flask-passenger.git .
  • virtualenv .
  • . bin/activate
  • easy_install flask
  • git submodule init
  • git submodule update
  • Replace myappname.domain.com in passenger_wsgi.py with your folder path.
  • touch tmp/restart.txt
  • DONE!

Part 1 - Setup Domain

  • Go to Manage Domains after logging into the Web Panel
  • Add New Domain / Sub-Domain
    • Domain to host: I like to use subdomains a lot of testing and the different Flask apps I run, so I tend to use myappname.domain.com Obviously swap out myappname.domain.com with your own names.
    • (Optional) Check remove WWW
    • If you have more than one user account make sure to pick the correct one.
    • Web directory should fill out automatically for you
    • Passenger (Ruby/Python apps only): Check this box
  • Fully host this domain!
  • SSH into your web server and wait a minute or two for the myappname.domain.com folder to appear
  • cd into myappname.domain.com

Part 2 - Install Flask with Passenger

1. Setup a virtualenv

First we need to setup the virtual environment
$ virtualenv .
$ ls
You should now have a directory that looks something like this:
bin     
include  
lib 
public
Next activate the virtual environment by using
$ . bin/activate
The command line should now show up something like this:
(myappname.domain.com)myappname.domain.com $

2. Install Flask

$ easy_install flask

3. Setup passenger

Create a file named passenger_wsgi.py with the following:

NOTE: Make sure to hand type this, as pasting the tabbed lines from the browser can translate to spaces which will evaluate incorrectly.

import sys, os
INTERP = os.path.join(os.environ['HOME'], 'myappname.domain.com', 'bin', 'python')
if sys.executable != INTERP:
    os.execl(INTERP, INTERP, *sys.argv)
sys.path.append(os.getcwd())

from flask import Flask application = Flask(__name__)

@application.route('/') def index(): return 'Hello Passenger'

NOTE: Don’t forget to change myappname.domain.com to match the setup you are using.

4. Start the server

Add a folder called tmp with a file named restart.txt
$ mkdir tmp
$ touch tmp/restart.txt
To restart the Flask application after making changes you need to update the restart.txt file. This can easily achieved by doing a touch tmp/restart. (For my projects I add a post-receive hook into my git repo to touch the file for me).

The directory should now look something like this:

bin  
include  
lib  
passenger_wsgi.py
public  
tmp

5. Test

At this point you should be able to hit the server address mynameapp.domain.com from the browser and see 'Hello passenger'

Part 3 - Deploying a real app

1. Clone sample project from github https://github.com/icecreammatt/flask-empty.git

$ pwd
/home/username/myappname.domain.com
$ git clone https://github.com/icecreammatt/flask-empty.git myappname

1. Adjust passenger_wsgi.py

Now that the basic stuff is in place a real application can be setup.

Edit passenger_wsgi.py so it now contains

import sys, os
INTERP = os.path.join(os.environ['HOME'], 'myappname.domain.com', 'bin', 'python')
if sys.executable != INTERP:
    os.execl(INTERP, INTERP, *sys.argv)
sys.path.append(os.getcwd())

sys.path.append('myappname')
from myappname.app import app as application

Note: Make sure if you copy this to tab os.excl… since it will copy as spaces and cause a runtime error.

Restart Flask

$ touch tmp/restart.txt

Other Resources:

I am by no means an expert at Python or Flask, I just like to code in it during my free time. Feel free to correct me on my style of code. Please post any questions or comments.
Author Avatar

Matt Carrier

I am a pixel connoisseur who enjoys the finer details of a Bresenham line. When not staring at arrays of smoothly rendered pixels I enjoy playing guitar and consuming coffee.