Plone on Heroku
** WARNING ** Currently Plone contains syntax errors (skins aren’t valid
python, why are we calling then .py!!) and heroku really doesn’t like that.
Currently you can’t deploy again after the first successful Plone
deployment because of it. I have reported this.
You will require
- The heroku tools installed locally and working
- A verified heroku account
- A willingness to spend $15 a month for 20GB of Postgres (Plone doesnt
fit in 5mb).
Starting a project
We need to be able to install Plone in a virtualenv and do without any of the
environment building capabilities of buildout. On top of that, the runtime
environment is temporary, so we cant build it manually after the initial push.
In your requirements.txt:
The first 2 eggs are virtual packages that install 200+ packages in your
virtualenv. These are needed because we need to pin the versions of Plone that
are to be used.
The third egg provides bin/plone and bin/migrate. These helpers
will dynamically provision their environment as it is required and instance
a site / run migrations.
We’ll be using RelStorage to get cheap persistent storage. We have to use 1.4.2
over the 1.5.x series in order to avoid the plpgsql requirement it would
At the time of writing it appears that only Django Python apps get a database
automatically. You can get one by adding a folder with an empty settings.py:
You will need a Procfile so heroku knows how to run a zope instance:
web: ./bin/plone -p $PORT
Doing a local build
Build your virtualenv:
./bin/pip install -r requirements.txt
You can start a plone instance like this:
That will get you a plone instance running on port 8080. By default it won’t
be using any data store.
Adding your product
You can quickly create a new product with ZopeSkel:
mkdir src && cd src
pip install zopeskel
zopeskel plone my.app
Then follow the prompts. Make sure to answer yes to the GenericSetup question.
You can add your own custom eggs to requirements.txt:
The instructions tell you to use file: prefixes. They lie. Don’t.
Your ZCML should be found by z3c.autoinclude.
Then you should be able to install your products throught the ZMI or by using the
migrate script described below.
Deploying to heroku
Make sure all your changes are committed to your Git repo. Then:
~/bin/heroku create --stack cedar
git push heroku master
Then wait. It should just work, if it doesn’t its probably a timeout. It takes
a long time to deploy 200+ eggs and heroku probably thinks your deployment has gone
wrong and times out.
So edit your requirements:
Commit and push to heroku.
That will build Zope without Plone, about half of the eggs that needed to be built.
Then you can uncomment the Plone dependency egg and push again to finish off.
You should now have a working Plonesite!
Re-rooting your portal
By default your actual site won’t be at / it will be at /Plone. We can fix
that with some old school Zope magic - note that the migrate command can set
this up for you automatically.
In the ZMI, in /Plone create a SiteRoot object. Default settings are fine.
In the ZMI, in / create a DTMLMethod containing:
<dtml-if "stack and stack[-1]=='zmi'">
In the ZMI, at / create an AccessRule and point it at the DTMLMethod we
Now any requests for /foo will be handled by /Plone/foo and any requests
for /zmi/manage will be handled by /manage. Success.
Maintaining your app
You can look at your looks with the built in heroku log tool:
You can get an interpreter pointed at your database with the debug command:
./bin/heroku run ./bin/debug
You can run a script in your git repo using the run command:
./bin/heroku run ./bin/run scripts/myscript.py