Bloghttp://appsembler.com/blog/feeds/rss/Musings and stories from a startupenMediathreadDjangoOpen SourceEventsInterviewsMezzanineLearning CenterPaaSTue, 10 Sep 2013 19:03:27 +0000Mediathread for the rest of ushttp://appsembler.com/blog/mediathread-for-the-rest-of-us/<div>Mediathread is a next generation media analysis tool that lets students create compositions embedded with rich media (video, images, audio). What's really cool about Mediathread is that the videos can come from anywhere (Youtube, Vimeo, Library of Congress, etc) and annotated by "clipping" different segments of the video. These clips are then used to support an argument in an essay.</div>
<div> </div>
<div>Similarly, images can be pulled into Mediathread from a variety of sources (Museum of Modern Art, Flickr, Google Art Project, etc.) and annotated by "drawing" on the image itself. These drawings become annotations that can be used to demonstrate the student's understanding of the material: a particular technique that a painter used, or the historical significance of an object in the painting.</div>
<div> </div>
<div>Mediathread is being used by dozens of professors at Yale, Dartmouth, Columbia, Georgia Tech and MIT to get their students to engage more critically with the materials they're studying.</div>
<h3>Where to find support and hosting?</h3>
<div>One thing that I've observed is that while Mediathread has attracted a large number of people interested in using it, the number of people who actually get to use it for their class is much smaller.</div>
<div> </div>
<div>Professors want to use it, but their IT department is overworked and will only support software tools that they are already familiar with.</div>
<div> </div>
<div>Once installed, the Mediathread software is quite easy to use, but getting the software installed in the first place is not trivial. It requires someone with expertise in setting up a server, installing, configuring and maintaining the software.</div>
<h3>Now anyone can create a Mediathread course</h3>
<div>Well, we have such expertise and we wanted to make this problem go away. We believe that any professor who wants to use Mediathread should be able to do so, without having to beg their IT department to try setting it up for them.</div>
<div> </div>
<div>And so I'm super excited to announce the availability of our Mediathread hosting service! </div>
<div>Check it out at <a href="http://getmediathread.com/" target="_blank">http://getmediathread.com</a></div>
<div> </div>
<div>For the first time ever, professors can start using Mediathread within a matter of minutes. No software to install, no servers to procure, no need to beg the IT guy/gal. </div>
<div> </div>
<div>We offer a hassle-free hosted Mediathread service that includes expert support, regular software updates and professional hosting.</div>
<div> </div>
<div>The advantages of our service over doing it yourself are:</div>
<div> </div>
<div><strong>1) Hassle-free hosting</strong></div>
<div>We do all the nitty gritty server stuff so you don't have to. We've managed high traffic sites for Harvard University, Oxfam America and the Smithsonian so we know what we're doing. We keep the software up-to-date and take care of security patches and other bug fixes. Daily backups and 24/7 monitoring - we've got you covered.</div>
<div> </div>
<div><strong>2) Prompt and professional support</strong></div>
<div>We provide prompt and professional support by email, chat and phone. We're expert Django developers and can dig deep into the codebase if necessary to troubleshoot and debug problems that arise.</div>
<div> </div>
<div><strong>3) Self-registration and faculty/student roster</strong></div>
<div>We made it easier for you to delegate administrative tasks by allowing professors to self-register, create courses and invite students. We've also added a class roster page where professors can promote a user to the faculty role and add/remove students from a course. </div>
<div> </div>
<div><strong>4) Customizations and new feature development</strong></div>
<div>We can make customizations that your professors have been asking for. And we're constantly adding new features. Some new features that are being considered include video/audio uploading, single-signon and iPad support.</div>
<div> </div>
<div>This is the first of many blog posts about not only Mediathread, the software, but the process of turning an open source software package into a commercially available SaaS product. We've learned a lot of lessons along the way, and we're very excited to share those with you! </div>
<div> </div>
<div>As always, we welcome your feedback either in the comments of this blog post, or in our special <a href="http://support.appsembler.com/knowledgebase/topics/39118-mediathread">Mediathread knowledgebase and support forum</a>.</div>Nate AuneTue, 10 Sep 2013 19:03:27 +0000http://appsembler.com/blog/mediathread-for-the-rest-of-us/MediathreadDjangoOpen SourceOpen source and open cloudshttp://appsembler.com/blog/open-source-and-open-clouds/<p>I was invited to speak at an event sponsored by EMC called <a href="http://www.eventbrite.com/event/6434679299">Technology Directions: Keeping it Real. Open Source Software- What's the Buzz All About?</a> which was hosted by MassChallenge on May 23, 2013.</p>
<p>I used <a href="http://www.telestream.net/screenflow/">Screenflow Pro</a> to record my presentation and audio from my computer.</p>
<p><iframe height="480" src="http://www.youtube.com/embed/jpepZIVxS-Y" width="640"></iframe></p>
<p>I split the talk into 3 parts: </p>
<ul>
<li>about me and my company Appsembler</li>
<li>what is open source and why is it important</li>
<li>what is the open cloud and where are we heading</li>
</ul>
<p>I didn't know whether the audience would already be familiar with open source, so I used a couple analogies to illustrate what makes open source software different from proprietary commercial software.</p>
<ul>
<li>Giving cookies to someone versus giving them the cookie and the recipe for how to make it.</li>
<li>Buying a car in which the hood is welded shut (yes, <a href="http://news.bbc.co.uk/2/hi/business/3528757.stm">Volvo actually made such a car</a>!)</li>
</ul>
<p><br>For the open cloud part of my talk, I told a story about the shipping industry in the Bay Area and about how Oakland embraced the "containerization" of shipping, whereas San Francisco was too much invested in the old way and didn't adapt.</p>
<p>Within a few years, Oakland had surpassed San Francisco as the leading shipping port on the West Coast. This story fed nicely into the analogy of containerization of shipping that Dotcloud so eloquently describes in the <a href="http://docs.docker.io/">Docker documentation</a>. </p>
<p>I knew there was going to be someone from EMC and Rackspace talking after me after OpenStack, so I focused on PaaS providers and the emerging open source ones like Redhat's OpenShift and VMWare's CloudFoundry.</p>
<p>I finish the talk by highlighting some trends around increased adoption of open technologies.</p>
<p>Take a look and send me your feedback in the comments below!</p>Nate AuneSun, 02 Jun 2013 01:12:21 +0000http://appsembler.com/blog/open-source-and-open-clouds/Open SourcePaaSDeploy Django apps to Dotcloud with django-deployer in 5 minuteshttp://appsembler.com/blog/deploy-django-apps-to-dotcloud-with-django-deployer-in-5-minutes/<p>Yesterday I posted a video demonstrating how to <a href="/blog/deploy-django-apps-to-google-app-engine-with-django-deployer-in-5-minutes/">deploy a Django project to Google App Engine</a> using <a href="http://natea.github.io/django-deployer/">django-deployer</a>.</p>
<p>Today I'm going to demonstrate how to deploy <a href="https://github.com/appsembler/paasbakeoff/">the same project</a> (Mezzanine, a blogging/CMS platform) to <a href="http://dotcloud.com">Dotcloud</a>, another platform-as-a-service (PaaS). Watch this short 4.5 min video to see how it works:</p>
<p><iframe height="368" src="http://ascii.io/a/2800/raw" width="567"></iframe></p>
<h2>How does it work?</h2>
<p>What did we just see in the video?</p>
<ol>
<li>After cloning the skeleton <a href="https://github.com/appsembler/paasbakeoff/">paasbakeoff</a> project with <strong>git clone https://github.com/appsembler/paasbakeoff/</strong></li>
<li>We install django-deployer into our virtualenv with <strong>pip install django-deployer</strong></li>
<li>We ran a command <strong>deployer-init</strong>, that simply copies a 'fabfile.py' into our project's directory.</li>
<li>Then we run <strong>fab setup</strong> which asks us a bunch of questions about our project. Based on the answers, django-deployer creates all the necessary configuration files to deploy our project to Dotcloud.</li>
<li>Once the project is prepped, then we run the <strong>dotcloud create myapp</strong> command to create the app.</li>
<li>Lastly, we deploy the app to Dotcloud with the command <strong>dotcloud push</strong>.</li>
</ol>
<p>That's it! In less than 5 minutes, we've taken a Django project that knows nothing about Dotcloud, made it Dotcloud-ready, and got it running up on Dotcloud!</p>
<h2>What files get created?</h2>
<h3>deploy.yml </h3>
<p>Stores all the answers to the questions after running fab setup. (<em>Note: this file is not needed for Dotcloud and can be deleted after running 'fab setup')</em></p>
<pre class="brush: yaml; gutter: false;">admin_password: admin2
database: PostgreSQL
django_settings: mywebsite.settings
managepy: mywebsite/manage.py
media_url: /media/
project_name: mywebsite
provider: dotcloud
pyversion: Python2.7
requirements: mywebsite/requirements/project.txt
static_url: /static/
</pre>
<p><em>Note:</em> this file is likely to change in the future. Refer to the <a href="https://github.com/natea/django-deployer">django-deployer</a> code for the latest specifications.</p>
<h3>dotcloud.yml </h3>
<p>dotcloud.yml is the configuration file which tells Dotcloud that we're deploying a Python 2.7 application and want PostgreSQL as the database. It also sets some environment variables like the DJANGO_SETTINGS_MODULE and UTF-8 encoding on the file system.</p>
<pre class="brush: yaml; gutter: false;">www:
type: python
config:
python_version: v2.7
environment:
DJANGO_SETTINGS_MODULE: mywebsite.settings_dotcloud
LANG: en_US.UTF-8
LC_ALL: en_US.UTF-8
db:
type: postgresql
</pre>
<h3><strong>createdb.py</strong> </h3>
<p>This script doesn't what you would expect, creates the database on Dotcloud. <em>Not printed here because it's very long, but if you want to see what it looks like you can see an example <a href="https://github.com/appsembler/paasbakeoff/blob/dotcloud/createdb.py">here</a></em>.</p>
<h3>mkadmin.py </h3>
<p>This is a small script which simply creates a superuser so we can login to the Django admin.</p>
<pre class="brush: python; gutter: false;">#!/usr/bin/env python
from wsgi import *
from django.contrib.auth.models import User
u, created = User.objects.get_or_create(username='admin')
if created:
u.set_password('secret')
u.is_superuser = True
u.is_staff = True
u.save()
</pre>
<h3>mywebsite/settings_dotcloud.py </h3>
<p>This is a special settings file that sets up the <strong>DATABASES</strong> declaration to use the database that Dotcloud provides. It also configures the <strong>STATIC_ROOT</strong> and <strong>MEDIA_ROOT</strong> to put static assets and uploaded media in special directories that Dotcloud provides.</p>
<p>You'll see that <strong>wsgi.py</strong> references <strong>settings_dotcloud</strong> instead of the usual settings and we also set it as an environment variable in <strong>dotcloud.yml</strong>, so that the manage.py script knows about it too.</p>
<pre class="brush: python; gutter: false;">import json
with open('/home/dotcloud/environment.json') as f:
env = json.load(f)
from .settings import *
STATIC_ROOT = '/home/dotcloud/volatile/static/'
STATIC_URL = '/static/'
MEDIA_ROOT = '/home/dotcloud/data/media/'
MEDIA_URL = '/media/'
if 'DOTCLOUD_DATA_MYSQL_HOST' in env:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': env['DOTCLOUD_PROJECT'],
'USER': env['DOTCLOUD_DATA_MYSQL_LOGIN'],
'PASSWORD': env['DOTCLOUD_DATA_MYSQL_PASSWORD'],
'HOST': env['DOTCLOUD_DATA_MYSQL_HOST'],
'PORT': int(env['DOTCLOUD_DATA_MYSQL_PORT']),
}
}
elif 'DOTCLOUD_DB_SQL_HOST' in env:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': env['DOTCLOUD_PROJECT'],
'USER': env['DOTCLOUD_DB_SQL_LOGIN'],
'PASSWORD': env['DOTCLOUD_DB_SQL_PASSWORD'],
'HOST': env['DOTCLOUD_DB_SQL_HOST'],
'PORT': int(env['DOTCLOUD_DB_SQL_PORT']),
}
}
</pre>
<h3>nginx.conf </h3>
<p>In this file we set up the static mappings for our static and media URLs:</p>
<pre class="brush: text; gutter: false;">location /media/ { root /home/dotcloud/data ; }
location /static/ { root /home/dotcloud/volatile ; }
</pre>
<h3>postinstall </h3>
<p>postinstall is a bash script that gets run after the build is finished. Here is where we create the database (with createdb.py), sync the database, create the superuser (with mkadmin.py) and collect the static assets (optionally we could run the manage.py migrate command if we were using South)</p>
<pre class="brush: bash; gutter: false;">#!/bin/sh
python createdb.py
python mywebsite/manage.py syncdb --noinput
python mkadmin.py
mkdir -p /home/dotcloud/data/media /home/dotcloud/volatile/static
python mywebsite/manage.py collectstatic --noinput
</pre>
<h3>requirements.txt</h3>
<p>Dotcloud expects there to be a file named requirements.txt in the root of the project directory. Since Mezzanine already provides one, we'll just make requirements.txt point to that one:</p>
<pre class="brush: text; gutter: false;">-r mywebsite/requirements/project.txt
</pre>
<h3>wsgi.py</h3>
<p><strong></strong>Lastly, we need to tell Dotcloud how to serve our Django app with a wsgi handler:</p>
<pre class="brush: python; gutter: false;">import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),'mywebsite')))
os.environ['DJANGO_SETTINGS_MODULE'] = 'mywebsite.settings_dotcloud'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>Notice that we had to add 'mywebsite' to the Python path with sys.path.insert.</p>
<h2>What makes Dotcloud different?</h2>
<h3>No more free lunch</h3>
<p>Almost all of the PaaS providers have a free tier, undoubtedly to gain developer mindshare. But as of April 25, 2013, Dotcloud is discontinuing their free "sandbox" tier and it will only be available as a paid service. There is a silverlining in <a href="http://blog.dotcloud.com/new-sandbox">this announcement</a> in that Dotcloud will be open sourcing a good chunk of their technology such as Docker and Hipache, core components of their hosted service.</p>
<p>Kudos to Dotcloud for giving away their code so we can learn from it. Although I would argue that the reason people are attracted to PaaS in the first place is because they want to let someone else take care of the servers for them. It will be interesting to see what interesting things people come up with using <a href="http://docker.io">Docker</a>, a runtime for Linux containers (LXC). See Solomon Hyke's lightning talk from PyCon 2013 about <a href="http://youtu.be/9xciauwbsuo">The Future of Linux Containers</a>.</p>
<h3>System packages</h3>
<p>Dotcloud lets you install system packages. Anything that's available in the public Ubuntu apt repositories should be available to install in your application container. Simply add 'systempackages' to your dotcloud.yml file and define which ones to install. For example, in order to save time installing PIL or lxml, you can just use the pre-compiled packages provided by Ubuntu:</p>
<pre class="brush: yaml; gutter: false;">www:
type: python
systempackages:
- python-imaging
- python-lxml
</pre>
<h3>Configurable nginx.conf</h3>
<p>Dotcloud lets you set up <a href="http://docs.dotcloud.com/guides/nginx/">your own Nginx config file</a>. You can go to town with mappings and rewrite rules.</p>
<h3>SSH just like you can with a VPS</h3>
<p>And as with OpenShift, Heroku, Stackato and Elastic Beanstalk, you can SSH into your application container using this command:</p>
<pre class="brush: bash; gutter: false;">$ dotcloud run www
</pre>
<h2>What's next?</h2>
<p>The django-deployer project is still a work-in-progress and there are many other things I'd like to add to it, such as auto-detection of your settings.py, manage.py and requirements.txt files (less typing), and handling configuration for other services like Celery, Redis, Memcached and email sending. What would you like to see?</p>
<p>The code is open source and available on Github if you want to <a href="https://github.com/natea/django-deployer">check it out</a>. Contributions welcome! Feel free to report any bugs or feature requests to <a href="https://github.com/natea/django-deployer/issues">the Github issue tracker</a>, or just add a comment below.</p>Nate AuneThu, 11 Apr 2013 01:19:02 +0000http://appsembler.com/blog/deploy-django-apps-to-dotcloud-with-django-deployer-in-5-minutes/DjangoMezzaninePaaSDeploy Django apps to Google App Engine with django-deployer in 5 minuteshttp://appsembler.com/blog/deploy-django-apps-to-google-app-engine-with-django-deployer-in-5-minutes/<p>Yesterday I announced the <a href="/blog/journey-through-time-and-paas-introducing-django-deployer/">alpha release of django-deployer</a>, and today I'd like to show how to use it for deploying a Django app to Google App Engine (GAE).</p>
<p>Here is a 5 min demonstration video showing how it works. <em>(The video is best viewed in Chrome or Safari - there is currently a bug in the player when used with Firefox)</em></p>
<p><iframe height="496" src="http://ascii.io/a/2745/raw" width="675"></iframe></p>
<p> </p>
<h2>What makes Google App Engine different?</h2>
<p>GAE is a bit different than the other PaaS providers in the following ways:</p>
<p>1. You cannot run pip install -r requirements.txt on the server, so you have to run it locally and then push up all the packages to GAE. Thankfully, there is a script provided by django-deployer that takes care of this for you.</p>
<p>2. GAE already provides Django 1.4, PIL and <a href="https://developers.google.com/appengine/docs/python/tools/libraries27">a bunch of other packages</a>, so you should use the versions that GAE provides, rather than pushing up your own. django-deployer prepares and uploads the packages that are in your project that are not already provided by GAE. (Note: any unsupported package that requires C extensions is not going to work on GAE, since you can't compile code on the server)</p>
<p>3. GAE provides a MySQL-compatible service called <a href="https://developers.google.com/appengine/docs/python/cloud-sql/django">Cloud SQL</a>. You need to <a href="https://developers.google.com/cloud-sql/docs/before_you_begin#request_a_sql_service_instance">create a new Cloud SQL instance</a> and grant your GAE app as an authorized application. Once you've created an instance, it can contain unlimited databases up to the disk allowance (on the free tier, this is 512MB). The script provided by django-deployer will prompt you for the instance name, and then proceed to create the database for you using google_sql.py (provided by the GAE Python SDK).</p>
<p>4. Any Django management commands (syncdb, migrate) have to be run locally against the remote Cloud SQL database. Similarly, collectstatic also has to be run locally and then push the resulting 'static' dir up to the server. Again, django-deployer provides a wrapper script called manage.sh, that can handle these tasks for you.</p>
<h2>How do I get started with Django on GAE?</h2>
<p>You just head on over to <a href="http://appengine.google.com">sign up for an App Engine account</a> using any Google account. Once you're logged in, create a new app by clicking on <strong>Create application</strong>. We're going to call our application "<strong>djangodeployermezz</strong>":</p>
<p><img alt="Create a Google App Engine project" height="606" src="/site_media/media/uploads/create_appengine_project.png" title="Create a Google App Engine project" width="623"></p>
<h2>Turn on Cloud SQL</h2>
<p>Then you need to go over to the <a href="https://code.google.com/apis/console/">Google APIs console</a>, which is a bit confusing because it's a totally different interface than the App Engine UI. Hopefully in the future, Google will provide a more seamless unified experience when using their PaaS.</p>
<p>You'll want to click on the <strong>Services</strong> menu item and <strong>turn on Cloud SQL</strong>.</p>
<p><img alt="" height="44" src="/site_media/media/uploads/enabled_cloudsql.png" width="561"></p>
<p>Click on the <a href="http://developers.google.com/cloud-sql/docs/billing">pricing link</a> to see how much a Cloud SQL instance costs. Google is offering an introductory Cloud SQL trial instance (tier D0). You still need to <strong>enable billing</strong> for your project, but Google will not charge you for resources consumed by your tier D0 Cloud SQL instances.</p>
<p>You are allowed only one tier D0 Google Cloud SQL instance in total, no matter how many Google APIs projects you have. If your tier D0 instance reaches the storage limit, you will not be able to add more data to your database, but you will be able to access your instance to delete data. You can track the amount of storage used in the APIs Console. If you require more storage or RAM, you can change your trial instance to one of the paid tiers at any point through the console. </p>
<h2>Create a new database instance</h2>
<p>Once you've turned on Cloud SQL and enabled billing, then you need to create a new instance by clicking on the <strong>New Instance...</strong> button. We're going to make a new instance called "<strong>djangomezzanine:djangomezzdb</strong>". Note: be sure to add your application as an authorized application to interface with this database instance.</p>
<p><img alt="Create instance and authorize applications" height="431" src="/site_media/media/uploads/create-instance-and-authorize-applications.png" title="Create instance and authorize applications" width="593"></p>
<p> </p>
<h2>Using django-deployer to prepare your Django project for deployment to GAE</h2>
<p>Now that you've got the application and database instance created, you're all ready to use django-deployer to finish out the remaining steps. As you saw in the video above, there are just a few steps to follow:</p>
<pre class="brush: bash; gutter: false;">$ pip install django-deployer
$ git checkout -b appengine # optional step to make a separate branch
$ deployer-init # this creates the fabfile.py
$ fab setup
We need to ask a few questions before we can deploy your Django app
* What is your Django project directory name?
(This usually contains your settings.py and a urls.py) mywebsite
* What is your Django settings module? [mywebsite.settings]
* Where is your requirements.txt file? [requirements.txt] mywebsite/requirements/project.txt
* What version of Python does your app need? [Python2.7]
* What is your STATIC_URL? [/static/]
* What is your MEDIA_URL? [/media/]
* Which provider would you like to deploy to (dotcloud, openshift, appengine)? appengine
* What's your Google App Engine application ID (see https://appengine.google.com/)? djangodeployermezz
* What's the full instance ID of your Cloud SQL instance (should be in format "projectid:instanceid" found at https://code.google.com/apis/console/)? djangomezzanine:djangomezzdb
* What's your database name? appenginedemo
* Where is your Google App Engine SDK location? [/usr/local/google_appengine]
Creating a deploy.yml with your app's deploy info...
Created /Users/nateaune/Dropbox/code/paasbakeoff/deploy.yml
</pre>
<p>Then run fab deploy create the virtualenv with all the packages and deploy:</p>
<pre class="brush: bash; gutter: false;">$ fab deploy
...
</pre>
<p>Next create the database on Cloud SQL using the convenience command cloudcreatedb:</p>
<pre class="brush: bash; gutter: false;">$ sh manage.sh cloudcreatedb
Google SQL Client
Type "help" or "?" for help.
Connecting to Google SQL database "djangomezzanine:djangomezzdb" on host None.
Using readline for history management.
Loading history file "/Users/nateaune/.googlesql/djangomezzanine:djangomezzdb.hist"
sql&gt; Execution time: 0.212 seconds
1 row
sql&gt;
Bye.
</pre>
<p>Next syncdb the database on Cloud SQL using the convenience command cloudsyncdb:</p>
<pre class="brush: bash; gutter: false;">$ sh manage.sh cloudsyncdb
...
</pre>
<p>Everything is set up now, you can run other commands that will execute on your remotely deployed app, such as:</p>
<pre class="brush: bash; gutter: false;">$ sh manage.sh dbshell
</pre>
<p>You can now go to http://djangodeployermezz.appspot.com to see the site running!</p>
<h2>Testing and contributing</h2>
<p>django-deployer is an open source project and the code is <a href="http://github.com/natea/django-deployer">available on Github</a>. Please test it out and give me feedback. Your contributions (docs, fixes and features) are most welcome! A big thanks to <a href="http://about.me/littleq">Colin Su</a> who already contributed lots of code to get django-deployer working with Google App Engine.</p>Nate AuneTue, 09 Apr 2013 17:06:23 +0000http://appsembler.com/blog/deploy-django-apps-to-google-app-engine-with-django-deployer-in-5-minutes/DjangoPaaSA journey through time and PaaS - introducing django-deployerhttp://appsembler.com/blog/journey-through-time-and-paas-introducing-django-deployer/<p>It seems that the topic of Django deployment never seems to go out of style. It's a recurring theme for <a href="http://www.djangonauts.org/">Django user groups</a> across the country. In this post, I want to introduce a new project that I'm working on called django-deployer. But first, a brief history of deployment discussions over the last 3 years:</p>
<h3>Python deployment and hosting open space (DjangoCon 2010)</h3>
<p>At DjangoCon 2010, I organized an open space to discuss Python deployment and hosting issues which was surpringly well-attended. It became obvious then that deployment was a huge pain point for everyone from small two person dev shops, all the way up to larger companies like Redhat and Mozilla. That was also the year that I gave a 5 min lightning talk about DjangoZoom, the pivotal moment that set the stage for what was to come next. (if you want to watch me sweating on stage <a href="http://pyvideo.org/video/35/djangocon-2010--lightning-talks---day-1">watch this video at 50:40</a>)</p>
<h3>Django deployment bonanza (San Francisco and Boston Django meetups)</h3>
<p>A couple months later, I attended the <a href="http://www.meetup.com/The-San-Francisco-Django-Meetup-Group/events/15393684/">Django Deployment Bonanza meetup</a> in San Francisco and met Dave and Sameer, the founders of the now defunct <a href="http://djangy.com">Djangy</a> PaaS. Just one month later, the Boston Django meetup got a special guest speaker when <a href="http://www.pkshiu.com/loft/archive/2010/12/jacob-kaplan-moss-on-devops">Jacob Kaplan Moss gave a talk on DevOps</a>.</p>
<h3>Python deployment and hosting open space (PyCon 2011)</h3>
<p>At PyCon 2011 in Atlanta, I organized another open space on <a href="http://us.pycon.org/2011/openspaces/DeploymentHosting/">Python deployment and hosting</a> which was attended by Mitch Garnaat (author of Boto and now works at Amazon), Graham Dumpleton (author of mod_wsgi and now works at New Relic), Brian Rosner (steward of Gondor PaaS), Andrew Godwin, co-founder of now defunct ep.io (now works at Lanyrd) and folks from Excite, Opscode and Disqus.</p>
<h3>Panel: Creating a better deployment story (PyCon 2012)</h3>
<p>At the <a href="/admin/blog/blogpost/add/It%20seems%20that%20the%20topic%20of%20Django%20deployment%20never%20seems%20to%20go%20out%20of%20style.%20It's%20a%20recurring%20theme%20for%20Django%20user%20groups%20across%20the%20country.%20In%202010,%20I%20attended%20the%20Django%20Deployment%20Bonanza%20meetup%20in%20San%20Francisco%20and%20met%20the%20founders%20of%20the%20now%20defunct%20Djangy%20PaaS.%20Just%20one%20month%20later,%20the%20Boston%20Django%20meetup%20got%20a%20special%20guest%20speaker%20when%20Jacob%20Kaplan%20Moss%20gave%20a%20talk%20on%20DevOps.%20%20At%20the%202012%20PyCon,%20I%20sat%20on%20a%20panel%20&quot;Creating%20a%20better%20deployment%20story&quot;%20with%20Jacob%20Kaplan%20Moss,%20Ian%20Bicking,%20Jim%20Fulton,%20Kenneth%20Reitz%20and%20Tarek%20Ziade.%20The%20conversation%20turned%20from%20%20%20Fast%20forward%20to%202013,%20and%20deployment%20is%20still%20a%20hot%20topic,%20with%20two%20deployment%20presentations%20happening%20on%20both%20coasts,%20on%20the%20same%20night!%20%20%20%20%20https:/us.pycon.org/2012/community/WebDevSummit/">2012 PyCon Web Summit</a>, I sat on a panel "Creating a better deployment story" with Ian Bicking, Jim Fulton, Kenneth Reitz and Tarek Ziade moderated by Jacob Kaplan Moss. See some of <a href="https://docs.google.com/spreadsheet/ccc?key=0Ar-zm5xAShvadF9iWk9pSTdPMjlKQTVPeW0yODh2ZWc#gid=0">the questions</a> that were voted on in advance of this panel. The point I tried to make on the panel is that Python developers would be better served if we as a community were to put forth a standard for defining the deployment requirements for a Python application. This standard format could then be consumed by all the PaaS providers and translated into their specific way of doing things.</p>
<p>But the scope of the discussion changed when it diverged into the realm of Python packaging. Packaging is also an important topic, and peripherally related to deployment, but it also happens to be one that people feel very strongly about which meant that we spent most of the panel talking about packaging.</p>
<h3>django-deployer is born at DjangoCon sprint (DjangoCon 2012)</h3>
<p>The photo is from a dinner at DjangoCon 2012 where I once again tried to get everyone together to discuss the idea of a PaaS-agnostic definition for deployment requirements. Andrew Godwin (formerly ep.io), Kenneth Reitz (now at Heroku), Ken Cochrane and Gabriel Grant (formerly Dotcloud) and Jacob Kaplan Moss. I think Diane Mueller was also at the table (formerly ActiveState and now Redhat OpenShift).</p>
<p>At that same conference, I proposed to sprint on a universal deploy tool for Django. I pitched the idea and managed to attract a few folks to work with me on it: John Debs, Kevin Daum and Gabriel Grant. We only sprinted for a couple days, but got a working prototype pushed to Github that could create all the files needed to deploy your Django app to Dotcloud or Stackato.</p>
<h3>Snakes in the Cloud (East Bay and DC Django meetup groups) </h3>
<p>It's now 2013, and the interest in deployment remains a hot topic! On February 12, on opposite coasts, there were two talks happening on the same night, both about Django deployment! Aleksandr Vladimirsky was talking about <a href="http://www.meetup.com/The-San-Francisco-Django-Meetup-Group/events/100266682/">deploying Django-based Mezzanine to Heroku and S3</a> and at the Django-District meetup in DC, they were talking about <a href="http://www.django-district.org/events/16249987/">Django &amp; Deployment</a>. By the way, if you're in the DC area, next week the Django District group is hosting a <a href="http://www.django-district.org/events/99659672/">hands-on workshop on deploying Django to Amazon Web Services</a>.</p>
<h3>django-deployer revisited at PyCon sprint (PyCon 2013)</h3>
<p>Like many sprint-born projects, django-deployer didn't see much action for a few months, but at the most recent PyCon, I was giving a talk about <a href="/blog/deploy-your-python-app-in-5-min-with-a-paas/">deploying Python apps to PaaS providers</a>, so I decided to see if anyone wanted to <a href="https://us.pycon.org/2013/community/sprints/projects/">sprint</a> on django-deployer with me. As it turns out, there were others interested in deployment (no surprise there), so we grabbed a sprint room and started working.</p>
<p>Colin Wu from Taiwan had experience working with Google App Engine (GAE), so he volunteered to add support for GAE. Kevin Grinberg, Kyle Kelley and Wes Winham (author of <a href="https://github.com/winhamwr/neckbeard">Neckbeard</a> - best tool name ever!) also provide valuable input. I created a "PaaS matrix" Google Spreadsheet that was essentially a condensed form of my <a href="/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/">PaaS bakeoff post</a>, to make it easier to extract the code snippets we needed for each provider. (The PaaS matrix spreadsheet has since been expanded into the <a href="http://www.paascheatsheet.com">PaaS Cheatsheet</a>)</p>
<p><a href="http://natea.github.io/django-deployer/">django-deployer</a> now provides the following:</p>
<ul>
<li>Fabric script that asks questions about your Django app (settings file, requirements, database, etc.)</li>
<li>The answers to these questions are stored in deploy.yml file</li>
<li>The script then reads this file as input and outputs config files for a PaaS provider of your choice (currently Dotcloud, Stackato and Google App Engine)</li>
</ul>
<p>You then use the native clients for those PaaS providers to do the actual deployment. The nice thing is that all the information about your app is captured in the deploy.yml, so if you want to experiment with different PaaS providers, you can simply re-run the Fabric script, and it will create new config files for the other provider. It recognizes the existing deploy.yml, and doesn't ask you the same questions again.</p>
<p>Note: If you're going to try various providers, I suggest that you make a new branch for each provider, as sometimes the config files will have the same names, and there's a risk that you might unintentially overwrite one of those files when you re-run the script.</p>
<p>The <a href="http://github.com/natea/django-deployer">code is on Github</a> if you want to try it out on your project. I'd love to hear your comments and suggestions. And if you prefer a different PaaS provider than the ones already supported, it would be awesome if you contributed code to support additional providers. I consider this an early working prototype, and there is still a lot of work to do.</p>Nate AuneSun, 07 Apr 2013 21:39:37 +0000http://appsembler.com/blog/journey-through-time-and-paas-introducing-django-deployer/DjangoPaaSDeploy your Python app in 5 min with a PaaShttp://appsembler.com/blog/deploy-your-python-app-in-5-min-with-a-paas/<p>UPDATE: Here is the video recording from PyCon 2013 in Santa Clara, CA.</p>
<p><iframe height="480" src="http://www.youtube.com/embed/eJcFsaVu8HI" width="640"></iframe></p>
<p>UPDATE: Here are the slides from my actual PyCon talk, which I've expanded to include the slides from the original Django deployment talk. If you want to hear the audio from the previous practice talk, see the slides at the bottom of this post.</p>
<p><iframe height="486" src="http://www.slideshare.net/slideshow/embed_code/17293629" style="" width="597"></iframe></p>
<div><strong> <a href="http://www.slideshare.net/appsembler/pycon-talk-deploy-python-apps-in-5-min-with-a-paas" target="_blank" title="PyCon talk: Deploy Python apps in 5 min with a PaaS">PyCon talk: Deploy Python apps in 5 min with a PaaS</a> </strong> from <strong><a href="http://www.slideshare.net/appsembler" target="_blank">Appsembler</a></strong></div>
<p>Next week I'm going to be attending one of my favorite conferences of the year: <a href="http://us.pycon.org">PyCon</a>. On friday, I'm giving a talk entitled <a href="https://us.pycon.org/2013/schedule/presentation/118/">Deploy your Python app in 5 min with a PaaS</a>. If you're going to be at PyCon, stop by and say hi! You can find me on Twitter (@natea) or IRC (natea).</p>
<p>This talk is a riff on the <a href="/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/">PaaS bakeoff talk</a>, a presentation that I gave previously at the <a href="http://www.meetup.com/djangoboston/events/68186952/">Django meetup last November</a>. That talk went into great detail about how to configure your Django app to be able to deploy to various PaaS providers. In this talk for PyCon, I wanted to spend more time talking about the <em>why</em> of using a PaaS.</p>
<p>So the first part of the talk defines the problem by introducing Dave, a fictional CTO of a startup, and the challenges that he faces trying to manage his infrastructure on Amazon EC2, and how much time he has to spend on DevOps related tasks.</p>
<p>Thanks to the <a href="http://bostonpython.com">Boston Python meetup</a>, I got a chance to practice my talk last week as part of their <a href="http://meetup.bostonpython.com/events/76032852/">PyCon on the Charles series</a>. I've published the slides including synchronized audio (thanks to Phil Skaroulis for recording it!).</p>
<p><iframe height="486" src="http://www.slideshare.net/slideshow/embed_code/16786630" style="" width="597"></iframe></p>
<div><strong> <a href="http://www.slideshare.net/appsembler/deploy-python-apps-in-5-min-with-a-paa-s" target="_blank" title="Deploy Python apps in 5 min with a PaaS">Deploy Python apps in 5 min with a PaaS</a> </strong> from <strong><a href="http://www.slideshare.net/appsembler" target="_blank">Appsembler</a></strong></div>
<div><strong><br></strong></div>
<div>
<p> </p>
</div>Nate AuneWed, 06 Mar 2013 16:11:01 +0000http://appsembler.com/blog/deploy-your-python-app-in-5-min-with-a-paas/EventsPaaS10 Things Every Open Source Project Should Havehttp://appsembler.com/blog/10-things-every-open-source-project-should-have/<p>On the second day of the <a href="http://webfwd.org">WebFwd</a> accelerator, Ash and Rastin, the dynamic duo from <a href="http://www.anahitapolis.com/">Anahita</a>, cornered <a href="http://tantek.com/">Tantek Celik</a>, one of the WebFwd mentors, to grill him with questions about the business model for their open source social networking software Anahita.</p>
<p>I was talking with someone else, so I only caught fragments of their conversation, but at one point I heard Tantek say, "You're running an open source project, but you don't have an IRC channel!?"</p>
<p>To some, <a href="http://en.wikipedia.org/wiki/Irc">IRC</a> may be associated with yesteryear's technology, but for others, IRC is the lifeblood of an open source community, a virtual watering hole where newbies and veterans alike come to drink from the fountain of knowledge. Okay, it's not always emitting knowledge - often it's just senseless banter, but it still serves a vital need. Lacking a physical space, IRC provides a venue for people to come together in real-time and not just learn from each other, but get to know each other.</p>
<p>IRC is just one example, but it got me thinking about all the things that I take for granted in a mature open source community such as <a href="http://plone.org">Plone</a>. How does the community communicate? How do people report problems? How does one get the software running? How do I know the quality of the code? Below is a list of 10 things that I think every open source project should have:</p>
<h2>1) Github repository</h2>
<p>At the last <a href="https://developers.google.com/events/io/">Google I/O conference</a>, I was surprised to see that Google engineers are putting their own code examples on Github (instead of their own <a href="https://code.google.com/">Google Code</a>) and even <a href="http://www.wired.com/wiredenterprise/2013/02/mcirosoft-github/">Microsoft is using Github now</a> instead of their own <a href="http://www.codeplex.com">CodePlex</a>. Why? Because that's where the developers live!</p>
<p>If you have an open source project, and it's not on Github, it might as well not exist. What are you waiting for!? If you're still stuck in the dark age of Subversion, all is not lost! You can easily <a href="https://help.github.com/articles/importing-from-subversion">import from Subversion to Github</a> using svn2git. Even if you can't switch from Subversion entirely, you can still set up a read-only Github repo.</p>
<p>As a <a href="http://en.wikipedia.org/wiki/Distributed_version_control_system">DVCS</a> (distributed version control system), Git also allows for more distributed collaboration and experimentation, since it's trivial to <a href="http://nvie.com/posts/a-successful-git-branching-model/">make new feature branches</a> and try new things without disrupting the work that's happening on the master branch.</p>
<h2>2) Documentation</h2>
<p>I remember reading Chris McDonough's blog post "<a href="http://plope.com/Members/chrism/documentation_is_the_differentiator">Documentation is the Differentiator</a>" which basically makes the case that the documentation quality is the differentiator between project success and failure. I love his explanation:</p>
<blockquote>
<p>"A choice between good docs and better software is a false choice. The act of continually writing documentation always makes software better, because if it's hard to explain, it's probably not very good. Complexity becomes clear very quickly when you need to explain it away; it's usually easier to change the software to be less complex than it is to document something complex. It's frighteningly easy to write undocumentable software."</p>
</blockquote>
<p>Looking at Chris' own docs for the <a href="http://docs.pylonsproject.org/en/latest/docs/pyramid.html">Pyramid</a> project, it's clear why Pyramid is the fastest growing Python web framework.</p>
<p>At a minimum, your project should have the following documentation:</p>
<ul>
<li>README - tell me who your software is for, what it does and why I might want to use it</li>
<li>INSTALL - give me step by step instructions for how to get it running</li>
<li>CHANGES - show me a history of changes so I can see the evolution and frequency of updates/releases</li>
<li>AUTHORS - is this a solo project or do you have other contributors? give credit where credit is due!</li>
<li>LICENSE - make it clear how your software is licensed. See #10 below for more explanation.</li>
</ul>
<p>These files should either be authored in <a href="http://daringfireball.net/projects/markdown/">Markdown</a> (the default <a href="https://help.github.com/articles/github-flavored-markdown">markup language on Github</a>) or <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> which seems to be preferred in the Python community). Both formats are readable in a terminal as plain text files, but also can be rendered as HTML for better readability.</p>
<p>The advantage of using reStructuredText is that you can use <a href="http://sphinx-doc.org/">Sphinx</a> which allows you to easily make intelligent and beautiful documentation. And it's even been <a href="http://plope.com/Members/chrism/self_publishing">used to layout books</a>!</p>
<p>Once you are using Sphinx, you can then instantly publish the latest version of your docs to <a href="https://readthedocs.org/">Read the Docs</a>, and you can even tell Read the Docs to <a href="https://read-the-docs.readthedocs.org/en/latest/webhooks.html">update your docs every time you make a commit</a>.</p>
<h2>3) Public issue tracker</h2>
<p>As soon as you get your first bug report, the clock starts ticking: how long will it take to reproduce the bug, write a test for it that shows it was fixed, and issue the fix? If this cycle takes too long, the person who submitted the bug may have moved on with a different software package.</p>
<p>If you're the only maintainer, you can probably get by receiving and responding to bug reports by email, but as soon as you get another person helping you, you need a way to assign the bugs to the appropriate person. Again, if there are just a handful of bugs, an email exchange works fine, but when this reaches dozens or hundreds? What about handling feature requests?</p>
<p>This is when an issue tracker comes in handy, as it lets you keep track of all the bugs and feature requests and manage them in a systematic way, instead of searching through your Gmail inbox trying to find the bug report that someone (whose name you've forgotten) sent you weeks ago.</p>
<p>While you're setting up that Github repo, you can also get an issue tracker. Just click on 'Settings' and check the 'Issues' checkbox under Features. The Github issue tracker used to be quite useless, but it's come a long way since it was first announced, and is actually quite good now.</p>
<p>The advantage of having your issues in the same place as your code repository is that everything is in one place, and using <a href="https://help.github.com/articles/github-flavored-markdown">Github-flavored markdown</a> you can easily reference issues in your commit messages and even close issues with commit messages ("Fixes #45" - would close issue #45).</p>
<h2><br>4) Mailing list</h2>
<p>While the issue tracker is great for handling discrete bugs and well-defined issues, it's not the best medium for having more involved discussions about the roadmap and other topics that are not immediately actionable. A mailing list provides a forum for users and developers to answer each other's questions. As an author, that means less work for you!</p>
<p>I usually set up mailing lists using <a href="http://groups.google.com">Google Groups</a> because it's free and there's a low friction to get people to sign up since most people already have Gmail accounts. Google Groups archives all the past messages and makes them searchable, so this also serves as a knowledge-base for newcomers to find answers to their questions.</p>
<h2>5) IRC channel</h2>
<p>An asynchronous tool like a mailing list allows people to connect at each person's own convenience and schedule. An IRC channel doesn't have that benefit, but it does allow for real-time communication which is incredibly beneficial when you have a burning question at 3 in the morning and it's business hours in Europe.</p>
<p>I would argue that the free support that I've received on IRC channels of open source projects is superior to the majority of paid support I receive when calling a toll-free phone number. Usually I'm communicating directly with the author who can answer my question authoritatively rather than navigating a phone tree to be connected with someone who is reading from a script and never touches the code.</p>
<p>By now you might be asking yourself, "But Nate, do people really use IRC anymore? How would they even begin to install an IRC client?" The good news is that you don't even need to download anything to use IRC - you can use the <a href="http://webchat.freenode.net/">Webchat client</a> that Freenode provides. Or for a more featureful web-based IRC client that provides search of the conversations, Leah Culver's <a href="https://grove.io/">Grove.io</a> provides a private IRC server as a commercial service. Or if you want to go with an open source solution, Stephen Mcdonald is building <a href="https://github.com/stephenmcd/gnotty">Gnotty</a>.</p>
<p>The bad news is that IRC still appeals to more of a technical audience, so you're unlikely to use it as your main support channel for end users. But you can still benefit from real-time chat by using something like <a href="http://snapengage.com/">SnapEngage</a> or <a href="http://www.olark.com/">Olark</a> which are one-to-one web-based chat services. Some open source projects like <a href="https://wiki.jenkins-ci.org/display/JENKINS/Office+Hours">Jenkins</a> and <a href="http://www.anahitapolis.com/component/groups/group/53161-hangout-with-anahita">Anahita</a> are even hosting "office hours" via Google Hangouts.</p>
<h2>6) Twitter account</h2>
<p>This is such a no-brainer, but I'm still surprised that many open source developers don't set up Twitter accounts for their projects. If I'm using your software and I like it, I want to tweet about it. I could cc your personal Twitter account, but people might not want to read all of your tweets, just the ones about your software. Give them an easy way to follow the updates about your software.</p>
<p>Even as an open source developer, you're still trying to sell your project to people. No one benefits from software that dies in obscurity. Twitter is an effective and low cost way to spread the word about your project, and more importantly, makes it easy for others to do the same.</p>
<h2>7) Automated tests</h2>
<p>When evaluating open source software, there are a number of things that I look at to see if it passes the "smell test". One of those is automated tests. If I don't see a tests directory, I'll assume that the author doesn't take testing seriously and conclude that the software is likely to have more bugs than software with good test coverage.</p>
<p>But it's not enough to just have a test suite. Are those tests being run on every commit, or at least nightly? Are the tests passing? If they're not passing, how long have they been failing?</p>
<p>While <a href="http://jenkins-ci.org">Jenkins</a> (formerly Hudson) is the darling of the open source continuous integration software, there's a new kid on the block called <a href="http://travis-ci.org">Travis</a> and it's a growing quickly. Travis is itself open source but most developers just use the hosted service because it's free for open source projects.</p>
<p>If you've been browsing around on Github, you've probably seen <a href="http://about.travis-ci.org/docs/user/status-images/">Travis' status messages</a> reporting whether a given project's tests are passing or not. With this status message on your project's Github page, you're wearing your test results on your sleeve. This is a kind of badge that tells me you care about testing enough to broadcast it.</p>
<p>For functional testing using Selenium, <a href="https://saucelabs.com/">Sauce Labs</a> also offers free accounts for open source projects.</p>
<h2>8) Internationalization</h2>
<p>One could argue that internationalization is not a must-have, and that may be the case for certain kinds of software, especially developer-oriented software. But if you're making a product that is for a non-technical end user, it will probably appeal to people all over the world for whom English is not their native language.</p>
<p>Open source projects that are built from the start with internationalization in mind, enjoy contributions from translators all around the world who want to localize the software so that it's more applicable to their customers. Don't assume that code contributions are the only thing your users can offer - you may wake up one morning to find that your software has been translated into Swahili!</p>
<p><a href="http://transifex.com">Transifex</a> provides an easy translation management service for free to open source projects. See how Roberto, the author of <a href="http://www.mayan-edms.com">Mayan</a>, set up his <a href="https://github.com/rosarior/mayan/blob/master/.tx/config">translation config file</a> and manages these translations in English, Arabic, French, Romanian and 12 other languages from the <a href="https://www.transifex.com/projects/p/mayan-edms/">Transifex interface</a>.</p>
<h2>9) Package or Deploy scripts</h2>
<p>The easier you can make it for me to try your software, the more likely I am to invest the time to use it. If there is a 10 page installation doc, I might decide to use another software package that has a lower barrier to entry. So how do you make your software easy to try? Here are a few ideas:</p>
<p>- Provide it as an easily installable package. If you're building a Python package, <a href="http://guide.python-distribute.org/quickstart.html">make a proper release to PyPi</a>. Don't be lazy and make people check it out from your Github repo.</p>
<p>- If you're distributing software that relies on other packages, make sure to <a href="http://nvie.com/posts/pin-your-packages/">pin your versions</a> so that I can be assured to get the same versions of those packages as you intended.<br> <br>- Consider providing config files to easily deploy your software to one of the popular PaaS providers such as Heroku, Dotcloud or OpenShift. Read <a href="/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/">my blog post</a> about how to do this.</p>
<p>- Consider providing a downloadable <a href="http://virtualbox.org">VirtualBox</a> image or at least a <a href="http://vagrantup.com">Vagrant</a> file so that someone can create their own VM. This is especially useful if your software has a lot of system dependencies that will be a chore to install.</p>
<p>A VirtualBox image guarantees that the people evaluating your software are using the same operating system, and with a Vagrantfile you can make a repeatable and reliable installation method.</p>
<p>Roberto Rosario, the author of Mayan, an open source document management system, <a href="https://groups.google.com/forum/#!topic/mayan-edms/55TpopIjoIA">made a Virtualbox appliance</a> and has had a lot of positive feedback from his users.</p>
<h2>10) License</h2>
<p>I'm not a lawyer, but I know that software licensing is a messy business. You want to make it very clear to your users how your software is licensed. There are a lot of <a href="http://opensource.org/licenses">open source licenses</a> you can choose from but the most common are GPL, BSD, MIT, Apache or Mozilla.</p>
<p>Have other suggestions? Leave your feedback as a comment below! You can also upvote or downvote the article on <a href="http://news.ycombinator.com/item?id=5331297">Hacker News.</a></p>Nate AuneTue, 05 Mar 2013 01:26:45 +0000http://appsembler.com/blog/10-things-every-open-source-project-should-have/Open SourceInterview with Daniel Lindsley, creator of Haystack and Tastypiehttp://appsembler.com/blog/interview-with-daniel-lindsley-creator-of-haystack-and-tastypie/<p>Sometimes you create the best software when you are frustrated with the status quo and have an itch to scratch. <a href="http://toastdriven.com/">Daniel Lindsley's</a> <a href="http://haystacksearch.org/">Haystack</a> and <a href="http://tastypieapi.org/">Tastypie</a> are classic examples of scratching your own itch. He had a problem to solve and none of the existing solutions were good enough, so he built his own, and in doing so, came up with a solution that solves other people's problems too.</p>
<p>Those of you who have been attending the Django Boston meetup events may remember that we had Daniel come and speak at the <a href="http://www.meetup.com/djangoboston/events/50213312/">Django Boston meetup in February 2012</a>. I was unable to attend that meetup, but at the <a href="http://www.djangocon.us/sprints/">DjangoCon 2012 sprint</a> in September, I got the chance to sit down with him, and talk with him about how he came to build Haystack and Tastypie, two of the most popular add-ons for Django. Check out <a href="https://crate.io/packages/django-haystack/">Haystack</a> and <a href="https://crate.io/packages/django-tastypie/">Tastypie</a> on crate.io to see their activity.</p>
<p>Here is the full-length video from that interview:</p>
<p><iframe height="360" src="http://www.youtube.com/embed/IsMV4ZegGBc" width="640"></iframe></p>
<p>In this interview, we talk about:</p>
<div>
<ul>
<li><strong>How Daniel got started building Haystack and Tastypie - what was the impetus</strong>?</li>
<li><strong>What is the best use of Haystack?</strong> (NASA uses it for a couple of their sites)</li>
<li><strong>How are people using Tastypie?</strong> (lots of mobile, crate.io has one consistent API that serves both public as well as site itself)</li>
<li><strong>What are the challenges of maintaining an open source project?</strong> (Expectations for commercial grade support, availability, etc.)</li>
<li><strong>What do you like about the Django sprints?</strong> (Camaraderie and dedicated time to fix things. Getting in person time with people you don't usually get to work with)</li>
</ul>
</div>
<div>My favorite quote from the interview:</div>
<blockquote>
<div>"I produce open source software (OSS) because my life has been possible because of OSS. These tools affect my every day life. I've gotten so much from open source, it feels like the only right thing to do is give back to OSS." <br> -Daniel Lindsley</div>
</blockquote>
<div> </div>
<h3>Want more?</h3>
<div>Also check out Daniel's excellent talk from DjangoCon 2012 on <a href="http://toastdriven.com/blog/2012/sep/04/djangocon-2012-slides-api-design-tips/">API Design Tips</a> and <a href="http://www.youtube.com/watch?v=IKQzXu43hzY&amp;list=PL0QM1wfr-MYzocgVBNgPuooMjt-Pupbki&amp;index=16&amp;feature=plpp_video">watch the video recording of his talk</a> on Youtube.</div>
<div>He also gave a recent talk <a href="https://speakerdeck.com/daniellindsley/avoiding-the-search-hall-of-shame">Avoiding the Search Hall of Shame</a> (<a href="http://pyvideo.org/video/1559/avoiding-the-search-hall-of-shame">video</a>) at PyCon Canada 2012. See more of his slides on <a href="https://speakerdeck.com/daniellindsley">Speakerdeck</a>, and watch more of his talks on <a href="http://pyvideo.org/speaker/364/daniel-lindsley">PyVideo</a> or <a href="http://lanyrd.com/profile/daniellindsley/">Lanyrd</a>.</div>
<div> </div>
<div>If you like Daniel's work, consider <a href="https://www.gittip.com/toastdriven/">funding Daniel on Gittip</a> to make it possible for him to continue maintaining Haystack and Tastypie and developing more amazing open source software.</div>
<p><iframe height="22pt" src="https://www.gittip.com/toastdriven/widget.html" style="" width="48pt"></iframe></p>Nate AuneFri, 30 Nov 2012 20:10:09 +0000http://appsembler.com/blog/interview-with-daniel-lindsley-creator-of-haystack-and-tastypie/Interviews10 tips for hackathon successhttp://appsembler.com/blog/10-tips-for-hackathon-success/<p class="p1">The month of November was a busy month for hackathons in Boston with the <a href="http://boston.startupweekend.org/">Startup Weekend</a>, <a href="http://boston.musichackday.org/">Music Hack Day</a> and <a href="http://angelhack.com/">AngelHack</a>. This past weekend I participated in the <a href="http://bostonangelhack.eventbrite.com/">Boston Angelhack</a>, and wanted to share a few thoughts about the experience.</p>
<p class="p1">If you've never been to a hackathon, they are typically a 24-48 hour event during which time your team needs to build a working prototype for a product, usually a web or mobile app, but some teams build actual hardware devices. I've been to a lot of these hackathons, and have observed some patterns for what makes for a successful hackathon experience. So without further ado, here are 10 tips for hackathon success:</p>
<p class="p2"> </p>
<h3 class="p1">1. Set realistic expectations</h3>
<p class="p1"><img alt="" class="img_right" height="299" src="/site_media/media/uploads/blog/einstein-quote.png" width="300">There's the temptation to go into a hackathon thinking that you're going to build a 1.0 version of a product. The reality is that with only 24 hrs, you'll be lucky to build something that actually works and is demoable. Make sure it's something you can build in 24 hrs. Otherwise, you'll spend the majority of the time postulating on all the different things you could build and trying to prioritize the features, and you'll be left with a bunch of diagrams on the back of a napkin, but no actual thing that you can demo.</p>
<p class="p1">You need to think big, but start small. What is the simplest thing you can build that provides value? Err on the side of subtracting functionality rather than adding functionality. In lean startup terminology, this is called a <a href="http://en.wikipedia.org/wiki/Minimum_viable_product">minimum viable product</a> (MVP).</p>
<h3 class="p1">2. Attract talent to your team</h3>
<p class="p1">If you are a business guy and can't write code, you're going to need to convince a developer to join your team. Likewise, if you're a developer but can't design, you're team is going to be much stronger if you can attract designer talent. Without the right people on your team, you're going to be handicapped and have a hard time getting to a working prototype.</p>
<p class="p1">How do you attract talent to your team? Most hackathons provide an opportunity to pitch your idea before the hackathon starts. Write down a concise description of what you want to build, who it's for, and why they would want to use it (what's the problem that you're trying to solve). And then practice your pitch so that it comes off naturally when you stand up to present it. State very clearly who you are looking for, and if you have a particular technology in mind, mention that too. If you're planning to develop in Django, you just might attract other developers who want to code in Django too.</p>
<h3 class="p1">3. Get to know the vendors/sponsors</h3>
<p class="p1">For our project <a href="http://boston2012.hackathon.io/teams/view/913/">Ourmy</a>, we decided to use the unified APIs provided by <a href="http://singly.com">Singly</a>, rather than building all that code from scratch. Singly allowed us to authenticated users using their Facebook or Twitter accounts, and post status updates on behalf of those users to their Facebook and Twitter accounts. The Singly guys (Kristjan and Justin) were really helpful and we wouldn't have been able to develop Ourmy as fast as we did without them by our side. We also took advantage of the <a href="http://chat.singly.com">Singly chat room</a> to get questions answered by Singly engineers who weren't even at the hackathon. </p>
<h3 class="p1">4. Do your homework</h3>
<p class="p2">One thing that we didn't do was to study the APIs before the hackathon. I highly recommend going through the examples and understanding how the various libraries you're going to use are put together. That way you don't spend precious time reading docs, and trying to figure out how to use a library or 3rd party API, but can focus 100% on building the functionality that is unique to your app. We spun our wheels trying out django-bitly, only to discover that it was broken, and so we reverted to using the Python library recommended by bit.ly. </p>
<p class="p1">The <a href="http://angelhack.com/rules">AngelHack rules</a> state that you can't write any code beforehand, but you can leverage existing open source libraries. Using existing code can drastically speed up your development time, but beware of code that is buggy or not well-documented. You could spend as much time debugging someone else's code or scratching your head because of non-existent docs, than if you were to just build the functionality from scratch. </p>
<p class="p1">Where do you find trusted packages? Again, do your homework beforehand and select packages that are actively being developed (so you know they'll work with current versions of your web or mobile framework), have good documentation and preferably you've already installed them and run the tests, so you know they work. For example, if you're working in Python, look for an existing package at <a href="http://pypi.python.org">PyPi</a> and <a href="http://djangopackages.com">DjangoPackages</a> lets you compare similar Django packages. <a href="http://crate.io">Crate.io</a> is an alternative to PyPi that provides some additional information about the packages so you don't have to go digging for it.</p>
<h3 class="p1">5. Use Github for version control</h3>
<p class="p1">This seems like a no-brainer but I'm constantly amazed at how many developers are not familiar with <a href="http://en.wikipedia.org/wiki/Distributed_version_control_system">DVCS</a> such as Git. You can save yourself a lot of pain and frustration by setting up a repository on <a href="http://github.com">Github</a> at the very start, and remembering to commit early and often. It's much easier to roll back an atomic change, than trying to roll back a bug that was also committed with a bunch of new features. </p>
<p class="p1">Even better, use <a href="http://nvie.com/posts/a-successful-git-branching-model/">feature branches</a> or have each person on the team work on their own branch. Rather than merging into master and potentially breaking the application for everyone else on the team, merge the master branch into your branch, and only after you've ensured that everything is working properly, merge it back into master. </p>
<p class="p1">We got a little bit lazy and on made the mistake of merging to master before testing things fully. Inevitably, this broke things badly an hour before we were supposed to submit our hack and we ended up having to make a new 'predemo' branch and <a href="http://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html">cherry-pick</a> commits into that branch to get the needed functionality for our demo. This was painful and could have been avoided had we been more careful with our git merging process. </p>
<h3 class="p1">6. Use a PaaS for deployment and hosting</h3>
<p class="p1">This also seems like a no-brainer, but old habits die hard. Once you get used to doing something a certain way, even if evidence suggests there is an easier and faster way of doing it, we hold onto that which is familiar. Unless you're using some obscure language that is not supported by the PaaS providers, you'll be able to deploy faster and spend more time writing code and less time with tedious sysadmin tasks if you use a PaaS. Some that I like are Heroku, Dotcloud, OpenShift and Stackato, and if you're a Django developer, read my post <a href="/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/">comparing various PaaS providers for Django deployment</a>.</p>
<p class="p1">As with the vendor APIs, spend some time before the Hackathon to try out these PaaS providers to get familiar with the deployment process, and make sure that the PaaS supports all the features you need for the app you're planning to build. </p>
<h3 class="p1">7. Take frequent breaks</h3>
<p class="p1">When you're under time pressure, and when the whole team is counting on you to build feature XYZ, it's tempting to sit in one spot and plow through until you're fingers are numb from all the typing. But this is a sure-fire way to burn out and even worse, hurt yourself with <a href="http://en.wikipedia.org/wiki/Repetitive_strain_injury">RSI</a>. I always bring my <a href="http://www.kinesis-ergo.com/advantage.htm">Kinesis Ergonomic keyboard</a> with me to hackathons, and my wrists thank me for it.</p>
<p class="p1">Remember to get up from the desk, stretch your shoulders and wrists, and go get a drink of water. Sometimes walking away from the code and coming back to it after taking a break makes all the difference in breaking through a tough problem.</p>
<h3 class="p1">8. Envision your perfect demo and work backwards</h3>
<p class="p1">When I participated in <a href="http://www.techstars.com/cloud/">Techstars Cloud</a>, one of the hackstars, <a href="http://www.alexbaldwin.com/">Alex Baldwin</a> told me that the best way to prepare for demo day was to think about what you wanted to show in your demo, and then work backwards. In other words, build the functionality and UI screens that you need to show the audience what is unique about your app. A 24 hour hackathon is not the time to build a full-featured product, so focus on the parts that you want to show in the demo, and only work on those. If you decide to continue working on it, you can always come back and fill in the missing pieces. </p>
<p class="p1">It's important to spend time making a decent video, and not wait until the last minute to do it. As with the APIs and PaaS, learn how to use a Screen recording software package <em>before</em> the Hackathon, so that you're not wasting time trying to figure out how to get the audio drivers working to record the sound. </p>
<p class="p1">The official Angelhack <a href="http://boston2012.hackathon.io/pages/how_to_screencast">how to make a hack video</a> page recommends using <a href="http://screencast-o-matic.com">Screencast-o-matic.com</a>. I haven't used this software before, so I can't vouch for it, but if you have a Mac, I can't recommend <a href="http://www.telestream.net/screenflow/">Screenflow</a> enough. At $99, it's not cheap but it's the best. If you do Hackathons regularly, or you need to make a video of a new app that you've built and post to Hacker News, this software is worth it. </p>
<p class="p1">If you don't want to spend $99 for Screenflow, you can <a href="http://thenextweb.com/apple/2011/01/15/how-to-record-quick-easy-screencast-videos-with-mac-osx/">use the built-in Quicktime player to make a screen recording</a>. And if you to record the audio from your computer, visit <a href="http://bosker.wordpress.com/2011/12/11/how-to-record-a-screencast-video-for-free-on-mac-os-x-10-7-lion/">this post</a>. </p>
<p class="p1">There are other screen casting tools out there such as <a href="http://www.techsmith.com/camtasia.html">Camtasia</a> (Mac/Win), <a href="http://www.ambrosiasw.com/utilities/snapzprox/">Snapz Pro</a> ($69 Mac only), <a href="http://shinywhitebox.com/ishowu-v1/">iShowU</a> ($20 Mac only) and <a href="http://www.araelium.com/screenflick">Screenflick</a> ($29 Mac only). </p>
<h3 class="p1">9. Use an HTML/CSS framework</h3>
<p class="p1"><img alt="" class="img_right" height="170" src="/site_media/media/uploads/blog/ourmy_mockup_300px.png" width="300">The <a href="http://angelhack.com/rules">AngelHack rules</a> state that you can come to the Hackathon with pre-made wireframes or mockups, so you should definitely do this in advance, so you're not spending valuable time doing this at the Hackathon. But what about the HTML/CSS? I'd highly recommend using <a href="http://twitter.github.com/bootstrap">Twitter Bootstrap</a> or <a href="http://foundation.zurb.com/">Zerb</a> to build a nice-looking prototype without having to write hardly any CSS yourself. </p>
<p class="p1">If you're worried that your Twitter Bootstrap site is going to look like every other bootstrap site, head over to <a href="http://bootswatch.com/">Bootswatch</a> to get a free bootstrap theme, or <a href="http://wrapbootstrap.com">Wrapbootstrap</a> and buy a theme for a few bucks. The advantage of using something like Twitter Bootstrap is that you can assign someone in your team who is less technical but who has good design sense, to create the templates using <a href="http://jetstrap.com">Jetstrap</a>, a completely web-based drag-n-drop tool for building Twitter Bootstrap templates. </p>
<p class="p1">The other advantage of using Twitter Bootstrap is that there are <a href="http://viget.com/inspire/an-omnigraffle-stencil-for-twitter-bootstrap-2">Omnigraffle Stencils</a> available that you can use when you're wireframing, which can translate directly into HTML/CSS without losing time in translation. In other words, there's a one-to-one match between what is shown in the wireframe and the corresponding HTML/CSS element, so the wireframes will exactly match the HTML/CSS. </p>
<p class="p1">Like Screenflow, <a href="http://omnigraffle.com">Omnigraffle</a> is not cheap ($99) but it's the best wireframing tool for Mac, so if you do a lot of wireframing/diagramming, it's totally worth it. If you're not ready to pay $99, you can get a two-week trial.</p>
<h3 class="p1">10. Have fun!</h3>
<p class="p1">Remember that you're at the Hackathon to have fun. Yes, it's a competition but it's also a place to experiment, meet interesting people, learn something new and build something from scratch. Don't stress yourself out too much if you don't accomplish what you set out to do, or if you don't win. Just have a good time and put your best effort forward.</p>
<h3 class="p1">Other resources</h3>
<p class="p1">Kinvey's downloadable PDF <a href="http://www.kinvey.com/how-to-have-a-great-hackathon">How to have a great hackathon</a> was an inspiration for this post, and my Techstars Cloud buddies (or cloudies as we like to refer to each other) at Keen.io recently wrote a post <a href="http://blog.keen.io/post/36156420559/hackathons-are-a-terrible-way-to-get-new-users-why">Hackathons are a Terrible Way to Get New Users and Why</a>.</p>
<p class="p1">Lastly, <a href="http://brooklynhacker.com">Rob Spectre</a>, my friend at Twilio wrote a post about <a href="http://www.twilio.com/blog/2012/08/how-to-tell-a-story-with-code-2.html">how to tell a story with code</a>, that is very relevant as you're giving a presentation about your app, especially if it's very developer-focused. </p>
<h3 class="p1">Continuous hackathons</h3>
<p class="p1">Despite enjoying my time at hackathons, it always irks me that at the end of the hackathon, people say their goodbyes, go home, and then the project quietly dies. That app that you were singularly focused on for 24 hrs and sweated bullets to complete on time, is now not much more than an unmaintained landing page. The app's Github repo is a ghost town and Heroku has decommissioned your app because it doesn't get enough page visits.</p>
<p class="p1">But it doesn't have to be this way! Imagine a hackathon that was not a single event, but a continuous bi-weekly or monthly gathering in which participants meet to work on their hacks? I think that meeting consistently would help build momentum for a project, and make it more likely to reach some level of maturity.</p>
<p class="p1">Martin Fowler wrote about such a hackathon called <a href="http://martinfowler.com/bliki/CharityCodeJam.html">CharityCodeJames</a> that started out at a single event hackathon in New York to write software for charitable causes and now meets every week. Along those lines, my friend <a href="http://danielchoi.com/software/">Dan Choi</a> has a similar idea for "barnraising" to help local Boston non-profits build websites and web applications. The idea needs more fleshing out, but feel free to leave comments below if you're interested in this idea tool. </p>
<p class="p4">Happy hacking!</p>
<p class="p1"><em>(A little known fact: Appsembler was born as <a href="http://www.flickr.com/photos/noderabbit/4917594865/in/set-72157624660314257/">NodeRabbit at a Startup Weekend in 2010</a>, so you never know where an idea conceived in a weekend might take you.)</em></p>Nate AuneMon, 26 Nov 2012 00:03:51 +0000http://appsembler.com/blog/10-tips-for-hackathon-success/EventsPaaS bakeoff: Comparing Stackato, OpenShift, Dotcloud and Heroku for Django hosting and deploymenthttp://appsembler.com/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/<p>If you've been following this blog, you'll know that <a href="/blog/django-deployment-using-paas/">I'm a big fan of PaaS providers</a> - heck, I even built <a href="http://kencochrane.net/blog/2011/06/djangozoom-com-review/">one</a> which gave me even greater respect for all the work that goes into making a platform that is flexible, scalable, reliable and easy to use.</p>
<p>During the last few weeks I've been kicking the tires on these PaaS solutions, both publicly hosted ones like Heroku and Dotcloud as well as open source ones like OpenShift and CloudFoundry.</p>
<p>Last night I gave a talk <a href="http://www.meetup.com/djangoboston/events/68186952/">Django deployment revisited</a> at the Django Boston meetup group, and discussed four different PaaS providers: Stackato, Dotcloud, OpenShift and Heroku. As an example, I showed for each provider how to deploy <a href="/blog/mezzanine-a-django-based-alternative-to-wordpress/">Mezzanine</a>, a Django-based blogging and CMS software.</p>
<p>Here are the slides from the presentation (sorry, no audio):</p>
<p><iframe height="421" src="http://www.slideshare.net/slideshow/embed_code/15212342" style="" width="512"></iframe></p>
<div><strong> <a href="http://www.slideshare.net/appsembler/django-deployment-revisited" target="_blank" title="Django deployment with PaaS">Django deployment with PaaS</a> </strong> from <strong><a href="http://www.slideshare.net/appsembler" target="_blank">Appsembler</a></strong></div>
<p> </p>
<h3>Show me the code!</h3>
<p>All the code used in the examples is available in this <a href="https://github.com/appsembler/paasbakeoff/">paasbakeoff</a> Github repo - with <a href="https://github.com/appsembler/paasbakeoff/network">a different branch</a> for each PaaS provider.</p>
<p>One criteria for a PaaS is how many files do I need to add/modify in order to get my Django project deployed. What became apparent as I was giving the talk, is that all of the providers function quite similarly in regards to how you get your Django project working with them. It really boils down to these things:</p>
<h3>DATABASES</h3>
<p>All of the providers will provision a PostgreSQL or MySQL (except for Heroku) database for you without you needing to do anything except issue one command.</p>
<p>The actual database creation happens automatically except for Dotcloud in which you get to specify the name of the database in your settings.py, and you have complete control about how it's created in a createdb.py script. You can either see this as an advantage (complete flexibility) or a disadvantage (one more thing to have to manage). It's the classic tradeoff - control. vs ease-of-use, that is a recurring theme when adopting a PaaS solution.</p>
<p>The way you tell Django to use this provisioned database, is to modify your settings.py file (or use a separate production_settings.py) to override the DATABASES setting. All of the providers expose environment variables that contain the connection string:</p>
<h4>Stackato</h4>
<pre class="brush: text; gutter: false;">DATABASE_URL</pre>
<p>You can also use VCAP_SERVICES to retain <a href="http://core.cloudfoundry.org/">CloudFoundry Core</a> compatibility.<br><strong></strong></p>
<h4>OpenShift</h4>
<pre class="brush: text; gutter: false;">OPENSHIFT_MYSQL_DB_URL
OPENSHIFT_POSTGRESQL_DB_URL
</pre>
<h4>DotCloud</h4>
<pre class="brush: text; gutter: false;">DOTCLOUD_DB_SQL_LOGIN
DOTCLOUD_DB_SQL_PASSWORD
DOTCLOUD_DB_SQL_HOST
DOTCLOUD_DB_SQL_PORT</pre>
<h4>Heroku</h4>
<pre class="brush: text; gutter: false;">DATABASE_URL</pre>
<p>Also see the convenient <a href="http://pypi.python.org/pypi/dj-database-url">dj-database-url</a> package by Kenneth Reitz for handling the parsing of the DATABASE_URL string with one line of code.</p>
<p>Heroku lets you attach multiple PostgreSQL databases (master/slave, or staging/production) and each database gets it's own color-coded database URL (i.e. HEROKU_POSTGRESQL_GREEN, HEROKU_POSTGRESQL_RED, etc.) Most Django projects are only going to use 1 database, so Heroku provides a pg:promote command that lets you promote that database to be the canonical DATABASE_URL.</p>
<h3>STATIC_ROOT</h3>
<p>While it's possible to have Django serve up static assets (images, CSS, Javascript), it's advised that all static assets should be served up using an HTTP server like Apache or Nginx for performance reasons. All of the PaaS providers have a built-in way to do this except for Heroku which requires that you serve them up using Amazon S3.</p>
<h4>Stackato</h4>
<p>Stackato strangely <a href="http://docs.stackato.com/deploy/languages/python/index.html#uwsgi-python-static-files">uses uWSGI to serve the static assets</a>. In the stackato.yml file:</p>
<pre class="brush: yaml; gutter: false;">processes:
web: $STACKATO_UWSGI --static-map /static=$HOME/mywebsite/static</pre>
<h4>OpenShift</h4>
<p><strong></strong>In the settings.py file:</p>
<pre class="brush: python; gutter: false;">STATIC_ROOT = os.path.join(os.environ.get('OPENSHIFT_REPO_DIR'), 'wsgi', 'static')</pre>
<p>In /wsgi/static/.htaccess:</p>
<pre class="brush: text; gutter: false;">RewriteEngine On
RewriteRule ^application/static/(.+)$ /static/$1 [L]</pre>
<h4>Dotcloud</h4>
<p><strong></strong>In settings.py:</p>
<pre class="brush: python; gutter: false;">STATIC_ROOT = '/home/dotcloud/volatile/static/'</pre>
<p>In nginx.conf:</p>
<pre class="brush: text; gutter: false;">location /static/ { root /home/dotcloud/volatile ; }</pre>
<h4>Heroku</h4>
<p><strong></strong>In settings.py:</p>
<pre class="brush: python; gutter: false;">STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'</pre>
<p>See <a href="https://github.com/appsembler/paasbakeoff/blob/heroku/mywebsite/settings.py#L369">complete example of S3FileStorage</a></p>
<p> </p>
<h3>MEDIA_ROOT</h3>
<p>Similar to the STATIC_ROOT, the files in MEDIA_ROOT need to not only be served up Apache, Nginx or uWSGI, but also need to be persisted across subsequent deploys. By default, files that are uploaded through your Django application will be stored in the application container that is thrown away on every deploy. So we need to tell Django to store these files in a data directory that won't be discarded.</p>
<h4>Stackato</h4>
<p>You first need to create a 'filesystem' service by adding it to your stackato.yml file:</p>
<pre class="brush: yaml">services:
postgresql-mywebsite: postgresql
filesystem-mywebsite: filesystem
</pre>
<p>Then in your settings.py:</p>
<pre class="brush: python; gutter: false;">MEDIA_ROOT = os.environ['STACKATO_FILESYSTEM']
</pre>
<h4>OpenShift</h4>
<p>OpenShift provides a persisted data dir that can be referenced with the environment variable OPENSHIFT_DATA_DIR:</p>
<pre class="brush: python; gutter: false;">MEDIA_ROOT = os.path.join(os.environ.get('OPENSHIFT_DATA_DIR'), 'media')
</pre>
<p> You then need to symlink this directory to the static directory that is being served up by Apache (see above in STATIC_ROOT).</p>
<p>In .openshift/action_hooks/build:</p>
<pre class="brush: bash">#!/bin/bash
if [ ! -d $OPENSHIFT_DATA_DIR/media ]; then
mkdir $OPENSHIFT_DATA_DIR/media
fi
ln -sf $OPENSHIFT_DATA_DIR/media $OPENSHIFT_REPO_DIR/wsgi/static/media
</pre>
<h4>Dotcloud</h4>
<p>Add the following to your settings.py:</p>
<pre class="brush: python; gutter: false;">MEDIA_ROOT = '/home/dotcloud/data/media/'</pre>
<p>Add another line to your nginx.conf:</p>
<pre class="brush: text; gutter: false;">location /static/ { root /home/dotcloud/volatile; }
location /media/ { root /home/dotcloud/data/media; }
</pre>
<h4>Heroku</h4>
<p>In settings.py:</p>
<pre class="brush: python; gutter: false;">DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'</pre>
<p>See <a href="https://github.com/appsembler/paasbakeoff/blob/heroku/mywebsite/settings.py#L369">complete example of S3FileStorage</a></p>
<p> </p>
<h3>WSGI</h3>
<p>The PaaS providers use mod_wsgi, uWSGI or Gunicorn to serve the Django application.</p>
<h4>Stackato</h4>
<p>Stackato uses uWSGI by default but you can <a href="http://docs.stackato.com/deploy/languages/python/index.html#using-a-custom-web-server">use gunicorn instead</a> if you prefer. You simply place a <a href="https://github.com/appsembler/paasbakeoff/blob/stackato/wsgi.py">wsgi.py</a> file that references our Django settings file.</p>
<h4>OpenShift</h4>
<p>OpenShift uses mod_wsgi and expects to find a file /wsgi/application that <a href="https://github.com/appsembler/paasbakeoff/blob/openshift/wsgi/application">looks something like this</a>. </p>
<h4>Dotcloud</h4>
<p>Like Stackato, Dotcloud expects a <a href="https://github.com/appsembler/paasbakeoff/blob/dotcloud/wsgi.py">wsgi.py</a> file in the root of the project directory.</p>
<h4>Heroku</h4>
<p>Heroku recommends using <a href="http://gunicorn.org/">gunicorn</a>. Simply add gunicorn to your requirements.txt and INSTALLED_APPS, and create a file called Procfile in the root of your repo, that contains the following:</p>
<pre class="brush: text; gutter: false;">web: gunicorn hellodjango.wsgi -b 0.0.0.0:$PORT</pre>
<h3>Requirements</h3>
<p>All of the providers expect a requirements.txt file to be in the root of the project directory except for OpenShift which uses the more Pythonic way of defining dependencies in a setup.py file. You can still reference your requirements.txt file using <a href="https://github.com/appsembler/paasbakeoff/blob/openshift/setup.py#L15">this trick</a>.</p>
<h3>Configuration</h3>
<p><strong>Stackato</strong> (<a href="https://github.com/appsembler/paasbakeoff/blob/stackato/stackato.yml">example stackato.yml</a>) and <strong>Dotcloud</strong> (<a href="https://github.com/appsembler/paasbakeoff/blob/dotcloud/dotcloud.yml">example dotcloud.yml</a>) both use a YAML file to define configuration information about your app (i.e. what database to create and bind)</p>
<p><strong>OpenShift</strong> doesn't seem to have a configuration file, so you have to add the cartridges (database) with a separate command.</p>
<p><strong>Heroku</strong> uses a Procfile but most of the configuration is done using the config and addons commands. </p>
<h3>Management commands</h3>
<p>When it comes time to provide instructions for what should be done when you do a deploy, each provider has a slightly different way of handling these management commands (syncdb, collectstatic, migrate, etc.).</p>
<p><strong>Stackato</strong> uses <a href="https://github.com/appsembler/paasbakeoff/blob/stackato/stackato.yml#L17">post-staging hooks</a> in the stackato.yml file.</p>
<p><strong>Dotcloud</strong> uses a simple <a href="https://github.com/appsembler/paasbakeoff/blob/dotcloud/postinstall">postinstall</a> bash script.</p>
<p><strong>OpenShift</strong> uses a <a href="https://github.com/appsembler/paasbakeoff/blob/openshift/.openshift/action_hooks/deploy">deploy</a> bash script in the .openshift/action_hooks directory.</p>
<p><strong>Heroku</strong> does most of these things for you automatically and you can disable them by adding a <a href="https://devcenter.heroku.com/articles/django-assets#disabling-collectstatic">collectstatic_disabled</a> marker to the .heroku directory.</p>
<h3>Background processes with Celery</h3>
<p>Many advanced Django applications require the use of background job processing using <a href="http://celeryproject.org/">Celery</a>, a distributed task queue. Which PaaS providers support Celery?</p>
<p><strong>Stackato</strong> supposedly had Celery support at one time as evidenced by <a href="http://community.activestate.com/node/7585">this thread</a>, but the <a href="https://github.com/Stackato-Apps/celery-demo/commit/cd74b1cabcd515d4afb50d4a8e6dcd51a2b4d271">latest commit on the celery-demo</a> app is that it no longer works.</p>
<p><strong>OpenShift</strong> supposedly has Celery support according to <a href="https://openshift.redhat.com/community/forums/openshift/problem-with-starting-celery-on-the-openshift-python-26-environment">this thread</a> and <a href="https://bugzilla.redhat.com/show_bug.cgi?id=814991">this closed bug</a>, but I don't see any definitive documentation about how to set it up on OpenShift.</p>
<p><strong>Dotcloud</strong> has a complete documentation page on <a href="http://docs.dotcloud.com/tutorials/python/django-celery/">how to use Django and Celery on Dotcloud</a>.</p>
<p><strong>Heroku </strong>lets you <a href="https://devcenter.heroku.com/articles/django#running-a-worker">run Celery as just another worker</a>. </p>
<h3 class="p1">So who took the 1st prize trophy home?</h3>
<p>All of the PaaS providers are winners in my book, because they're making our jobs as developers easier! But there are clearly pros/cons for each one:</p>
<h4>Stackato</h4>
<p><strong>Pros:</strong></p>
<ul>
<li>runs anywhere (EC2, VirtualBox, VMWare, HPCloud, etc.)</li>
<li>recent versions of MySQL and PostgreSQL and support for most other services</li>
<li>you can apt-get Ubuntu packages</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>long deploy times due to rebuilding the virtualenv on every deploy</li>
<li>no hosted offering, so if you want to use it you need to deploy it yourself to EC2 or HP Cloud</li>
</ul>
<h4>OpenShift</h4>
<p><strong>Pros:</strong></p>
<ul>
<li>Open source and backed by a company (Redhat) known for open source community building</li>
<li>Zero downtime deploys with Jenkins builds and hot_deploys</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>Older versions of Python 2.6 and PostgreSQL 8.4</li>
<li>Bit clunky handling of git repos. Add your app's source as a remote, rather than adding OpenShift git repo as a remote</li>
<li>Missing built-in services that other PaaS' have (Redis, Memcached, RabbitMQ)</li>
</ul>
<h4>Dotcloud</h4>
<p><strong>Pros:</strong></p>
<ul>
<li><a href="http://docs.dotcloud.com/">Great documentation</a></li>
<li>Very flexible platform - ex: can use a script to <a href="http://docs.dotcloud.com/0.9/tutorials/python/django/#creating-your-database">tell Dotcloud exactly how to create your database</a>, control with <a href="http://docs.dotcloud.com/0.9/guides/nginx/">your own nginx.conf</a></li>
<li>Built-in support for <a href="http://docs.dotcloud.com/0.9/services/">just about any service you'd want</a></li>
<li>Zero-downtime and hot deploys with <a href="http://blog.dotcloud.com/get-to-know-our-new-build-system">Granite</a></li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>Flexibility adds some complexity</li>
</ul>
<h4>Heroku</h4>
<p><strong>Pros:</strong></p>
<ul>
<li><a href="https://devcenter.heroku.com/articles/django">Good documentation</a> (including e-book <a href="http://www.theherokuhackersguide.com/">Heroku Hacker's Guide</a>)</li>
<li>Large community of developers using Heroku (more likely you'll be able to get your question answered)</li>
<li>Large ecosystem of <a href="http://addons.heroku.com">3rd party add-ons</a></li>
<li>Easiest deployment - Heroku auto-detects Django app and sets most things up automagically (syncdb, collectstatic, etc.)</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>No serving of static assets, so you have to <a href="https://devcenter.heroku.com/articles/django-assets">use Amazon S3</a></li>
<li>No persisted storage, so you have to use something like <a href="https://devcenter.heroku.com/articles/s3">Amazon S3 for storing uploaded media</a></li>
<li>No built-in MySQL database service (have to <a href="https://devcenter.heroku.com/articles/amazon_rds">use Amazon RDS</a>)</li>
<li><a href="http://www.heroku.com/pricing/#2-0">Expensive</a> once you exceed the resources provided in the free tier and need a production database (starts at $50/mo)</li>
</ul>
<h3 class="p1">Feature comparison matrix</h3>
<p class="p1">This is by no means an exhaustive list, but just the things I could think of off the top of my head. If you have suggestions for other things to be included, let me know in the comments below.</p>
<table border="1" cellpadding="5" cellspacing="5" class="t1">
<tbody>
<tr>
<td>
<p class="p1"> </p>
</td>
<td>
<p class="p2"><strong>Stackato</strong></p>
</td>
<td>
<p class="p2"><strong>OpenShift</strong></p>
</td>
<td>
<p class="p2"><strong>Dotcloud</strong></p>
</td>
<td>
<p class="p2"><strong>Heroku</strong></p>
</td>
</tr>
<tr>
<td class="td5" valign="top">
<p class="p3"><strong>Python</strong></p>
</td>
<td class="td6" valign="top">
<p class="p4">2.7, 3.2<br> stackato runtimes</p>
</td>
<td class="td7" valign="top">
<p class="p2">2.6 (2.7)</p>
</td>
<td class="td7" valign="top">
<p class="p5">2.6.5, 2.7.2, 3.1.2, 3.2.2</p>
</td>
<td class="td8" valign="top">
<p class="p2">2.7.2</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p3"><strong>PostgreSQL</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">9.1</p>
</td>
<td class="td11" valign="middle">
<p class="p2">8.4</p>
</td>
<td class="td11" valign="middle">
<p class="p2">9.0</p>
</td>
<td class="td12" valign="middle">
<p class="p2">9.1.6</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p3"><strong>MySQL</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">5.5</p>
</td>
<td class="td11" valign="middle">
<p class="p2">5.1</p>
</td>
<td class="td11" valign="middle">
<p class="p2">5.1</p>
</td>
<td class="td12" valign="middle">
<p class="p6">(Yes, via RDS)</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p3"><strong>Persisted FS</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td12" valign="middle">
<p class="p6">(Yes, via S3)</p>
</td>
</tr>
<tr>
<td class="td13" valign="middle">
<p class="p3"><strong>Redis</strong></p>
</td>
<td class="td14" valign="middle">
<p class="p2">Yes, 2.4</p>
</td>
<td class="td15" valign="middle">
<p class="p2">No</p>
</td>
<td class="td15" valign="middle">
<p class="p2">Yes, 2.4.11</p>
</td>
<td class="td16" valign="middle">
<p class="p6">(Yes, via addon)</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p3"><strong>MongoDB</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">Yes, 2.0</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes, 2.2</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes, 2.2.1</p>
</td>
<td class="td12" valign="middle">
<p class="p6">(Yes, via addon)</p>
</td>
</tr>
<tr>
<td class="td17" valign="middle">
<p class="p3"><strong>Memcached</strong></p>
</td>
<td class="td18" valign="middle">
<p class="p2">Yes, 1.4</p>
</td>
<td class="td19" valign="middle">
<p class="p2">No</p>
</td>
<td class="td19" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td20" valign="middle">
<p class="p6">(Yes, via addon)</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p3"><strong>RabbitMQ</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">Yes, 2.4</p>
</td>
<td class="td11" valign="middle">
<p class="p2">No</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes, 2.8.5</p>
</td>
<td class="td12" valign="middle">
<p class="p6">(Yes, via addon)</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p3"><strong>Solr</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">No</p>
</td>
<td class="td11" valign="middle">
<p class="p2">No</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes, 3.4.0</p>
</td>
<td class="td12" valign="middle">
<p class="p6">(Yes, via Websolr)</p>
</td>
</tr>
<tr>
<td class="td21" valign="middle">
<p class="p3"><strong>Cron</strong></p>
</td>
<td class="td22" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td23" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td23" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td24" valign="middle">
<p class="p2">Yes</p>
</td>
</tr>
<tr>
<td class="td25" valign="middle">
<p class="p3"><strong>Extensible</strong></p>
</td>
<td class="td26" valign="middle">
<p class="p7">Yes, apt-get install</p>
</td>
<td class="td27" valign="middle">
<p class="p7">Yes, DIY cartridge</p>
</td>
<td class="td27" valign="middle">
<p class="p7">Yes, custom service</p>
</td>
<td class="td28" valign="middle">
<p class="p7">Yes, buildpacks</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p8"><strong>WebSockets</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes</p>
</td>
<td class="td12" valign="middle">
<p class="p7">Yes, via Pusher add-on</p>
</td>
</tr>
<tr>
<td class="td9" valign="middle">
<p class="p8"><strong>Hot deploys</strong></p>
</td>
<td class="td10" valign="middle">
<p class="p2">No</p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes, w/ <a href="https://access.redhat.com/knowledge/docs/en-US/OpenShift/2.0/html/User_Guide/sect-OpenShift-User_Guide-Hot_Deploying_Applications.html">hot_deploy</a></p>
</td>
<td class="td11" valign="middle">
<p class="p2">Yes, with <a href="http://blog.dotcloud.com/get-to-know-our-new-build-system">Granite</a></p>
</td>
<td class="td12" valign="middle">
<p class="p7">Yes, with <a href="https://devcenter.heroku.com/articles/labs-preboot/">preboot</a></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h3>If it ain't broke, don't fix it</h3>
<p>There were a lot of questions at the end about reliability, portability, extensibility which I think sums up the reasons that people are still not jumping on these PaaS platforms. When you've got something that works (Fabric file that pushes to AWS), why change it?</p>
<p>Several people contacted me afterwards and said that after my talk, they are now reconsidering their opinion of PaaS providers and might dump the Linode, Rackspace, AWS servers that they're babysitting in favor of a PaaS deployment solution.</p>
<h3>The Future of PaaS</h3>
<p>PaaS is still in its infancy and it will be interesting to see over the next few years what happens in the developer ecosystem as these platforms mature. There will no doubt be more consolidation, and hopefully some standardization around common formats.</p>
<p>Imagine being able to define a generic deploy.yml file in your code repo that is consumed by each PaaS provider and translated into their specific way of doing things.</p>
<p>At the last <a href="http://djangocon.us/sprints">DjangoCon 2012 sprint</a>, we started working on a project called <a href="https://github.com/natea/django-deployer">django-deployer</a>, to attempt to make a PaaS-agnostic deployment tool for Django. We added support for Stackato and Dotcloud and then the sprint was over, and I haven't had time to revisit it. But if anyone is interested in working on this, let me know!</p>
<h3>What's next</h3>
<p>I only had time in this presentation to cover four PaaS providers, but there are others that have Python/Django support including Amazon Elastic Beanstalk, Google App Engine, CloudFoundry, AppFog and even Microsoft Azure!</p>
<p>What would you like the next blog post to be? Leave a comment below to express your preference!</p>
<ul>
<li><strong>Additional PaaS providers</strong> compared like we already did with these four</li>
<li><strong>Pricing comparison</strong> showing for an average Django application what the costs are on each provider</li>
<li><strong>Deployment time durations</strong> - statistics about deployment times (how long is the first push, subsequent deploys)</li>
<li><strong>Scaling your app on a PaaS</strong></li>
<li>something else?</li>
</ul>
<div>Sign up for the <a href="http://eepurl.com/qlVfj">SaaS Developers Kit</a> to get notified about useful developer tips!</div>Nate AuneFri, 16 Nov 2012 20:44:35 +0000http://appsembler.com/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/PaaSBoston companies using Djangohttp://appsembler.com/blog/boston-companies-using-django/<p>We're huge fans of Django, the Python web framework for perfectionists with deadlines. We not only provide 1-click deployment of a <a href="http://dashboard.appsembler.com/dashboard">dozen or so Django web applications</a>, but we also use Django for this website and the <a href="http://dashboard.appsembler.com">Appsembler dashboard</a>.</p>
<p>I started the <a href="http://www.meetup.com/djangoboston/">Django Boston user group</a> in 2008, and we've had around 30 meetups to date. Last year Kevin Grinberg reached out to me and said that he was compiling a list of companies in Boston that were using Django. He was under a tight editorial deadline for BostInno, so we <a href="http://www.meetup.com/djangoboston/messages/13022108/">put out a call to the mailing list</a>, and within 24 hours we had over 50 companies respond to <a href="http://appsembler.wufoo.com/forms/companies-using-django-in-the-boston-area/">a survey</a> describing how and why they were using Django!</p>
<p>Among the respondents were well-known companies and organizations like Adobe, Akamai, Boston.com, Boston University, Hewlett Packard, Hubspot, WGBH and Harvard Medical School, as well as up-and-coming startups such as Locately, CustomMade and WebReply. See the article that Kevin wrote <a href="http://bostinno.com/2011/03/31/boston-companies-using-django/">here</a>.</p>
<p>It's been a year since we compiled this list, and judging from <a href="http://www.meetup.com/djangoboston/messages/archive/">the activity on the Django Boston mailing list</a>, there are a lot of companies hiring Django developers. We'd like to do it a bit differently this time and make it more collaborative and self-sustaining. inspired by the Boston Ruby group's Github wiki page with a <a href="https://github.com/bostonrb/bostonrb/wiki/Companies">list of companies in the Boston area that are working with Ruby</a>, we put together this wiki page with <a href="https://github.com/DjangoBoston/DjangoBoston/wiki/Companies-using-Django-in-Massachusetts">Companies using Django in Massachusetts</a>.</p>
<h3><a href="https://github.com/DjangoBoston/DjangoBoston/wiki/Companies-using-Django-in-Massachusetts"><img alt="" class="img_right" height="450" src="/site_media/media/uploads/blog/django-companies-in-boston.png" style="" width="400">View the list of Companies using Django in Massachusetts</a></h3>
<p>If your company is not listed, or you want to edit the entry for your company, simply click in the <strong>Edit Page</strong> button or fork the entire repo, make the change and submit a pull request. We'll review the change and update the wiki page. Hopefully, this will make it easier to maintain an up-to-date page since every one is responsible for making sure their info is correct. Let me know if you have a better idea of how to manage this process.</p>Nate AuneThu, 15 Nov 2012 14:52:21 +0000http://appsembler.com/blog/boston-companies-using-django/Django deployment using OpenShifthttp://appsembler.com/blog/django-deployment-using-openshift/<p>OpenShift is a platform-as-a-service (PaaS) that lets you quickly and easily deploy Django/Python apps to a production hosting environment. The OpenShift software is open source so you can either run it on servers that you own or rent, or you can use Redhat's hosted OpenShift service at <a class="reference external" href="http://openshift.redhat.com">http://openshift.redhat.com</a></p>
<p>This is the third article in <a class="reference external" href="/blog/django-deployment-using-paas/">a series about deploying Django web applications using a PaaS</a>. I'll walk you through the steps to deploy <a href="/blog/mezzanine-a-django-based-alternative-to-wordpress/">Mezzanine</a>, a popular Django-based blogging and content management system (CMS).</p>
<p>The first thing you need to do is install the OpenShift client (rhc). We're assuming that you're on Linux or MacOSX and have Ruby already installed:</p>
<pre class="brush: text; gutter: false;">$ sudo gem install rhc
</pre>
<p>Next we'll run the setup which creates a config file and SSH keypair:</p>
<pre class="brush: text; gutter: false;">$ rhc setup
</pre>
<p>I found that at least on MacOSX, I had to add the SSH key and start the SSH agent:</p>
<pre class="brush: text; gutter: false;">$ ssh-add ~/.ssh/id_rsa
$ ssh-agent
</pre>
<p>To make sure that you have everything set up properly, you can run some tests which should all pass:</p>
<pre class="brush: text; gutter: false;">$ rhc domain status
</pre>
<div class="section" id="quick-n-dirty-instructions">
<h3>Quick 'n dirty instructions</h3>
<p>If you don't want to go through the entire example below, but just want a shortcut to deploying Mezzanine, you can do the following:</p>
<pre class="brush: text; gutter: false;">$ rhc app create -a mezzanineopenshift -t python 2.6
$ rhc app cartridge add -c mysql-5.1 -a mezzanineopenshift
$ cd mezzanineopenshift
$ git remote add paasbakeoff git://github.com/appsembler/paasbakeoff.git
$ git fetch paasbakeoff
$ git merge paasbakeoff/openshift
$ git push
</pre>
<p>The repository that contains the code used in this example can be found in the <cite>openshift</cite> branch: <a class="reference external" href="https://github.com/appsembler/paasbakeoff/tree/openshift">https://github.com/appsembler/paasbakeoff/tree/openshift</a></p>
</div>
<div class="section" id="creating-the-app">
<h3>Creating the app</h3>
<p>Now we'll create a new app for our Mezzanine site:</p>
<pre class="brush: text; gutter: false;">$ rhc app create -a mezz -t python-2.6
Password: ******
Creating application 'mezz'
===========================
Scaling: no
Cartridge: python-2.6
Namespace: natea
Gear Size: default
Your application's domain name is being propagated worldwide (this might take a minute)...
Cloning into 'mezz'...
done
mezz @ http://mezz-natea.rhcloud.com/
=====================================
Application Info
================
UUID = 0e94a6186e07430f8d9b989fdf702362
Gear Size = small
Git URL = ssh://0e94a6186e07430f8d9b989fdf702362@mezz-natea.rhcloud.com/~/git/mezz.git/
SSH URL = ssh://0e94a6186e07430f8d9b989fdf702362@mezz-natea.rhcloud.com
Created = 9:20 PM
Cartridges
==========
python-2.6
RESULT:
Application mezz was created.
</pre>
<p>Check to see that it is in fact running:</p>
<pre class="brush: text; gutter: false;">$ rhc app show mezz --state
Password: ******
RESULT:
Geargroup python-2.6 is started
</pre>
<p>You'll notice that it created the app with the URL mezz-natea.rhcloud.com. That's because "natea" is my namespace. In OpenShift, each app is a "gear" and with the free account you only get 3 gears. <a class="reference external" href="https://openshift.redhat.com/community/faq/what-is-a-gear">A gear</a> is a container with a set of resources that allows users to run their applications. OpenShift runs many gears on each virtual machine and dynamically distributes gears across them.</p>
<p>Applications are made up of at least one framework that is contained in a cartridge and runs on one or more gears. Additional cartridges can be added to the application on the same or different gears.</p>
</div>
<div class="section" id="inspecting-the-auto-generated-git-repository">
<h3>Inspecting the auto-generated git repository</h3>
<p>You'll also notice that there is a Git URL and an SSH URL. A git repo has already been cloned to my computer, and using the SSH credentials, I can login to the remote instance and poke around - although unlike the Stackato PaaS, we can't install arbitrary system packages using apt-get or yum.</p>
<p>Let's take a look at the git repo that was created:</p>
<pre class="brush: text; gutter: false;">$ cd mezz
$ ls -la
total 24
drwxr-xr-x 7 nateaune staff 340 Nov 13 21:20 .
drwxr-xr-x 23 nateaune staff 816 Nov 13 21:20 ..
drwxr-xr-x 8 nateaune staff 442 Nov 13 21:20 .git
-rw-r--r-- 1 nateaune staff 12 Nov 13 21:20 .gitignore
drwxr-xr-x 5 nateaune staff 170 Nov 13 21:20 .openshift
-rw-r--r-- 1 nateaune staff 2703 Nov 13 21:20 README
drwxr-xr-x 2 nateaune staff 102 Nov 13 21:20 data
drwxr-xr-x 2 nateaune staff 102 Nov 13 21:20 libs
-rw-r--r-- 1 nateaune staff 283 Nov 13 21:20 setup.py
drwxr-xr-x 3 nateaune staff 136 Nov 13 21:20 wsgi
</pre>
</div>
<div class="section" id="defining-dependencies-in-the-setup-py-file">
<h3>Defining dependencies in the setup.py file</h3>
<p>Unlike the other PaaS providers that use a <cite>requirements.txt</cite>, with OpenShift they use a more Pythonic way of requiring a <cite>setup.py</cite> to be in your repo. In this file you define all of your Python package dependencies.</p>
<p>Since we're deploying Mezzanine, we only have one package to list in our setup.py file:</p>
<pre class="brush: python">from setuptools import setup, find_packages
setup(name='paasbakeoff',
version='1.0',
author='Nate Aune',
author_email='nate@appsembler.com',
url='https://github.com/appsembler/paasbakeoff',
packages=find_packages(),
include_package_data=True,
description='Example Mezzanine CMS deploy to OpenShift PaaS',
install_requires=['Mezzanine==1.2.4',],
)
</pre>
<p>Now we can install Mezzanine into our virtualenv with:</p>
<pre class="brush: text; gutter: false;">$ python setup.py develop
</pre>
</div>
<div class="section" id="creating-a-new-skeleton-mezzanine-project">
<h3>Creating a new skeleton Mezzanine project</h3>
<p>Next we use the <cite>mezzanine-project</cite> command that comes with Mezzanine to create a new project:</p>
<pre class="brush: text; gutter: false;">$ mezzanine-project mywebsite
$ ls mywebsite
-rw-r--r-- 1 nateaune staff 0 Nov 13 21:35 __init__.py
drwxr-xr-x 2 nateaune staff 238 Nov 13 21:37 deploy
-rw-r--r-- 1 nateaune staff 15282 Nov 13 21:35 fabfile.py
-rw-r--r-- 1 nateaune staff 548 Nov 13 21:35 local_settings.py
-rw-r--r-- 1 nateaune staff 898 Nov 13 21:35 manage.py
drwxr-xr-x 2 nateaune staff 102 Nov 13 21:37 requirements
-rw-r--r-- 1 nateaune staff 13115 Nov 13 21:37 settings.py
-rw-r--r-- 1 nateaune staff 3955 Nov 13 21:35 urls.py
</pre>
<p>You can see that this is a standard Django project directory layout, with manage.py, settings.py and urls.py files.</p>
</div>
<div class="section" id="tell-setup-py-to-reference-project-txt-optional">
<h3>Tell setup.py to reference project.txt (optional)</h3>
<p>Mezzanine includes it's requirements in a <cite>requirements/project.txt</cite> file, so we can tell our <cite>setup.py</cite> to use this file instead of hardcoding the dependencies. This means we only need to add new requirements to <cite>project.txt</cite> instead of keeping both of these files up-to-date:</p>
<pre class="brush: python">import os
from setuptools import setup, find_packages
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
setup(name='paasbakeoff',
version='1.0',
author='Nate Aune',
author_email='nate@appsembler.com',
url='https://github.com/appsembler/paasbakeoff',
packages=find_packages(),
include_package_data=True,
description='Example Mezzanine CMS deploy to OpenShift PaaS',
install_requires=open('%s/mywebsite/requirements/project.txt' % os.environ.get('OPENSHIFT_REPO_DIR', PROJECT_ROOT)).readlines(),
)
</pre>
<p>You'll notice that we're referencing <cite>OPENSHIFT_REPO_DIR</cite> here to indicate the root of our repo, but it will fallback to <cite>PROJECT_ROOT</cite> if it doesn't find that in the environment. We'll explain these OpenShift environment variables more later.</p>
<p>Note: this is not a necessary step for deploying Mezzanine to OpenShift. It's optional and only mentioned here for convenience.</p>
</div>
<div class="section" id="creating-the-wsgi-application">
<h3>Creating the wsgi application</h3>
<p>Next we need to edit the <cite>/wsgi/application</cite> file to tell OpenShift how to bind to our application. Replace the <cite>application</cite> file in the <cite>wsgi</cite> directory with this:</p>
<pre class="brush: python">#!/usr/bin/env python
import os
import sys
sys.path.append(os.path.join(os.environ['OPENSHIFT_REPO_DIR']))
os.environ['DJANGO_SETTINGS_MODULE'] = 'mywebsite.settings'
virtenv = os.environ['OPENSHIFT_HOMEDIR'] + 'python-2.6/virtenv/'
os.environ['PYTHON_EGG_CACHE'] = os.path.join(virtenv, 'lib/python2.6/site-packages')
virtualenv = os.path.join(virtenv, 'bin/activate_this.py')
try:
execfile(virtualenv, dict(__file__=virtualenv))
except IOError:
pass
#
# IMPORTANT: Put any additional includes below this line. If placed above this
# line, it's possible required libraries won't be in your searchable path
#
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>We're adding the <cite>OPENSHIFT_REPO_DIR</cite> to our Python path, so that <cite>mywebsite</cite> will be found, and then we're setting <cite>mywebsite.settings</cite> as our <cite>DJANGO_SETTINGS_MODULE</cite>.</p>
<p>We're also defining the virtual environment as <cite>python-2.6/virtenv/</cite> inside the <cite>OPENSHIFT_HOMEDIR</cite>. If you're wondering what all the environment variables are, you can SSH into the environment and run <cite>env</cite> or you can consult <a class="reference external" href="https://openshift.redhat.com/community/page/openshift-environment-variables">this page</a></p>
</div>
<div class="section" id="create-and-bind-the-database">
<h3>Create and bind the database</h3>
<p>We could use a SQLite database and store that in OpenShift's persisted <cite>/data/</cite> directory, but MySQL or PostgreSQL are more suitable databases to use in production, so we'll show how to set those up with OpenShift.</p>
<p>To bind a database to this "gear", you must add what OpenShift calls a <a class="reference external" href="https://openshift.redhat.com/community/faq/what-is-a-cartridge">cartridge</a>. Cartridges are the containers that house the framework or components that can be used to create an application. One or more cartridges run on each gear or the same cartridge can run on many gears for clustering or scaling.</p>
<p>Let's add the MySQL cartridge:</p>
<pre class="brush: text; gutter: false;">$ rhc cartridge add -c mysql-5.1 -a mezz
Password: ******
Adding 'mysql-5.1' to application 'mezz'
Success
mysql-5.1
=========
Properties
==========
Connection URL = mysql://127.12.26.129:3306/
Database Name = mezz
Password = **********
Username = admin
</pre>
<p>If you'd rather use PostgreSQL, the command is similar to the one above for creating a MySQL database:</p>
<pre class="brush: text; gutter: false;">$ rhc cartridge add -c postgresql-8.4 -a mezz
</pre>
</div>
<div class="section" id="telling-django-about-the-database-openshift-created-for-us">
<h3>Telling Django about the database OpenShift created for us</h3>
<p>Now we need to make some changes to the <cite>settings.py</cite> file so that our Django app will work with the database that OpenShift just created for us.</p>
<p>Edit the <cite>DATABASES</cite> section of the <cite>settings.py</cite> file to have the following (yeah, this code could be cleaner):</p>
<pre class="brush: python">import os
import urlparse
DATABASES = {}
if 'OPENSHIFT_MYSQL_DB_URL' in os.environ:
url = urlparse.urlparse(os.environ.get('OPENSHIFT_MYSQL_DB_URL'))
DATABASES['default'] = {
'ENGINE' : 'django.db.backends.mysql',
'NAME': os.environ['OPENSHIFT_APP_NAME'],
'USER': url.username,
'PASSWORD': url.password,
'HOST': url.hostname,
'PORT': url.port,
}
elif 'OPENSHIFT_POSTGRESQL_DB_URL' in os.environ:
url = urlparse.urlparse(os.environ.get('OPENSHIFT_POSTGRESQL_DB_URL'))
DATABASES['default'] = {
'ENGINE' : 'django.db.backends.postgresql_psycopg2',
'NAME': os.environ['OPENSHIFT_APP_NAME'],
'USER': url.username,
'PASSWORD': url.password,
'HOST': url.hostname,
'PORT': url.port,
}
else:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'dev.db',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
</pre>
<p>Again, we're using OpenShift-specific environment variables to test if there is a MySQL or PostgreSQL database available, and if so we're extracting the database name, username, password, hostname and post from the provided URL string.</p>
</div>
<div class="section" id="create-a-deploy-script">
<h3>Create a deploy script</h3>
<p>You'll notice that there is a <cite>.openshift</cite> directory in the project that contains another directory called <cite>action_hooks</cite>. This is where we define scripts that will run on every build or on every deploy.</p>
<p>Replace the <cite>deploy</cite> script with the following:</p>
<pre class="brush: bash">#!/bin/bash
# This deploy hook gets executed after dependencies are resolved and the
# build hook has been run but before the application has been started back
# up again. This script gets executed directly, so it could be python, php,
# ruby, etc.
source ${OPENSHIFT_HOMEDIR}python-2.6/virtenv/bin/activate
export PYTHON_EGG_CACHE=${OPENSHIFT_HOME_DIR}python-2.6/virtenv/lib/python-2.6/site-packages
echo "Executing 'python ${OPENSHIFT_REPO_DIR}mywebsite/manage.py syncdb --noinput'"
python "$OPENSHIFT_REPO_DIR"mywebsite/manage.py syncdb --noinput
echo "Executing 'python ${OPENSHIFT_REPO_DIR}mywebsite/manage.py collectstatic --noinput -v0'"
python "$OPENSHIFT_REPO_DIR"mywebsite/manage.py collectstatic --noinput -v0
</pre>
<p>Here we can define any Django management commands that we want to be run on every deploy, namely <cite>syncdb</cite> and <cite>collectstatic</cite>. If we were using South for database schema migrations (as all Django projects should do), we could add the <cite>migrate</cite> command as well.</p>
<p>You can read about all the different action hooks (pre-receive, pre-build, build, deploy, post-deploy) <a class="reference external" href="https://openshift.redhat.com/community/developers/deploying-and-building-applications">here</a>.</p>
<p>Example of a <a class="reference external" href="https://github.com/openshift/reviewboard-example/blob/master/.openshift/action_hooks/deploy">more sophisticated deploy script</a> for deploying Reviewboard.</p>
</div>
<div class="section" id="handling-static-media">
<h3>Handling static media</h3>
<p>OpenShift provides a directory <cite>wsgi/static</cite> that can be exposed to Apache and serve up static assets, so we need to tell Django to collect the static media to this directory. Replace the <cite>STATIC_ROOT</cite> definition in <cite>settings.py</cite> with the following:</p>
<pre class="brush: python">if 'OPENSHIFT_REPO_DIR' in os.environ:
STATIC_ROOT = os.path.join(os.environ.get('OPENSHIFT_REPO_DIR'), 'wsgi', 'static')
else:
STATIC_ROOT = os.path.join(PROJECT_ROOT, STATIC_URL.strip("/"))
</pre>
<p>Next we need to tell Apache to serve up media at <cite>/static/</cite> from this directory. Add an <cite>.htaccess</cite> file to <cite>/wsgi/static/</cite> directory:</p>
<pre class="brush: text">RewriteEngine On
RewriteRule ^application/static/(.+)$ /static/$1 [L]
</pre>
</div>
<div class="section" id="handling-uploaded-media">
<h3>Handling uploaded media</h3>
<p>OpenShift will wipe out the remote repo directory on every deploy, so if you want to make sure uploaded media files are persisted, you need to store them in the special <cite>/data/</cite> dir that OpenShift provides. Replace the <cite>MEDIA_ROOT</cite> definition in <cite>settings.py</cite> with the following:</p>
<pre class="brush: python">if 'OPENSHIFT_DATA_DIR' in os.environ:
MEDIA_ROOT = os.path.join(os.environ.get('OPENSHIFT_DATA_DIR'), 'media')
else:
MEDIA_ROOT = os.path.join(PROJECT_ROOT, *MEDIA_URL.strip("/").split("/"))
</pre>
<p>We also need to symlink this directory into <cite>/wsgi/static/media/</cite> so that the media assets will be served up by Apache. Add the following to the <cite>build</cite> script in <cite>.openshift/action_hooks</cite>:</p>
<pre class="brush: bash">#!/bin/bash
# This is a simple build script and will be executed on your CI system if
# available. Otherwise it will execute while your application is stopped
# before the deploy step. This script gets executed directly, so it
# could be python, php, ruby, etc.
if [ ! -d $OPENSHIFT_DATA_DIR/media ]; then
mkdir $OPENSHIFT_DATA_DIR/media
fi
ln -sf $OPENSHIFT_DATA_DIR/media $OPENSHIFT_REPO_DIR/wsgi/static/media
</pre>
</div>
<div class="section" id="deploying-the-app">
<h3>Deploying the app</h3>
<p>Once you've got all of these things in place, it's finally time to try deploying the app. This is done with a simple <cite>git push</cite>:</p>
<pre class="brush: text; gutter: false;">$ git push
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 498 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: restart_on_add=false
remote: Waiting for stop to finish
remote: Done
remote: restart_on_add=false
remote: ~/git/mezz.git ~/git/mezz.git
remote: ~/git/mezz.git
remote: Running .openshift/action_hooks/pre_build
remote: setup.py found. Setting up virtualenv
remote: New python executable in /var/lib/openshift/0e94a6186e07430f8d9b989fdf702362/python-2.6/virtenv/bin/python
remote: Installing setuptools............done.
remote: Installing pip...............done.
...
remote: Running .openshift/action_hooks/deploy
remote: hot_deploy_added=false
remote: MySQL already running
remote: Done
remote: Running .openshift/action_hooks/post_deploy
To ssh://0e94a6186e07430f8d9b989fdf702362@mezz-natea.rhcloud.com/~/git/mezz.git/
03605bf..e05607c master -&gt; master
</pre>
<p>If everything went well, you can go to <a class="reference external" href="http://mezz-natea.rhcloud.com">http://mezz-natea.rhcloud.com</a> to see the running app. You can login to the Mezzanine admin dashboard with these credentials. Username: admin Password: <a class="reference external" href="mailto:P@s$w0rd1">P@s$w0rd1</a></p>
</div>
<div class="section" id="troubleshooting">
<h3>Troubleshooting</h3>
<p>If there were any errors they will show up in the stdout, or you can tail the log files with:</p>
<pre class="brush: text; gutter: false;">$ rhc tail -a mezz
</pre>
</div>
<div class="section" id="subsequent-deploys">
<h3>Subsequent deploys</h3>
<p>One thing that is nice about OpenShift is that the next time we deploy, it will see that these eggs are already installed in the virtual environment and not install them again. If we want to force a clean build, we can add a <cite>force_clean_build</cite> marker file in the <cite>.openshift/markers/</cite> directory.</p>
<p>Since downloading all the packages and installing them is the most time-consuming part of the build and deploy process, this feature significantly speeds up subsequent deploys.</p>
</div>
<div class="section" id="avoiding-downtime-during-deploys">
<h3>Avoiding downtime during deploys</h3>
<p>You can also set a marker <cite>hot_deploy</cite> which will dynamically reload python scripts via WSGI Daemon mode, so that you don't experience any downtime when deploying a new version of your app.</p>
<p>Or you can <a class="reference external" href="https://access.redhat.com/knowledge/docs/en-US/OpenShift/2.0/html/User_Guide/sect-OpenShift-User_Guide-Using_the_Jenkins_Embedded_Build_System.html">use Jenkins</a> to avoid downtime when deploying.</p>
</div>
<div class="section" id="deploying-an-existing-git-repo">
<h3>Deploying an existing Git repo</h3>
<p>Since OpenShift creates a git repo for your app, if you have code living in an existing Github repo, you need to pull that into the OpenShift git repo before you can push it. The OpenShift documentation says to do it this way:</p>
<pre class="brush: text; gutter: false;">$ rhc app create -a mydjangoapp -t python-2.6
$ cd mydjangoapp
$ git remote add upstream -m master git://github.com/openshift/django-example.git
$ git pull -s recursive -X theirs upstream master
</pre>
<p>This will pull in the code from the <cite>django-example</cite> and merge it with the repo that OpenShift created on your local machine. You can then deploy this with the usual <cite>git push</cite>.</p>
<p>I've found that you can also just fetch the code from the remote repo and merge it like this:</p>
<pre class="brush: text; gutter: false;">$ git remote add django-example git://github.com/openshift/django-example.git
$ git fetch django-example
$ git merge django-example/master
</pre>
</div>
<div class="section" id="python-2-7-on-openshift">
<h3>Python 2.7 on OpenShift</h3>
<p>OpenShift currently only supports Python 2.6, but there are <a class="reference external" href="https://github.com/ehazlett/openshift-diy-py27-django">several</a> <a class="reference external" href="https://github.com/zemanel/openshift-diy-django-example">Github</a> <a class="reference external" href="https://github.com/ksurya/openshift-diy-py27-django-jenkins">repos</a> explaining how to build Python 2.7 on a DIY cartridge.</p>
</div>
<div class="section" id="other-features-of-openshift">
<h3>Other features of OpenShift</h3>
<p>For this blog post, we didn't have time to go into all the features of OpenShift, but if you're interested in learning more I invite you to check out the following links. And if you'd like to see more articles like this one, <a class="reference external" href="http://eepurl.com/qlVfj">subscribe to the SaaS Developers Kit newsletter</a>, and you'll get an email the next time we publish.</p>
<ul class="simple">
<li><a class="reference external" href="https://access.redhat.com/knowledge/docs/en-US/OpenShift/2.0/html/User_Guide/chap-OpenShift-User_Guide-Storage_Management.html#sect-OpenShift-User_Guide-Backing_up_and_Restoring_Configuration_and_User_Data">Snapshotting (backing up) your application</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/videos/getting-started-with-cron-jobs-on-openshift">Cron jobs</a></li>
<li><a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=814991">Celery support</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/developers/remote-access">Remote SSH access</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/developers/scaling">Scaling your application</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/jenkins">Jenkins builds</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/developers/do-it-yourself">Extending OpenShift with your own languages and datastores</a></li>
</ul>
</div>
<div class="section" id="what-s-next">
<h3>What's next?</h3>
<p>Now that you've successfuly deployed Mezzanine, you can try a bunch of other apps (Python or non-Python) on the <a class="reference external" href="https://openshift.redhat.com/community/developers/get-started">getting started</a> page, or you can use <a class="reference external" href="http://lewk.org/">Luke Macken's</a> excellent <a class="reference external" href="https://github.com/lmacken/openshift-quickstarter">OpenShift quickstarter</a> which lets you deploy 22 different frameworks and applications to OpenShift with a single command.</p>
<p>OpenShift is open source software, so if you want to test out OpenShift on your local machine, you can <a class="reference external" href="https://openshift.redhat.com/community/wiki/getting-started-with-openshift-origin-livecd">download the LiveCD</a>.</p>
<p>Or if you're feeling really adventurous, you can use OpenShift to <a class="reference external" href="https://openshift.redhat.com/community/wiki/build-your-own">build a private PaaS on servers that you control</a>.</p>
</div>
<div class="section" id="references">
<h3>References</h3>
<ul class="simple">
<li><a class="reference external" href="https://access.redhat.com/knowledge/docs/en-US/OpenShift/2.0/html/User_Guide/index.html">OpenShift Manual</a></li>
<li><a class="reference external" href="https://github.com/openshift/django-example">Official OpenShift Django example</a></li>
<li><a class="reference external" href="http://peng-fei-xue.blogspot.com/2012/06/howto-create-django-application-in.html">How to create a Django application on OpenShift</a></li>
<li><a class="reference external" href="https://github.com/overshard/mezzanine-openshift">Mezzanine customized and optimized for the OpenShift platform</a></li>
<li><a class="reference external" href="https://github.com/k4ml/mezzanine-openshift/">Running Mezzanine on OpenShift</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/blogs/rapid-python-and-django-app-deployment-to-the-cloud-with-a-paas">Rapid Python and Django App Deployment to the Cloud with a PaaS (July 2012)</a></li>
<li><a class="reference external" href="http://masci.wordpress.com/2012/07/17/serving-django-media-files-in-openshift/">Serving up media files</a></li>
<li><a class="reference external" href="https://openshift.redhat.com/community/forums/openshift/how-to-install-a-custom-python-package">Adding custom python packages</a></li>
</ul>
</div>Nate AuneThu, 15 Nov 2012 03:19:44 +0000http://appsembler.com/blog/django-deployment-using-openshift/MezzaninePaaSAppsembler to be a showcased startup at Boston area eventshttp://appsembler.com/blog/appsembler-to-be-a-showcased-startup-at-boston-area-events/<h4> </h4>
<div>We have several upcoming events in Boston that we're really excited about. </div>
<div> </div>
<h3>MassChallenge Awards Ceremony reception</h3>
<p><img alt="" class="img_right" height="83" src="/site_media/media/uploads/MassChallengeAward_snapshot.png" width="250">This should be a blast! We are showing off Appsembler to VCs &amp; VIPs, as well ass supporting our Startup friends get to the next level! MassChallenge is a wonderful organization in Massachusetts, and they are all about helping entrepreneurs win. Check them out!</p>
<div> </div>
<div> </div>
<div><strong><em>Details:</em></strong></div>
<div><strong><em><br></em></strong></div>
<div>Tuesday, October 23th</div>
<div>6:00 - 9:30 PM</div>
<div><a href="https://maps.google.com/maps?q=Boston+Convention+and+Exhibition+Center,+Summer+Street,+Boston,+MA&amp;hl=en&amp;ll=42.346318,-71.044314&amp;spn=0.013052,0.031865&amp;sll=42.360573,-70.970306&amp;sspn=0.417568,1.019669&amp;oq=Boston+Conven&amp;t=h&amp;hq=Boston+Convention+and+Exhibition+Center,+Summer+Street,+Boston,+MA&amp;z=16" target="_blank" title="Boston Convention and Exhibition Center">Boston Convention and Exhibition Center</a></div>
<div> </div>
<div><a href="http://masschallenge.org/awards" target="_blank" title="MassChallenge award ceremony">Click here for more info!</a></div>
<div> </div>
<div> </div>
<div> </div>
<h3>BostonBeta - Open Source Edition @ The Microsoft NERD Center</h3>
<p><img alt="" class="img_right" height="71" src="/site_media/media/uploads/Bostonbeta_REALsnapshot.png" width="250">Boston Beta is part cocktail party, part demo night. They are having an open-source edition and have invited us to be part of it! </p>
<div> </div>
<div> </div>
<div><strong><em>Details:</em></strong></div>
<div><strong><em><br></em></strong></div>
<div>Thursday, October 25th</div>
<div>6:00 - 9:00 PM</div>
<div><a href="https://maps.google.com/maps?q=Microsoft+Nerd+Center&amp;hl=en&amp;ll=42.360573,-70.970306&amp;spn=0.417568,1.019669&amp;sll=42.31435,-70.970284&amp;sspn=0.417875,1.019669&amp;t=h&amp;hq=Microsoft+Nerd+Center&amp;z=11" target="_blank" title="Microsoft NERD Center">Microsoft NERD Center</a></div>
<div> </div>
<div><a href="http://boston.tie.org" title="Boston Beta">Click here for more info!</a></div>
<div> </div>
<div> </div>
<div> </div>
<h3>TiE Challenge Annual Gala @ The Microsoft NERD center</h3>
<div><img alt="" class="img_right" height="49" src="/site_media/media/uploads/Boston%20Tie_snapshot.png" width="250">Unfortunately this even is by invitation only, but if we could bring you all along, we would! <a href="http://boston.tie.org" title="Boston Tie">Check these guys out</a> and see what they're all about! </div>
<div> </div>
<div> </div>
<div>We are excited and humbled by the opportunities we've been getting. It's a crazy ride, but we're loving every minute of it!</div>
<div> </div>
<div>Take care and catch you soon!</div>
<div> </div>
<div><img alt="" height="21" src="/site_media/media/uploads/AppSembler_Shades+alpha.png" width="100"></div>
<div> </div>Ivan SifrimFri, 19 Oct 2012 20:22:29 +0000http://appsembler.com/blog/appsembler-to-be-a-showcased-startup-at-boston-area-events/Events9 online resources for learning Python &amp; Djangohttp://appsembler.com/blog/online-resources-for-learning-python-django/<p>We know that a lot of you are hungry for knowledge and eager to start coding. The problem is that it's such a big topic, that it's not clear where to start! It turns out that a lot of people have started to recognize this need, and have done something about it. Below you'll find some wonderful resources to help you dig deep into the world of computer programming. Oh, and by the way, they're all FREE, so forks up and dig in! </p>
<p> </p>
<h4><img alt="" class="img_right" height="250" src="/site_media/media/uploads/Learnpythonthehardway_snapshot.png" width="200"><strong><a href="http://learnpythonthehardway.org/">Learn Python the Hard Way</a></strong> </h4>
<p>Now that this title grabbed your attention, check this out. Zed Shaw wrote this fantastic exercise book to teach Python to absolute beginners. If you are new to programming and people have told you that you should start with Python, this is for you. This book has had tremendous success because its bite-sized exercises make it possible for you to learn the fundamentals and feel accomplished at the same time. The book is free and is intended to go with a video series ($30) that guides you through the whole thing. You don't need to pay for the video, although we recommend the support and think it is well worth its value. </p>
<h4> </h4>
<h4><img alt="" class="img_right" height="141" src="/site_media/media/uploads/coursera_fundamentals_snapshot.png" width="250"><a href="https://www.coursera.org/course/programming1" target="_blank" title="Coursera - Learn to program: The fundamentals">Coursera's Learn to program: The fundamentals</a> </h4>
<p>Here's a friendly course taught by a couple of awesome professors from the University of Toronto. They aim to teach the world how a computer actually works. "A computer program is a set of instructions for a computer to follow, just as a recipe is a set of instructions for a chef." Everyone can understand that! They promise that the student doesn't need to know a lick of programming to take the course, and that all the resources required to complete it are freely available and included as part of the package. The coolest thing you'll learn from this class is the ability to develop a word search game, and the knowledge to create interactive text-based programs! </p>
<h4><img alt="" class="img_right" height="170" src="/site_media/media/uploads/Coursera_interactive_python_snapshot.png" width="250"><a href="https://www.coursera.org/course/interactivepython" target="_blank">Coursera - An introduction to Interactive Programming in Python</a> </h4>
<p>Check out this other gem by Coursera, this time brought to you by Rice University. The main focus of this class is to learn how to build interactive games, such as Pong, Blackjack and Asteroids. The course is built on an 8-week structure, tackling fun programming activities that get more challenging as you go along. All of the coding is done on a web-based programming environment, so you don't need to worry about buying a thing! If you love playing games and have always been curious about how they are built, this course is for you. Create the game the word's been waiting for, just give props to these guys once you become a billionaire. </p>
<p> </p>
<h4><img alt="" class="img_right" height="144" src="/site_media/media/uploads/Code%20Academy%20-%20Python%20snapshot.png" width="250"><a href="http://www.codecademy.com/courses/introduction-to-python-6WeG3?curriculum_id=4f89dab3d788890003000096" target="_blank" title="Codeacademy's introduction to Python">Codeacademy's Introduction to Python</a></h4>
<p>Wanna move it along? Codeacademy to the rescue. The great thing about this course is that it's cut up into well-labled sections, so you can skip around to the parts you are actually interested in learning. It's also very hands-on, structured in a way that lets you try out the code right after reading how it works. This course doesn't offer as much guidance as an absolute beginner might need, but if you thrive on figuring things out with minimal help, this could work well for you. </p>
<p> </p>
<h4><img alt="" class="img_right" height="140" src="/site_media/media/uploads/Udacity_CS101_snapshot.png" width="250"><a href="http://www.udacity.com/overview/Course/cs101/CourseRev/apr2012" target="_blank" title="Udacity CS101">Udacity's CS101</a></h4>
<p>Recognize this dude? That's Google co-founder SERGEY BRIN, and he's endorsing this course...so what else can I say? Actually, I can say that this class is run by two amazing professors that really have your best interest at heart. Udacity does a fantastic job by creating a holistic approach to learning the art of coding. Along with the videos, you'll find a discussion board where you can post your questions and connect with the community that is going through this experience with you. By the end of this course, you'll learn how to create a search engine that puts Google to shame. Not quite :), but it's a start! We highly recommend this course. </p>
<h4> </h4>
<h4><img alt="" class="img_right" height="167" src="/site_media/media/uploads/Udacity_CS253_snapshot.jpeg" width="250"><a href="http://www.udacity.com/overview/Course/cs253/CourseRev/apr2012" target="_blank" title="Udacity's CS253 - Web Development">Udacity's CS253 - Web Development</a> </h4>
<p>Here we have another incredible course by Udacity. This time, taught by Reddit co-founder, Steve Huffman. Steve is a really friendly guy, and a great teacher. He breaks things down with a sunny disposition and from the perspective of someone who is new to this crazy world. The goal of this class is to build a blog, and by doing that, understanding how a dynamic web app is created. To do this, you'll use Google App Engine, which makes what would otherwise be a tedious process, a push-button solution. The course starts simple, but sometimes jumps around, so we recommend that you take Udacity's CS101 before tackling this one. With those two, you should be set for a while!</p>
<p> </p>
<h4><img alt="" class="img_right" height="235" src="/site_media/media/uploads/Mechanical%20Mooc_snapshot.gif" width="250"><a href="http://mechanicalmooc.org/" target="_blank" title="The Mechanical MOOC">The Mechanical MOOC - A Gentle Introduction to Python</a> </h4>
<p>A gentle introduction. That sounds nice. This class is like a doctor holding a needle full of Python saying "shh shh..don't worry, I'll be gentle." The unique thing about this class, is that the material actually comes from other classes. They take the best bits of multiple resources and combine them into a step-by-step guide to mastering the language. Another peculiarity of this course is that it's email based, reminiscent of those old-school distance course work people used to receive in the mail. Because this class exposes you to multiple professors and schools of thought, you'll quickly learn who the major players are, and will be able to branch off into a strategy that works for you.</p>
<p> </p>
<h4><img alt="" class="img_right" height="128" src="/site_media/media/uploads/MITx%20_snapshot.png" width="250"><a href="https://www.edx.org/courses/MITx/6.00x/2012_Fall/about" target="_blank" title="EDX - Introduction to Computer Science and Programming">EDX - Introduction to Computer Science and Programming</a> </h4>
<p>Can't go wrong here. Not when three MIT professors get together to drop some knowledge on the world...for free. One of the nice things about this class is that they provide a full transcript of everything that is taught, making it painless to jump to the exact topic you're interested in, or search for a particular phrase the professor said that didn't stick the first time around. Video lessons. You gotta love 'em. Didn't get it the first time? Rewind. then rewind, then rewind again. I wish my grad school professors came with a remote control! Take the clicker and give this course a shot.</p>
<p> </p>
<h4><img alt="" class="img_right" height="80" src="/site_media/media/uploads/Getting%20started%20with%20Django_snapshot.png" width="250"><a href="http://gettingstartedwithdjango.com/" target="_blank" title="Getting started with Django">Getting started with Django(.com)</a></h4>
<p>"Wait a minute...I thought these were Python resources... what the hell is Django?" Well, Django is recognized as the most popular web framework for Python. A web framework's purpose is for doing dynamic website development. This is not a course you want to take as an absolute beginner, but as soon as you feel comfortable with Python, jump on board. Django is praised in the programming community, and tons of employers are looking for Django rockstars. Instagram was made with Django... sooooo....yeah. Kind of a hot topic right now :). </p>
<p>We hope that by providing you with some excellent options you find one that is perfect for you. Let us know in the comments below if you have any questions about these online courses. Good luck and see you on the other side! </p>
<p>Ivan Sifrim &amp; the Appsembler team</p>Ivan SifrimThu, 18 Oct 2012 21:26:14 +0000http://appsembler.com/blog/online-resources-for-learning-python-django/Learning CenterVideo interview with Travis Swicegood from the Armstrong CMS projecthttp://appsembler.com/blog/video-interview-with-travis-swicegood-from-the-armstrong-cms-project/<p>Django has a long history in the news/media industry having been born at the Lawrence World Journal. Mediamorphmedia recently announced that they were going to get out of the content management business, and <a href="http://www.epublishing.com/articles/267-epublishing-to-acquire-ellington-cms-and-ellington-marketplace">sold their popular EllingtonCMS to e-Publishing.com</a>. While it remains to be seen whether ePublishing.com will be a good steward of the EllingtonCMS software, those refuge news media organizations now have an alternative: Armstrong CMS, an open-source publishing system designed for news organizations.</p>
<p>I got a chance to sit down with <a href="http://www.travisswicegood.com/">Travis Swicegood</a> at DjangoCon to hear more about <a href="http://armstrongcms.org">Armstrong CMS</a>. Travis is the Director of Technology at Texas Tribune, where Armstrong CMS was created through a joint partnership with the Bay Citizen, and <a href="http://www.niemanlab.org/2011/03/wordpress-for-news-orgs-knight-gives-bay-citizen-texas-tribune-975000-for-open-source-cms/">funded by a $1M grant from the Knight Foundation</a>.</p>
<p> </p>
<p><iframe height="315" src="http://www.youtube.com/embed/yHaOSCI_pTE" width="560"></iframe></p>
<p>In this interview we discuss:</p>
<ul>
<li>How did the Armstrong project get started?</li>
<li>How is the Knight Foundation involved?</li>
<li>Who is Armstrong CMS for?</li>
<li>Who are some early users of Armstrong CMS (i.e. <a href="http://dailydot.com">The Daily Dot</a>)?</li>
<li>How is Armstrong CMS architected? (you can pick 'n choose components rather than doing a full Armstrong install).</li>
<li>What is the Armstrong CMS release process? (two releases per year that are stable and wo unstable releases - more experimental - not unlike Canonical's release process for Ubuntu)</li>
<li>What is your vision for bringing on new contributors?</li>
<li>Why was Django chosen for Armstrong, and what are the benefits? (Django gets out of your way when you need it to. Dealing with the amount of traffic when your site is linked to by Huffington Post.)</li>
<li>What are the long-term goals for Armstrong? (Anybody who starts a news media organization uses Armstrong. The ability to do custom things with your data is what differentiates you. Armstrong gives you that ability in a way that most CMSes don't.</li>
<li>What are the next big milestones for Armstrong?</li>
</ul>
<p> </p>
<p><strong><a href="https://dashboard.appsembler.com/appstore/app/51/armstrong-cms-demo/">Testdrive Armstrong CMS today on Appsembler!</a> Get your own site to start evaluating Armstrong CMS for your organization.</strong></p>Nate AuneThu, 18 Oct 2012 17:02:36 +0000http://appsembler.com/blog/video-interview-with-travis-swicegood-from-the-armstrong-cms-project/InterviewsMezzanine - a Django-based alternative to Wordpresshttp://appsembler.com/blog/mezzanine-a-django-based-alternative-to-wordpress/<p><a class="reference external" href="http://mezzanine.jupo.org">Mezzanine</a> is the most downloaded CMS/blogging tool for Django, recently surpassing Django CMS with <a class="reference external" href="http://www.djangopackages.com/grids/g/cms/">over 115,000 downloads</a>. Mezzanine provides a Wordpress-like editing and admin experience with the power of Django under the hood for easy customizations. We use it for the main Appsembler.com website and love it!</p>
<p>In our continuing blog series about <a href="/blog/django-deployment-using-paas/">Django on PaaS</a>, we use Mezzanine as the example Django project to deploy to all the PaaS providers.</p>
<div class="section" id="no-hassle-testdrive-of-mezzanine">
<h2>No hassle testdrive of Mezzanine</h2>
<p>If all you want to do is testdrive Mezzanine to see if you like it, you can get your own site to play with by using Appsembler's 1-click testdrive service. Visit the <a class="reference external" href="https://dashboard.appsembler.com/appstore/app/47/mezzanine/">Mezzanine info page</a> and click on the FREE trial button to get a site in just a few minutes. And the best thing is that <a class="reference external" href="http://blog.jupo.org/">Stephen McDonald</a>, the author of Mezzanine, gets paid when you buy a paid Mezzanine subscription plan, so that he can continue to make this amazing open source software.</p>
<div class="section" id="quickstart-to-get-mezzanine-running-locally">
<h2>Quickstart to get Mezzanine running locally</h2>
<p>If you want to customize Mezzanine (which you'll want to do to get the most out of it), you'll need to install it locally and create a new project where you can start customizing it with your own theme. A future blog post will guide you through complete instructions on how to customize Mezzanine.</p>
<p>Below is a brief intro to getting Mezzanine set up locally for development. You should make a virtualenv into which we'll install Mezzanine, rather than installing it in your global Python path. Note: if you don't have virtualenv installed, follow <a class="reference external" href="http://www.virtualenv.org/en/latest/index.html#installation">these instructions</a> to install it:</p>
<pre class="literal-block">$ virtualenv mezzanine-venv
New python executable in mezzanine-venv/bin/python
Installing setuptools............done.
Installing pip...............done.
</pre>
<p>Now activate the virtualenv:</p>
<pre class="literal-block">$ . mezzanine-venv/bin/activate
</pre>
<p>The prompt will change to indicate that you've activated the virtualenv. Now install Mezzanine with <a class="reference external" href="http://pip-installer.org">pip</a>:</p>
<pre class="literal-block">(mezzanine-venv)$ pip install mezzanine
Downloading/unpacking mezzanine
...
Successfully installed mezzanine django filebrowser-safe grappelli-safe bleach pytz pillow html5lib
Cleaning up...
</pre>
<p>Create a top level directory that will eventually host the config files for whichever PaaS provider you choose to deploy your site to. And use the mezzanine-project command to create a skeleton Mezzanine project:</p>
<pre class="literal-block">(mezzanine-venv)$ mkdir paasbakeoff
(mezzanine-venv)$ cd paasbakeoff
(mezzanine-venv)$ mezzanine-project mywebsite
(mezzanine-venv)$ ls mywebsite
__init__.py local_settings.py settings.py
deploy manage.py urls.py
fabfile.py requirements
</pre>
<p>You should now run the syncdb command to initialize the database (it will use sqlite3 by default):</p>
<pre class="literal-block">$ python manage.py syncdb
</pre>
<p>It might ask you to create a superuser, site record and import sample content. Just say yes to all the defaults.</p>
<p>Now you can start up Mezzanine with the usual Django runserver command:</p>
<pre class="literal-block">$ python manage.py runserver
Validating models...
0 errors found
Django version 1.4.1, using settings 'mywebsite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
</pre>
<p>Visit your Mezzanine site in your browser by going to <a class="reference external" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a> and login to the admin by going to <a class="reference external" href="http://127.0.0.1:8000/admin">http://127.0.0.1:8000/admin</a>. The default admin username is "admin" and password is "default".</p>
<p>If you want to install any other Python packages for your Mezzanine project, you can add them to the requirements/project.txt and install them with:</p>
<pre class="literal-block">$ pip install -r requirements/project.txt
</pre>
</div>
<div class="section" id="getting-help">
<h2>Getting help</h2>
<p>If you need any help getting Mezzanine running, here are a few places to turn to for help.</p>
<ul class="simple">
<li><a class="reference external" href="http://groups.google.com/group/mezzanine-users">Mezzanine-users Google Group</a></li>
<li><a class="reference external" href="irc://irc.freenode.net/mezzanine">#mezzanine IRC channel on freenode</a></li>
<li><a class="reference external" href="http://mezzanine.readthedocs.org">Mezzanine official docs</a></li>
</ul>
<p>You can also use the feedback or livechat buttons on this site, and we'll do our best to help you!</p>
</div>
</div>Nate AuneWed, 10 Oct 2012 03:54:41 +0000http://appsembler.com/blog/mezzanine-a-django-based-alternative-to-wordpress/MezzanineDjango deployment using Stackatohttp://appsembler.com/blog/django-deployment-using-stackato/<p>As mentioned in <a href="/blog/django-deployment-using-paas/">the previous post</a>, Stackato has its roots in CloudFoundry and ActiveState claims that it's backwards compatible with Cloudfoundry's API. Stackato is unique in that it's not a publicly hosted offering (like Heroku or Dotcloud) but rather a PaaS-in-a-box that you install on your own servers or on a IaaS provider such as Amazon EC2 or HP Cloud. Here is a diagram that shows architecturally how Stackato is put together.</p>
<p>To try it out, you have 3 options.</p>
<ol class="arabic simple">
<li>Deploy to ActiveState's Stackato sandbox.</li>
<li><a class="reference external" href="http://www.activestate.com/stackato/download_vm">Download a VirtualBox image</a> and run it on your local machine (what they call a "microcloud")</li>
<li><a class="reference external" href="http://www.activestate.com/stackato/cloud_hosted">Launch an EC2 instance using the Stackato AMI</a></li>
</ol>
<p>In this post, I'll only cover the first option but it's pretty easy to test with the microcloud or EC2 instance if you want to have your own environment to play with, and see the management backend of Stackato.</p>
<p>You can <a class="reference external" href="http://www.activestate.com/stackato/sandbox">apply for sandbox access</a> to ActiveState's Stackato sandbox which is usually granted within a few hours after applying. You get the Stackato Sandbox Access username and password on your <a href="http://account.activestate.com">ActiveState account page</a>.</p>
<div class="section" id="installing-the-stackato-commmand-line-tool">
<h3>Installing the Stackato commmand line tool</h3>
<p>Next you need to <a class="reference external" href="http://www.activestate.com/stackato/download_client">download the Stackato command-line tool</a>, a small binary client written in TCL (if you're curious, you can look at <a class="reference external" href="https://github.com/ActiveState/stackato-cli">the source</a> in their Github account). The Stackato docs have a whole section on <a class="reference external" href="http://docs.stackato.com/deploy/languages/python/django.html">deploying Django</a> that will be useful to reference as we walk through this example.</p>
<p>For convenience, put the client in your /usr/local/bin directory so that it's available from anywhere:</p>
<pre class="brush: text; gutter: false;">$ unzip stackato-1.4.5-macosx10.5-i386-x86_64.zip
$ sudo cp stackato-1.4.5-macosx10.5-i386-x86_64 /usr/local/bin
$ sudo ln -s /usr/local/bin/stackato-1.4.5-macosx10.5-i386-x86_64 /usr/local/bin/stackato
</pre>
</div>
<div class="section" id="mezzanine-revisited">
<h3>Mezzanine revisited</h3>
<p>Mezzanine is the most popular CMS/blogging add-on for Django, and we're going to use it as the example Django project to deploy to Stackato, and all subsequent PaaS providers in this blog article series. In <a href="/blog/mezzanine-a-django-based-alternative-to-wordpress/">this post</a> we described how to get a stock Mezzanine site set up and running locally. You can see the this Mezzanine project template in the <a class="reference external" href="https://github.com/appsembler/paasbakeoff">master branch</a>, and the Stackato version that we're going to make below in the <a class="reference external" href="https://github.com/appsembler/paasbakeoff/tree/stackato">Stackato branch</a>.</p>
</div>
<div class="section" id="configure-wsgi">
<h3>Configure WSGI</h3>
<p>Stackato uses uWSGI by default, so we need to create a wsgi.py file that uWSGI will use to load Django. Put this file in the paasbakeoff directory:</p>
<pre class="brush: python">import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mywebsite.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
</pre>
</div>
<div class="section" id="create-requirements-txt-file">
<h3>Create requirements.txt file</h3>
<p>You can see that the 'mezzanine-website' command has made a skeleton Mezzanine project for us, including a requirements directory, which contains a project.txt. Since Stackato requires the requirements.txt file to be in the top level directory, let's make a requirements.txt file in the root, which points to this project.txt file:</p>
<pre class="brush: text; gutter: false;">$ echo "-r mywebsite/requirements/project.txt" &gt; requirements.txt
</pre>
</div>
<div class="section" id="target-and-login-to-the-stackato-endpoint">
<h3>Target and login to the Stackato endpoint</h3>
<p>Now we're going to try to push the app to the Stackato's sandbox. First we need to tell Stackato what API endpoint to use. In this case it's api.stacka.to, but if you're using your own EC2 or microcloud then that domain name instead.</p>
<pre class="brush: text; gutter: false;">$ stackato target api.stacka.to
$ stackato login --email user@domain.com
Attempting login to [https://api.stacka.to]
Password: *********
Successfully logged into [https://api.stacka.to]
</pre>
</div>
<div class="section" id="deploy-to-the-stackato-sandbox">
<h3>Deploy to the Stackato sandbox</h3>
<p>Now that we've successfully logged in, let's deploy the app to the Stackato sandbox with the 'push' command. We'll answer a bunch of questions the first time, and at the end it will prompt us to save this configuration as a stackato.yml file:</p>
<pre class="brush: text; gutter: false;">$ stackato push
Would you like to deploy from the current directory ? [Yn]:
Would you like to use 'paasbakeoff' as application name ? [Yn]:
Detected a Python Application, is this correct ? [Yn]:
Framework: python
Runtime: &lt;framework-specific default&gt;
Application Deployed URL [paasbakeoff.stacka.to]:
Application Url: paasbakeoff.stacka.to
Enter Memory Reservation [128M]:
Creating Application [paasbakeoff]: OK
Create services to bind to 'paasbakeoff' ? [yN]: y
What kind of service ?
1. filesystem
2. memcached
3. mongodb
4. mysql
5. postgresql
6. rabbitmq
7. redis
Choose: 5
Specify the name of the service [postgresql-cf691]:
Creating Service: OK
Binding Service: OK
Create another ? [yN]:
Would you like to save this configuration? [yN]: y
Uploading Application [paasbakeoff]:
Checking for bad links: 29 OK
Copying to temp space: 28 OK
Checking for available resources: 44022 OK
Packing application: OK
Uploading (20K): 100% OK
Push Status: OK
Staging Application [paasbakeoff]:
-----&gt; Installing dependencies using pip
...
InstallationError: Command /opt/ActivePython-2.7/bin/python -c 'import setuptools;__file__='/staging/staged/build/pillow/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))' install --single-version-externally-managed --record /tmp/pip-v9RVEi-record/install-record.txt --user failed with error code 1 in /staging/staged/build/pillow
</pre>
<p>This will fail with this error:</p>
<pre class="brush: text">libImaging/JpegDecode.c: In function ‘ImagingJpegDecode’:
libImaging/JpegDecode.c:136:2: error: ‘JPEG_LIB_VERSION’ undeclared (first use in this function)
libImaging/JpegDecode.c:136:2: note: each undeclared identifier is reported only once for each function it appears in
error: command 'gcc' failed with exit status 1
</pre>
<p>The solution is to add 'pillow' as a PyPm dependency in the stackato.yml file. This is described in the stackato.yml reference in the Stackato docs (<a class="reference external" href="http://docs.stackato.com/reference/stackatoyml.html#language-modules">http://docs.stackato.com/reference/stackatoyml.html#language-modules</a>).</p>
</div>
<div class="section" id="defining-package-dependencies">
<h3>Defining package dependencies</h3>
<p>The auto-generated stackato.yml file looks like this:</p>
<pre class="brush: yaml">name: paasbakeoff
instances: 1
framework:
type: python
mem: 128
services:
postgresql-cf691: postgresql
</pre>
<p>We're going to add a requirements section to include pillow as a dependency, and while we're at it, since we chose PostgreSQL as our database above, we also need to add psycopg2 as a requirement (if we were using MySQL, then we would add MySQL-python instead):</p>
<pre class="brush: yaml">requirements:
pypm:
- pillow
- psycopg2
</pre>
<p>If we wanted to install psycopg2 using pip, we could have added a pip requirements section:</p>
<pre class="brush: yaml">requirements:
pypm:
- pillow
pip:
- psycopg2
</pre>
<p>Or we could have added it to our requirements.txt file with:</p>
<pre class="brush: text; gutter: false;">$ echo "psycopg2" &gt;&gt; requirements.txt
</pre>
<p>But using ActiveState's PyPm repository is faster than using pip, since the PyPm packages are already compiled.</p>
<p>Once you've pushed the app the first time, subsequent pushes must be done with the 'update' command:</p>
<pre class="brush: text; gutter: false;">$ stackato update -n
Updating application 'paasbakeoff'...
Application Url: paasbakeoff.stacka.to
Uploading Application [paasbakeoff]:
Checking for bad links: 29 OK
Copying to temp space: 28 OK
Checking for available resources: 44056 OK
Packing application: OK
Uploading (20K): 100% OK
Push Status: OK
Note that [paasbakeoff] was not automatically started because it was STOPPED before the update.
You can start it manually using `stackato start paasbakeoff`
</pre>
<p>We won't start it yet, because there's still something we need to do in order for Mezzanine to recognize the PostgreSQL database that Stackato has created for us. Modify the settings.py file, to include these imports at the top of the file:</p>
<pre class="brush: python">import os
import urlparse
</pre>
<p>And replace the 'DATABASES' section with the following:</p>
<pre class="brush: python">#############
# DATABASES #
#############
DATABASES = {}
if 'DATABASE_URL' in os.environ:
url = urlparse.urlparse(os.environ['DATABASE_URL'])
DATABASES['default'] = {
'NAME': url.path[1:],
'USER': url.username,
'PASSWORD': url.password,
'HOST': url.hostname,
'PORT': url.port,
}
if url.scheme == 'postgres':
DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql_psycopg2'
elif url.scheme == 'mysql':
DATABASES['default']['ENGINE'] = 'django.db.backends.mysql'
else:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'dev.db', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
</pre>
<p>Run the stackato update command again:</p>
<pre class="brush: text; gutter: false;">$ stackato update -n
...
Successfully installed Mezzanine dj-database-url django filebrowser-safe grappelli-safe bleach pytz html5lib
Cleaning up...
OK
Starting Application [paasbakeoff]: OK
http://paasbakeoff.stacka.to/ deployed to Stackato
</pre>
<p>If it doesn't start up, you can start it with:</p>
<pre class="brush: text; gutter: false;">$ stackato start
</pre>
<p>If there are any problems, you can look at the logs with:</p>
<pre class="brush: text; gutter: false;">$ stackato logs
</pre>
<p>Even though it looks like everything worked properly, there is a problem because Stackato is using local_settings.py which defines SQLite as the database, which will override our special Stackato database settings. We need to make sure that .gitignore has this file included, and it doesn't hurt to add an ignores: section in stackato.yml as well:</p>
<pre class="brush: yaml">ignores:
- .git
- mywebsite/dev.db
- mywebsite/local_settings.py
</pre>
<p>Run stackato update -n after you make this change.</p>
</div>
<div class="section" id="running-manage-py-syncdb">
<h3>Running manage.py syncdb</h3>
<p>The database is not set up yet because we haven't run manage.py syncdb. (Note: in Django 1.4, the manage.py file is one directory above where the settings.py file is, so for the following command you would drop the 'mywebsite' prefix if you've created a new Django project using the django-admin.py startproject command):</p>
<pre class="brush: text; gutter: false;">$ stackato run python mywebsite/manage.py syncdb --noinput
Creating tables ...
...
Creating table django_comments
Creating table django_comment_flags
Creating default account (username: admin / password: default) ...
Creating default Site 127.0.0.1:8000 ...
Creating initial content (About page, Blog, Contact form, Gallery) ...
Installed 18 object(s) from 3 fixture(s)
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
</pre>
</div>
<div class="section" id="serving-up-static-assets">
<h3>Serving up static assets</h3>
<p>When we go to <a class="reference external" href="http://paasbakeoff.appsembler.net/">http://paasbakeoff.stacka.to/</a> we can see that the site is up, but none of the images or CSS are loading properly. This is because we need to collect all the static files using the collectstatic command:</p>
<pre class="brush: text; gutter: false;">$ stackato run python mywebsite/manage.py collectstatic --noinput
...
Copying '/app/python/lib/python2.7/site-packages/django/contrib/admin/static/admin/css/rtl.css'
Copying '/app/python/lib/python2.7/site-packages/django/contrib/admin/static/admin/css/ie.css'
Copying '/app/python/lib/python2.7/site-packages/django/contrib/admin/static/admin/css/forms.css'
554 static files copied.
</pre>
<p>You can make sure that the files were copied to the right place with this command:</p>
<pre class="brush: text; gutter: false;">$ stackato files app/mywebsite/static
admin/ -
css/ -
filebrowser/ -
grappelli/ -
img/ -
js/ -
media/ -
mezzanine/ -
robots.txt 24B
test/ -
</pre>
<p>And then we need to tell Stackato to serve up these static assets using uWSGI. This is easy to setup, by a few lines to our stackato.yml file:</p>
<pre class="brush: yaml">framework:
type: python
home-dir: app
processes:
web: $STACKATO_UWSGI --static-map /static=$HOME/mywebsite/static
</pre>
<p>Run stackato update -n after you make this change.</p>
<p><a class="reference external" href="http://docs.stackato.com/deploy/languages/python/index.html#serving-static-files-with-uwsgi">Read more about serving static files using uWSGI</a></p>
</div>
<div class="section" id="run-syncdb-and-collectstatic-commands-on-every-deploy">
<h3>Run syncdb and collectstatic commands on every deploy</h3>
<p>It would be nice if the syncdb and collectstatic commands would be run every time we do a deploy. We can add these to a post-staging hook in the stackato.yml file:</p>
<pre class="brush: yaml">hooks:
post-staging:
- python mywebsite/manage.py syncdb --noinput
- python mywebsite/manage.py collectstatic --noinput
</pre>
<p>Note: it's important to put the --noinput, or else the command will halt waiting for user input.</p>
</div>
<div class="section" id="south-migrations">
<h3>South migrations</h3>
<p>If we were using South for database schema migrations (which is highly recommended), then we could add a manage.py migrate command here as well:</p>
<pre class="brush: yaml">hooks:
post-staging:
- python mywebsite/manage.py syncdb --noinput
- python mywebsite/manage.py collectstatic --noinput
- python mywebsite/manage.py migrate --noinput
</pre>
<p>Just make sure that you add South to the PyPm requirements in stackato.yml, or add it to your requirements.txt file:</p>
<pre class="brush: yaml">requirements:
pypm:
- pillow
- psycopg2
- south
</pre>
</div>
<div class="section" id="persisted-filesystem-for-file-uploads">
<h3>Persisted filesystem for file uploads</h3>
<p>Mezzanine, like many other Django-based CMSes lets users upload files (images, PDFs, etc.) which need to be persisted on the server's filesystem. By default, the filesystem is ephemeral meaning, that it will get wiped out on each deploy. Thankfully, Stackato provides a way to persist these files across deploys. You need to add a filesystem service to the services section of stackato.yml:</p>
<pre class="brush: yaml">services:
postgresql-cf691: postgresql
filesystem-paasbakeoff: filesystem
</pre>
<p>In then in settings.py, we need to tell Django to use this as the MEDIA_ROOT:</p>
<pre class="brush: python">STACKATO = 'VCAP_APPLICATION' in os.environ
if STACKATO:
MEDIA_ROOT = os.environ['STACKATO_FILESYSTEM']
</pre>
<p>Run stackato update -n after you make this change.</p>
<p><a class="reference external" href="http://docs.stackato.com/deploy/services/filesystem.html">Read more about the persistent filesystem support on Stackato here</a>.</p>
</div>
<div class="section" id="caching-with-memcache">
<h3>Caching with memcache</h3>
<p>One of the supported services of Stackato is memcached, and to provision a new memcached instance, you simply add it to the services section of stackato.yml, and add python-memcached as a dependency in the pypm requirements:</p>
<pre class="brush: yaml; highlight: [3, 6];">services:
postgresql-cf691: postgresql
memcached-paasbakeoff: memcached
requirements:
pypm:
- python-memcached
</pre>
<p>And then you need to add the following to your settings.py file:</p>
<pre class="brush: python">if 'MEMCACHE_URL' in os.environ:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': os.getenv('MEMCACHE_URL'),
}
}
</pre>
<p>And make sure that these are in your middleware classes (should already be there in default Mezzanine):</p>
<pre class="brush: python">MIDDLEWARE_CLASSES = (
"mezzanine.core.middleware.UpdateCacheMiddleware",
...
"mezzanine.core.middleware.FetchFromCacheMiddleware",
)
</pre>
<p>Run stackato update -n after you make this change.</p>
<p><a class="reference external" href="http://docs.stackato.com/deploy/services/memcached.html">Read more about memcached support on Stackato</a>.</p>
</div>
<div class="section" id="the-benefits-of-using-linux-containers">
<h3>The benefits of using Linux Containers</h3>
<p>Stackato uses Linux Containers (LXC), almost like a lightweight virtual machine, to isolate each app from the other apps running on the server. This is not only more secure but it prevents one rogue app from sucking up all the memory on the machine, because each app is memory-bound.</p>
<p><strong>SSHing into the container</strong></p>
<p>Another benefit of using LXC is that it's possible to SSH into the container and have full control without the risk of affecting other apps:</p>
<pre class="brush: text; gutter: false;">$ stackato ssh
</pre>
<p><strong>Defining OS dependencies</strong></p>
<p>Since each app is essentially running in its own Linux box, you can install OS-level dependencies with apt-get or yum. You can either do this by SSHing into the container, or to persist the changes across deploys, it's best to define these dependencies in the stackato.yml file.</p>
<p>For example, if we wanted to define python-lxml as a OS level package to be installed, we could add it as follows:</p>
<pre class="brush: yaml">requirements:
running:
ubuntu:
- python-lxml
</pre>
<p><a class="reference external" href="http://docs.stackato.com/reference/stackatoyml.html#requirements">Read more about OS dependencies on Stackato</a></p>
</div>
<div class="section" id="wrap-up">
<h3>Wrap up</h3>
<p>That concludes the first article in this PaaS deployment for Django series! I hope you enjoyed learning how to get your Django app deployed quickly using Stackato. For the next article, we'll walk through how to deploy Mezzanine with Dotcloud.</p>
<p>If you find an errors in the examples, or have feedback, I welcome you to use the feedback button on the right of the page, or the live chat button on the bottom of the page. You can also submit an issue to the <a class="reference external" href="https://github.com/appsembler/paasbakeoff/issues">Github issue tracker</a>, and we'll fix it right away.</p>
</div>
<div class="section" id="don-t-miss-the-next-article">
<h3>Don't miss the next article!</h3>
<p>If you'd like to be notified when new articles in this series are posted, sign up for the <a class="reference external" href="http://eepurl.com/qlVfj">SaaS Developers Kit</a> announcement list, and we'll shoot you an email as soon a new post is available.</p>
</div>Nate AuneWed, 10 Oct 2012 03:17:28 +0000http://appsembler.com/blog/django-deployment-using-stackato/MezzaninePaaSDjango deployment using Platform-as-a-Service (PaaS)http://appsembler.com/blog/django-deployment-using-paas/<p><strong>UPDATE:</strong> I've published a <a href="/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/">PaaS bakeoff</a> summary comparing four different PaaS providers: Heroku, Dotcloud, Stackato and OpenShift.</p>
<p>Django developers have had to wrestle with deployment for so long, that just about everyone by now has either resorted to writing their own <a class="reference external" href="https://github.com/search?langOverride=&amp;q=django+fabric&amp;repo=&amp;start_value=1&amp;type=Repositories&amp;utf8=✓">custom Fabric script</a> or embraced <a class="reference external" href="http://honza.ca/2011/09/using-chef-with-small-django-apps">Chef</a> or Puppet as their swiss army knife provisioning and deployment tool. Google App Engine has had Django support for a few years now, but no Django developer took it seriously because your only data storage option was to use Google's Bigtable NoSQL datastore rather than a more common RDBMS such as MySQL or PostgreSQL. (Note: Google has since announced SQL support for App Engine, so you no longer need to use django-nonrel.)</p>
<p>But within the last year, there has emerged a wave of PaaS providers that offer seamless deployment without having to manage servers, a luxury that Rails developers have enjoyed for several years with Heroku. Some of these Python-only providers have come and gone (Djangy, ep.io and my own DjangoZoom), but the providers who are still standing are getting more mature and broadening their offerings. While Dotcloud has been polyglot from the start, Heroku only recently added their Cedar stack to support other runtimes besides Ruby, including Python. We also saw two goliaths release open source PaaS solutions, VMWare's CloudFoundry and Redhat's OpenShift. Amazon even recently announced support for Python on their Elastic Beanstalk PaaS.</p>
<p>So the market is heating up and it's getting quite competitive, which likely means falling prices but also carries the risk for consolidation as bigger PaaS players buy out or crush smaller players. We've already seen EngineYard buy Orchestra (to beef up their PHP offering) and AppFog buy Nodester (to beef up their Node.js offering). AppFog switched from their homegrown PaaS to building on top of CloudFoundry, and ActiveState took a similar route with their Stackato PaaS, which also has its origins in CloudFoundry, but has since diverged quite significantly from CloudFoundry.</p>
<p>If you're new to PaaS, I suggest looking at <a class="reference external" href="http://venturebeat.com/2012/07/05/engine-yard-paas-infographic/">EngineYard's Infographic</a> or <a class="reference external" href="http://gigaom.com/cloud/why-2013-is-the-year-of-noops-for-programmers-infographic/">AppFog's infographic</a>, because heck, who doesn't love infographics!</p>
<p>With all of these PaaS offerings, how does one know which one to use and trust? How do you know if it has the features you need for your app, and how do you know if it will scale, and how much is it going to cost? In a recent Venturebeat article entitled <a class="reference external" href="http://venturebeat.com/2012/10/08/paas-platform-as-a-service-explained/">An ugly duckling no more: why Platform-as-a-service is poised for huge growth</a>, the author says that unfamiliarity with PaaS among developers is a barrier to adoption:</p>
<blockquote>
<p class="literal-block">Not enough people know what PaaS can help their company accomplish. Heroku’s Teich said when he talks to developers and enterprises about PaaS, they don’t do much evaluation of their options or even know what the options are. Basically, they are woefully uneducated. "Developers have a lot of preconceived notions about which PaaS they should use," Teich said. "It’s another sign that PaaS is something that has a lot of growth potential."</p>
</blockquote>
<p>I remembered reading <a class="reference external" href="http://kencochrane.net/blog/2011/06/django-hosting-roundup-who-wins/">Ken Cochrane's blog series</a> last year in which he reviewed all of the Django-supporting PaaS providers and wrapped it up with a nice summary of the pros/cons of each provider. At the recent DjangoCon, he admitted that they need to be rewritten and updated, but given that <a class="reference external" href="http://kencochrane.net/blog/2012/03/im-now-working-for-dotcloud/">he's now employed by Dotcloud</a>, he's not exactly in the best position to do this comparison. I, on the other hand don't have any such allegiance and can therefore write an unbiased comparison of the various PaaS providers from the standpoint of a Django developer.</p>
<p>So inspired by Ken's posts, this is the first in a series of blog posts exploring how to deploy Django apps on the leading PaaS providers:</p>
<ul class="simple">
<li><strong>Stackato</strong>: <a href="/blog/django-deployment-using-stackato/">How to deploy Django projects to the Stackato PaaS</a></li>
<li><strong>OpenShift</strong>: <a href="/blog/django-deployment-using-openshift/">Deploying Django to OpenShift</a></li>
<li><strong>Dotcloud</strong>: article coming soon!</li>
<li><strong>Heroku</strong>: article coming soon!</li>
<li><strong>Amazon Elastic Beanstalk</strong>: article coming soon!</li>
</ul>
<p>And if I'm not PaaS'ed out by the time I've done these, I'll continue with <a class="reference external" href="http://Gondor.io">Gondor.io</a>, <a class="reference external" href="https://developers.google.com/appengine/">Google App Engine</a>, <a class="reference external" href="http://AppFog.com">AppFog</a>, <a class="reference external" href="http://cloudfoundry.com">CloudFoundry</a>, and who knows, maybe even <a class="reference external" href="http://www.windowsazure.com/en-us/develop/python/">Microsoft Azure</a>!</p>
<div class="section" id="id1">
<p><strong>UPDATE:</strong> I've published a <a href="/blog/paas-bakeoff-comparing-stackato-openshift-dotcloud-and-heroku-for-django-hosting-and-deployment/">PaaS bakeoff</a> summary comparing four different PaaS providers: Heroku, Dotcloud, Stackato and OpenShift and what changes you need to make to your Django project to deploy it.</p>
</div>
<div class="section" id="stay-up-to-date">
<h1>Stay up to date!</h1>
<p>If you'd like to be notified when new articles in this series are posted, sign up for the <a class="reference external" href="http://eepurl.com/qlVfj">SaaS Developers Kit</a> announcement list, and we'll shoot you an email as soon a new post is available.</p>
</div>Nate AuneTue, 09 Oct 2012 19:28:31 +0000http://appsembler.com/blog/django-deployment-using-paas/PaaSReplace your filing cabinets and digitize your documents with Mayanhttp://appsembler.com/blog/replace-your-filing-cabinets-and-digitize-your-documents-with-mayan/<p><img alt="Roberto working on Mayan" border="0" class="img_right" height="225" src="/site_media/media/uploads/blog/2969_162521130095_868540095_6777827_2062753_n.jpg" title="Roberto working on Mayan" width="300"></p>
<p>Wouldn't it be great if you could always find that document you were looking for? When looking around for high quality open source software, I came across <a href="http://www.mayan-edms.com" target="_blank">Mayan</a>, an electronic document management system (or EDMS for short), and reached out to the author, Roberto Rosario.</p>
<p>What makes Mayan impressive is not only software itself, but the passion that Roberto has for his software. One need only look at his tireless dedication to responding to questions on the mailing list or promptly fixing reported bugs, to see that Roberto epitomizes the exceptional open source community leader.</p>
<p>In the last few months, I've had many conversations with Roberto, both by email and Skype, and have grown to admire and respect the thought and care that he's put into Mayan.</p>
<p>The software is rich with features including document search linking, tagging, indexing, commenting, user defined metadata and more. You can even upload scanned documents and they are OCRed for fast searching. Mayan is also multilingual and has been translated into several languages.</p>
<p>And so we're super excited to announce that Mayan is now available as a hosted service on Appsembler. With one-click you can launch <a href="https://dashboard.appsembler.com/appstore/app/48/mayan/">your very own trial Mayan site</a> and start playing with the software in a few minutes. Each site provides full admin privileges so you can kick the tires and look under the hood. </p>
<p>It's been a dream of Roberto's to provide a cloud offering of Mayan, and we're absolutely thrilled to finally make that dream a reality! Thanks Roberto for making such awesome software.</p>adminSun, 03 Jun 2012 05:51:40 +0000http://appsembler.com/blog/replace-your-filing-cabinets-and-digitize-your-documents-with-mayan/DjangoOpen SourceAppsembler is a Techstars Cloud companyhttp://appsembler.com/blog/appsembler-is-a-techstars-cloud-company/<p><img alt="" border="0" height="168" src="/site_media/media/uploads/startup-life.png" style="" width="250">Hey everyone! This is Nate, Founder and CEO of Appsembler. And this is the very first blog post on the Appsembler blog. Yippee! I'm very pleased to announce that Appsembler is a <a href="http://techstars.com/cloud">Techstars Cloud</a> company. What that means is that we got to hang out with 10 other really cool companies in San Antonio, TX for 3 months and participate in an amazing mentorship program. It has been a roller-coaster ride and now I know why they call it an accelerator. I've learned so much and grown as a company and as a person, being challenged in ways that I had not expected. I'll be blogging more about our experience now that the cat is out of the bag. Now I must get some sleep because tomorrow is the big Demo Day where we have an amazing opportunity to pitch to a room full of investors. Wish us luck!</p>adminTue, 10 Apr 2012 20:53:12 +0000http://appsembler.com/blog/appsembler-is-a-techstars-cloud-company/