Alex Raichev

Deploying a Flask Application on Webfaction

A few months ago i had to deploy for the first time a Flask application on a Webfaction server. After studying this Webfaciton Community thread on the topic, issuing a Webfaction support ticket for help ---Webfaction customer service is excellent--- and trying and failing several times, i figured it out. Here's what i did.

Suppose that your Flask project structure looks like this:

APPNAME
├── APPNAME
│   ├── main.py
│   ...
│   └── wsgi.py
...
├── Pipfile
├── Pipfile.lock
└── README.rst

that you are tracking it with Git, that you run it locally in a Python virtual environment, e.g. using Pipenv, and that it works. Now, let's deploy it to Webfaction.

  1. Log in to your Webfaction control panel and create a new mod_wsgi/Python application. Also create a corresponding domain and website for the app. I assume you know how to do that.

  2. Throughout the remainder of these notes, suppose that your Webfaction username is USERNAME and that your Flask application is called APPNAME

  3. SSH into your Webfaction server and run these commands:

    > mkdir home/USERNAME/webapps/APPNAME/APPNAME
    > rm -r home/USERNAME/webapps/APPNAME/htdocs
    > rm -r home/USERNAME/webapps/APPNAME/lib
    

    You don't need the lib directory in the last line, because you will be using a virtual environment.

  4. Set up Git, Git hooks, and push your local repository to Webfaction. See the Webfaction instructions here and here.

  5. Create your virtual environment ---let's call it VENVNAME here--- and install your app requirements. I think the easiest way to do this is to install Pip to install Pipenv to manage your virtual environments and packages.

  6. If your local repo has a .env environment file containing (Git-ignored) secrets, then create a corresponding .env file in your Webfaction repo.

  7. If you haven't done so already, create the file home/USERNAME/webapps/APPNAME/APPNAME/wsgi.py containing the single line from main import server as application.

    This assumes that your Flask code lies in the module main.py and that the Flask app you create in that module is call server. If that's not the case, then change the above snippet as needed.

  8. Edit the file home/USERNAME/webapps/APPNAME/apache2/conf/httpd.conf to the following, where PORT is the port number that Webfaction assigned to your application (which you can view in your Webfaction control panel for the app):

    ServerRoot "/home/USERNAME/webapps/APPNAME/apache2"
    
    LoadModule authz_core_module modules/mod_authz_core.so
    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 unixd_module      modules/mod_unixd.so
    
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    CustomLog /home/USERNAME/logs/user/access_APPNAME.log combined
    ErrorLog /home/USERNAME/logs/user/error_APPNAME.log
    
    Listen PORT
    KeepAlive Off
    SetEnvIf X-Forwarded-SSL on HTTPS=1
    ServerLimit 1
    StartServers 1
    MaxRequestWorkers 5
    MinSpareThreads 1
    MaxSpareThreads 3
    ThreadsPerChild 5
    
    WSGIPythonHome /home/USERNAME/.virtualenvs/VENVNAME
    WSGIDaemonProcess APPNAME processes=2 threads=12 python-path=/home/USERNAME/webapps/APPNAME/APPNAME:/home/USERNAME/webapps/APPNAME/APPNAME/APPNAME
    WSGIScriptAlias / /home/USERNAME/webapps/APPNAME/APPNAME/APPNAME/wsgi.py
    WSGIProcessGroup APPNAME
    WSGIRestrictEmbedded On
    WSGILazyInitialization On
    
  9. Restart your app via home/USERNAME/webapps/APPNAME/apache2/bin/restart.

These instructions will probably go obsolete in a few months, as all things web related do. Still, they'll help me while they last and maybe help you too.

Author: Alex Raichev
Date: 2018-05-17
Tags: instructions, tech
Comment