Heroku buildpack: WordPress on Heroku
See also
Heroku now (2015) supports PHP in the standard stack.
WordPress on Heroku
This is a Heroku buildpack for runningIt uses this WordPress project template to bootstrap a highly tuned WordPress site built on the following stack:
nginx
- Nginx for serving web content. Built specifically for Heroku. See compile options.php
- PHP-FPM for process management. See compile options.wordpress
- Downloaded directly from wordpress.org.MySQL
- ClearDB for the MySQL backend.Sendgrid
- Sendgrid for the email backend.MemCachier
- MemCachier for the memcached backend.
You can see a live demo at WordPress on Heroku.
Getting started in 60 seconds
Fork and rename the WordPress project template.
Let's clone the repository for a new blog, 99catfacts.com
$ git clone git://github.com/your_name/wordpress-on-heroku.git 99catfacts.com
Create WordPress on Heroku.
$ cd 99catfacts.com
$ heroku create -s cedar
$ heroku config:add BUILDPACK_URL=https://github.com/mchung/heroku-buildpack-wordpress.git
Don't have the Heroku Toolbelt installed? Follow these quickstart instructions. Takes about 2 minutes.
Deploy your WordPress site to Heroku.
$ git push heroku master
...
-----> Heroku receiving push
-----> Fetching custom git buildpack... done
-----> WordPress app detected
.
[...]
.
-----> Discovering process types
Procfile declares types -> (none)
Default types for WordPress -> web
-----> Compiled slug size: 33.7MB
-----> Launching... done, v7
Open your new WordPress site in a web browser.
$ heroku apps:open
Happy? Add your site to the growing list of WordPress sites runnning on Heroku.
Overview
The buildpack bootstraps a WordPress site using the mchung/wordpress-on-heroku project template. That repo contains everything required to run your own WordPress site on Heroku.
There are several files available in config
for configuring your new WordPress site.
βββ config # Your config files goes here.
βββ public # The public directory
βΒ Β βββ wp-content # WordPress themes and plugins
βΒ Β βββ plugins
βΒ Β βββ themes
βββ vendor # Config files for vendored apps
βββ nginx
βΒ Β βββ conf # nginx.conf + your site.conf
βββ php
βββ etc # php.ini & php-fpm.conf
When you deploy WordPress to Heroku, everything in config
is copied over to Heroku. You can configure your blog by making changes to these files.
A few WordPress environment variables can be controlled via Heroku using heroku config:set
:
FORCE_SSL_LOGIN
FORCE_SSL_ADMIN
WP_CACHE
DISABLE_WP_CRON
WORDPRESS_DIR
, see Specifying WordPress installation directoryWORDPRESS_VERSION
, see VERSIONS
To add a Heroku environment variable:
heroku config:set GOOG_UA_ID=UA=1234777-9
See wp-config.php
and documentation from WordPress for details.
Enabling and configuring the following WordPress plugins will also speed up WordPress on Heroku significantly.
heroku-sendgrid
- Configures phpmailer to send SMTP email with Sendgrid.heroku-google-analytics
- Configures Google Analytics to display on your WordPress site.- GOOG_UA_ID=UA-9999999
wpro
- Configures WordPress to upload everything to S3.batcache
- Configures WordPress to use memcached for caching.memcachier
- Use a modern memcached plugin.cloudflare
- OPTIONAL, but very awesome.- If Cloudflare is installed, the plugin configures WordPress to play nicely with CloudFlare. It sets the correct IP addresses from visitors and comments, and also protects WordPress from spammers.
- Keep in mind that the free version doesn't support SSL, so you'll need to set both
FORCE_SSL_ADMIN
andFORCE_SSL_LOGIN
to false in order to login.
Usage
Creating your WordPress site on Heroku
$ git clone git://github.com/username/wordpress-on-heroku.git myblog
$ cd myblog
$ heroku create -s cedar
$ heroku config:add BUILDPACK_URL=https://github.com/mchung/heroku-buildpack-wordpress.git
$ git push heroku master
Adding a custom domain name
$ heroku domains:add marcchung.org
$ heroku domains:add www.marcchung.org
Note: Adding a domain still requires some DNS setup work. Basically you'll want to do something like this:
ALIAS marcchung.org -> proxy.herokuapp.com
CNAME www.marcchung.org -> proxy.herokuapp.com
Adding a theme
$ cp -r appply config/public/wp-content/themes/
$ git add .
$ git commit -m "New theme"
$ git push heroku master
Adding a plugin
$ cp -r google-analytics config/public/wp-content/plugins/
$ git add .
$ git commit -m "New plugin"
$ git push heroku master
Plugins and themes must be activated via the Plugins panel.
Adding custom secret keys to wp-config.php
Use the WordPress.org secret-key service to override the default ones in wp-config.php
.
Configuring cron
By default, wp-cron is fired on every page load and scheduled to run jobs like future posts or backups. This buildpack disables wp-cron so that visitors don't have to wait to see the site.
Heroku allows you to trigger wp-cron from their scheduler.
$ heroku addons:add scheduler:standard
# Visit the Heroku scheduler dashboard and add a new task:
./bin/cron.sh
Alternatively, you may also re-enable wp-cron.
$ heroku config:set DISABLE_WP_CRON=false
Enable system access
The alternative PHP cache and a generic PHPINFO page is available at /apc.php and /phpinfo.php.
$ heroku config:set ENABLE_SYSTEM_DEBUG=true
$ heroku config:set SYSTEM_USERNAME=admin
$ heroku config:set SYSTEM_PASSWORD=secret123
# Visit /apc.php or /phpinfo.php
/status.html
Remove the PHP-FPM status page Delete the directive from nginx.conf.erb
.
favicon.ico
drop one into public
Add a See #22 for details.
Specifying WordPress installation directory
Specifying a WordPress installation directory may help local development as you can just unzip wordpress into a subdirectory and .gitignore that folder.
$ heroku config:set WORDPRESS_DIR=mywordpress
wp-config.php:
define( 'WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'].'/wp-content' );
define( 'WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] .'/wp-content' );
define('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] . '/mywordpress');
Choosing specific versions of vendored packages
See VERSIONS for how to pick specific versions of Nginx, PHP, and WordPress
Workflow (optional)
By keeping your changes separate, it'll be easier to pull in changes from the WordPress site template.
Assign a remote upstream
$ git remote add upstream https://github.com/your_name/wordpress-on-heroku.git
Track changes in a separate branch called production
.
$ git checkout -B production
$ git push heroku production:master
# This keeps upstream (my) changes separate from (your) blog changes.
Pull changes from upstream into master
.
$ git co master
$ git pull
$ git co production
$ git merge master
Pull changes from upstream into production
.
$ git pull --rebase upstream master
How fast is this?
Pretty freaking fast.
System setup
- Single Heroku dyno
- Default WordPress installation
- Default twentytwelve theme
- Caching turned up
- Cron disabled
- Memcachier + ClearDB
Here are some benchmarks from Google PageSpeed, Blitz.io, and Web Page Test.
Google PageSpeed
Results from PageSpeed Insights: 94/100
blitz.io
Results from a blitz.io rush
Over 200 page views per second with less than 100ms response time sustained for a minute.
Web Page Performance Test
These tests are periodically rerun on WordPress on Heroku.
But doesn't Heroku only run Ruby applications?
Not anymore. Heroku's latest offerings (See Celadon Cedar stack) makes it easy (well, easyish) for developers to install and run any language, or service.
Constraints with Heroku
- End-users cannot upload media assets to Heroku. WORKAROUND: Enable
wpro
and use that plugin to upload media assets to S3 instead. - End-users cannot update themes or plugins from the admin page. WORKAROUND: Add them to
config/public/wp-content/themes
orconfig/public/wp-content/plugins
then push to Heroku.
Security disclosure
Each time WordPress is deployed, Heroku will fetch the latest buildpack from GitHub and execute the instructions in compile
and deploy
. This buildpack will download the latest precompiled versions of Nginx, PHP, and WordPress from my personal S3 bucket then add in config files from the config
directory.
Hacking and Contributing
Not comfortable downloading and running a copy of someone else's PHP or Nginx executables? Not a problem! The support
directory also contains a handful of compilation and deployment scripts to automate several processes, which are currently used for maintenance and repo management.
package_nginx
- Used to compile and upload the latest version of Nginx to S3.package_php
- Used to compile and upload the latest version of PHP to S3.wordup
- Really useful helper script for creating and destroying WordPress sites.
TODO
- End-users shouldn't be able to do things that aren't supported on Heroku. Write plugins to hide everything.
- Integrate New Relic.
- CDN support.
- Combine CSS/JS files
Authors and Contributors
- Marc Chung - Follow @mchung on GitHub and also @heisenthought on Twitter
- Oskari Okko Ojala - @okko on GitHub, @okko on Twitter
- Luis Herranz - @LuisHerranz on Github, @luisherranz on Twitter
- Matt Mullenweg - @m on Github, @photomatt on Twitter
Thanks
Thanks for reading this all the way through.
If you use this buildpack in production, please update the list of WordPress sites running on Heroku.
License
The MIT License - Copyright (c) 2013 Marc Chung