Deploying a Flask Project on WebFaction
I've been thoroughly enjoying my exodus from PHP to Python. My first self-assignment was to develop a Flask project, which came easily enough. The more difficult step was deploying it to WebFaction. The below guide are the steps I took to go from 0 - site, hopefully they'll come in useful.
Assumptions
This guide assumes a few things:
- You have a WebFaction account (you can get one here)
- Your Flask project is using a Virtual Environment (it should be)
- You've already set up your Virtual Environment on your Webfaction server
- You have SSH access to your WebFaction server (if not, get that going here)
Okay, let's get going.
Step 1: Add your site to Your WebFaction Account
I'm going to assume you're familiar with your WebFaction console, so this should be pretty simple:
- Log into your WF Console
- Go to your "Websites" tab, click the "Add New Website" button
- Enter the website name and domains as needed for your project
- Under the Contents section, choose Add an Application > Create a New Application
- Set App Category to "mod_wsgi"
- App Type should be the most recent version of mod_wsgi _that supports your Python version._ Make sure that your Python version matches with your mod_wsgi choice (I used "mod_wsgi 3.4/Python 2.7" for this guide).
- Click the Save button to add that application
- Click the Save button to save your website
Now your WebFaction account should have a new domain, website, and mod_wsgi application.
Step 2: SSH into your new application
First, you'll need to SSH into your webfaction account. Once you're there, cd
into your newly created application:
cd ~/webapps/application_name
In this directory, you'll see two folders:
- apache2/ # This contains all of your Apache config and action files
- htdocs/ # This is the folder Apache looks into (by default) to launch your project
All following instructions will assume you're still in this directory.
Step 3: Edit apache2/conf/httpd.conf
Using your favorite command line editor, open up the apache2/conf/httpd.conf file:
vim apache2/conf/httpd.conf
Load Alias module
You'll see a section where Apache Modules are being loaded. I had to manually add the Alias module to the bottom of the list (shown below).
LoadModule dir_module modules/mod_dir.so
LoadModule env_module modules/mod_env.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule wsgi_module modules/mod_wsgi.so
LoadModule alias_module modules/mod_alias.so # <-- What I added
Your version of mod_wsgi might not need to add this, but mine did.
Modify <Directory>
Add the following parameters to your <Directory> section:
<Directory /home/your_username/webapps/application_name/htdocs>
AddHandler wsgi-script .py
RewriteEngine On # <-- What I added
RewriteBase / # <-- What I added
WSGIScriptReloading On # <-- What I added
</Directory>
Now for the final edit of the config file.
Add Aliases
Finally, at the end of the file, add the following lines:
# This will ensure that www.yourdomain.com/static points to your flask static directory
Alias /static/ /home/your_username/webapps/application_name/app/main/static/
# This points to the file that launches our site, which we'll get to next
Alias / /home/your_username/webapps/application_name/htdocs/index.py/
Now to upload our files.
Step 4: Upload your Flask project
My prefered Flask structure matches the following format:
- My_Flask_Project
- fabfile.py
- project/
- config.py
- libs/
- main/
- static/
- templates/
- __init__.py
- views.py
- models.my
I upload my project/ folder to my application directory, and rename it to "app" - I don't really know why I feel the need to rename it, in retrospect:
scp -r ~/flask_files/project webfaction:~/webapps/application_name/app
Now, my ~/webapps/application_name directory list looks like the following:
- apache2/
- app/
- config.py
- libs/
- main/
- static/
- templates/
- __init__.py
- views.py
- models.my
- htdocs/
Next, we'll get our project's init file in order.
Step 5: Make sure your init.py file is right
Ensure that, whatever your structure, your project's __init__.py
file is launching your Flask application. In the struct I provided above, this is what my file at app/main/__init__.py
looks like:
from flask import Flask
# Setting up the App
app = Flask(__name__)
app.config.from_object('config')
# Importing the views for the rest of our site
from main import views
if __name__ == '__main__':
app.run()
This will work nicely with our htdocs/index.py file, which we'll set up next.
Step 6: Modify the htdocs/index.py file
WebFaction should have created this file. In it are a few scripts, but you can completely remove those. Here is what the htdocs/index.py
file should contain:
import sys
# Active your Virtual Environment, which I'm assuming you've already setup
activate_this='/home/username/.virtualenvs/venv_name/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))
# Appending our Flask project files
sys.path.append('/home/username/webapps/application_name/app')
# Launching our app
from main import app as application
And finally,
Step 7: Restart Apache
The last step will be to restart apache, like so:
apache2/bin/restart
Note: you call this script directly and do not need to source it
Troubleshooting
If you're having trouble, take a look at your logs in the ~/logs/users/
directory. Often my issues come from my Virtual Envs being misaligned.
Hope this guide helps. Please let me know if I missed an important step, or I'm way off on the process