This is a template for installing and running WordPress on Heroku with a focus on speed and security while using the official Heroku stack.
The repository is built on top of the following technologies.
- nginx - For serving web content.
- HHVM - A virtual machine designed to serve Hack and PHP.
- MySQL - Provided by the ClearDB add-on.
- Memcached - Provided by the MemCachier add-on.
- Composer - A dependency manager to make installing and managing plugins easier.
In additon repository comes bundled with the following plugins.
- SASL object cache - For running with MemCachier add-on
- Batcache - For full page output caching
- SSL Domain Alias - For sending SSLed traffic to a different domain (needed to send WP admin traffic to Heroku over SSL directly.)
- Authy Two Factor Auth
- Jetpack
- SendGrid
- WP Read-Only
WordPress and most included plugins are installed by Composer on build. To add new plugins or upgrade versions of plugins simply update the composer.json
file and then generate the composer.lock
file with the following command locally:
$ composer update --ignore-platform-reqs
To customize the site simply place files into /public
which upon deploy to Heroku will be copied on top of the standard WordPress install and plugins specified by Composer.
Clone the repository from Github
$ git clone git://github.com/xyu/heroku-wp.git
With the Heroku gem, create your app
$ cd heroku-wp
$ heroku create
> Creating strange-turtle-1234... done, stack is cedar
> http://strange-turtle-1234.herokuapp.com/ | git@heroku.com:strange-turtle-1234.git
> Git remote heroku added
Add a database to your app
$ heroku addons:create cleardb:ignite
> Adding cleardb:ignite on strange-turtle-1234... done, v2 (free)
> Use `heroku addons:docs cleardb:ignite` to view documentation.
Add memcache to your app
$ heroku addons:create memcachier:dev
> Adding memcachier:dev on strange-turtle-1234... done, v3 (free)
> MemCachier: added. Your credentials may take up to 3 minutes to sync to our servers.
> Use `heroku addons:docs memcachier:dev` to view documentation.
Add unique keys and salts to your Heroku config
$ heroku config:set\
WP_AUTH_KEY="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_SECURE_AUTH_KEY="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_LOGGED_IN_KEY="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_NONCE_KEY="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_AUTH_SALT="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_SECURE_AUTH_SALT="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_LOGGED_IN_SALT="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"\
WP_NONCE_SALT="`dd if=/dev/random bs=1 count=96 2>/dev/null | base64`"
> Setting config vars and restarting strange-turtle-1234... done, v4
> WP_AUTH_KEY: ...
> WP_AUTH_SALT: ...
> WP_LOGGED_IN_KEY: ...
> WP_LOGGED_IN_SALT: ...
> WP_NONCE_KEY: ...
> WP_NONCE_SALT: ...
> WP_SECURE_AUTH_KEY: ...
> WP_SECURE_AUTH_SALT: ...
Create a new production branch for your app
$ git checkout -b production
Deploy to Heroku
$ git push heroku production:master
> Fetching repository, done.
> Counting objects: 5, done.
> Delta compression using up to 8 threads.
> Compressing objects: 100% (3/3), done.
> Writing objects: 100% (3/3), 650 bytes | 0 bytes/s, done.
> Total 3 (delta 2), reused 0 (delta 0)
>
> -----> PHP app detected
> -----> Detected request for HHVM 3.1.0 in composer.json.
> -----> Setting up runtime environment...
> - HHVM 3.1.0
> - Apache 2.4.9
> - Nginx 1.4.6
> -----> Installing dependencies...
> Composer version 1d8b627b57a5a0fe8ceaef25534d9da8bd7cb301 2014-06-28 18:45:20
> Loading composer repositories with package information
> Installing dependencies from lock file
> - Installing fancyguy/webroot-installer (1.1.0)
> Loading from cache
>
> - Installing composer/installers (v1.0.14)
> Loading from cache
>
> - Installing wordpress/wordpress (3.9.1)
> Loading from cache
>
> - Installing wpackagist-plugin/authy-two-factor-authentication (2.5.4)
> Loading from cache
>
> - Installing wpackagist-plugin/jetpack (3.0.2)
> Loading from cache
>
> - Installing wpackagist-plugin/sendgrid-email-delivery-simplified (1.3.2)
> Loading from cache
>
> - Installing wpackagist-plugin/wpro (1.0)
> Loading from cache
>
> Generating optimized autoload files
> -----> Building runtime environment...
> -----> Discovering process types
> Procfile declares types -> web
>
> -----> Compressing... done, 61.1MB
> -----> Launching... done, v70
> http://strange-turtle-1234.herokuapp.com/ deployed to Heroku
>
> To git@heroku:strange-turtle-1234.git
> * [new branch] production -> master
After deployment WordPress has a few more steps to setup and thats it!
Installing and configuring the items below are not essential to get a working WordPress install but will make your site more functional and secure.
Heroku provides an SSL'ed endpoint to each app for free via the APP_NAME.herokuapp.com domain. To use this domain for all logged in sessions and to protect your login credentials simply set the SSL domain in the config vars. (Replace APP_NAME with the name of your Heroku app.)
$ heroku config:set SSL_DOMAIN="APP_NAME.herokuapp.com"
By default WordPress will connect to the database unencrypted which is a potential problem for a cloud based installs where the database and application servers may transfer data over unsecured connections. ClearDB provides SSL keys and certs for the database that's setup and it's highly advisable to use them to secure your database connection.
-
Go to your Heroku Dashboard and click on your heroku-wp app.
-
Click on the "ClearDB MySQL Database" add-on.
-
Scroll to the bottom of the page and download the "ClearDB CA Certificate", "Client Certificate", and "Client Private Key" in the "PEM Format".
-
Generate Heroku compatible RSA keys from the key file downloaded:
$ openssl rsa -in cleardb_id-key.pem -out cleardb_id-key.rsa.pem
-
Add the keys to the config vars of your app:
$ heroku config:set \ CLEARDB_SSL_CA="$(cat /path/to/cleardb-ca.pem)" \ CLEARDB_SSL_CERT="$(cat /path/to/cleardb_id-cert.pem)" \ CLEARDB_SSL_KEY="$(cat /path/to/cleardb_id-key.rsa.pem)" > Setting config vars and restarting strange-turtle-1234... done, v12 > CLEARDB_SSL_CA: ... > CLEARDB_SSL_CERT: ... > CLEARDB_SSL_KEY: ...
WP Read-Only plugin is included in the repository allowing the use of S3 for media uploads.
- Activate the plugin under 'Plugins', if not already activated.
- Input your Amazon S3 credentials in 'Settings'->'WPRO Settings'.
SendGrid plugin is included in the repository allowing the use of SendGrid for emails.
Add SendGrid to your app
$ heroku addons:create sendgrid:starter
> Adding sendgrid:starter on strange-turtle-1234... done, v11 (free)
> Use `heroku addons:docs sendgrid:starter` to view documentation.
Activate the plugin
Because a file cannot be written to Heroku's file system, updating and installing plugins or themes should be done locally and then pushed to Heroku. Even better would be to use Composer to install plugins so that version control and upgrading is simply a matter of editing the composer.json
file and bumping the version number.
In most cases you may want to have your WordPress blog in a language different than its default (US English). In that case all you need to do is download the .mo and .po files for your language from wpcentral.io/internationalization and place them in the
languages
directory you'll create under public/wp-content
. Then you should commit changes to your local branch and push them to your heroku remote. After that, you'll be able to select the new language from the WP admin panel.
Updating your WordPress version is just a matter of merging the updates into the branch created from the installation.
$ git pull # Get the latest
Using the same branch name from our installation:
$ git checkout production
$ git merge master # Merge latest
$ git push heroku production:master
WordPress needs to update the database. After push, navigate to:
http://your-app-url.herokuapp.com/wp-admin
WordPress will prompt for updating the database. After that you'll be good to go.
Heroku allows you to add custom domains to your site hosted with them. To add your custom domain, enter in the follow commands.
$ heroku domains:add www.example.com
> Added www.example.com as a custom domain name to myapp.heroku.com
A Vagrant instance to run Heroku WP is included. To get up and running:
- Install vagrant http://www.vagrantup.com/downloads
- Install virtual box https://www.virtualbox.org/wiki/Downloads
- Install virtual box extension pack https://www.virtualbox.org/wiki/Downloads
cd
into app root directory and run$ vagrant up
(should start setting up virtual env. go grab some ☕, takes about 10 minutes)
Once Vagrant provisions the VM you will have Heroku WP running locally at http://herokuwp.local/
. On first load, it should bring you to the wordpress install page. If the site is not accessible in the browser, you might need to add 192.168.50.100 herokuwp.local
to your hosts file.
As a convenience both the /public
dir and /composer.lock
file will be monitored by the VM. Any changes to either triggers a rebuild process which will result in /public.built
(the web root) being updated.
In order to connect you will need to change the MySQL config to work with 0.0.0.0 IP address instead of localhost.
- SSH into the vm
$ vagrant ssh
- Open the config file
$ sudo vim /etc/mysql/my.cnf
- Change the IP address from 127.0.0.1 to 0.0.0.0
Then you can connect using SSH with the following paramaters:
- SSH hostname: 127.0.0.1:2222
- SSH username: vagrant
- SSH password: vagrant
- MySQL hostname: 127.0.0.1
- MySQL port: 3306
- mysql user: root
- mysql password: password
Sometimes after vagrant up
from a aborted state, the vm does not start correctly and the site is not accessible.
- Provision the machine
vagrant provision
to force it to start back up again