Deploying a Pyramid App on AppFog

August 28, 2012

Last July, AppFog revealed it's official plans, which include a free plan that comes with 2GB of RAM. I then decided to give it a try and move a Pyramid app that I had running on a VPS for about a year. The app uses Python 2.7, PostgreSQL, Pyramid 1.3.2 and SQLAlchemy 0.7.8.

On the VPS, the app was running using Waitress behind nginx.

I had to make some minor modifications to the code to make it run on AppFog, which were not really documented anywhere. I decided to post it here, in the hope someone finds it when needed.

Configuration File

First of all, I created a new configuration file. I named it appfog.ini, but name it whatever you like. I removed the key sqlalchemy.url, since it is set in environment variables by AppFog. Also, for the app to know that it has to retreive the environment variables instead of using sqlalchemy.url, I added the key/value appfog = true.

SQLAlchemy Connection

In main function of __init__.py, I replaced the line where the engine is created from the configuration file to take into account that the connection information could come from environment variables. So I replaced:

engine = engine_from_config(settings, 'sqlalchemy.')

with:

if settings.get('appfog') == 'true':
engine = appfog_engine(settings)
else:
from sqlalchemy import engine_from_config
engine = engine_from_config(settings, 'sqlalchemy.')

And I defined appfog_engine later in the same file:

def appfog_engine(settings):
from sqlalchemy import create_engine
import os, json
all_config = json.loads(os.getenv("VCAP_SERVICES"))
config = all_config['postgresql-9.1'][0]['credentials']
connection_string = ('postgresql+psycopg2://%(username)s:%(password)s'
'@%(host)s:%(port)d/%(name)s')
engine = create_engine(connection_string % config)
return engine

Requirements

Like when you deploy on Heroku, you have to provide a requirements.txt file, that you generate by running:

$ pip freeze > requirements.txt

WSGI App

You then have to create a wsgi.py file that you place at the root of your project, beside setup.py and appfog.ini. In wsgi.py, you put:

import os
from paste.deploy import loadapp

os.system("python setup.py develop")
path = os.getcwd()
application = loadapp('config:appfog.ini', relative_to=path)

That's It

Your app is ready to upload using the regular instructions, using the af commmand line tool provided by AppFog.

Useful Stuff

Since my app was already in production for about a year, I had data in my PostgreSQL database that I had to migrate from my server to AppFog. One nice feature they provide is the ability to make a tunnel to your services. You can find the doc here. With the help of the tunnel, it was easy to use pg_dump and psql to migrate the database.