Bradezone

Reception. Observation. Perception. Emotion.

Pagoda Boxen

Allow me to reveal an inside secret between those of us who program and develop websites: we hate server administration! If you don’t know what server administration is, imagine your smoke alarm is blaring, and the only way to silence it is to locate a granule of sand somewhere in your spice rack, but the only way to locate the granule is to give specific instructions to a small child, because only his hand is tiny enough to dig through the various spices, and anyway you’re too busy fielding phone calls from irate neighbors who are strongly annoyed by all the racket.

PagodasSome people (bless their hearts) manage to get a weird adrenaline rush from this scenario. But the rest of us simply want to make websites and applications without getting caught up in stressful server minutiae. Enter Pagoda Box. Those of us who work mostly with PHP can now deploy our apps and sites to the outside world seamlessly, a luxury once afforded only to the snooty kids and their Heroku. Having worked with Pagoda Box for several months now, I am ready to offer some Pro-Tips™ that will knock your socks off (and possibly your mittens too).

Pagoda Box charges a certain amount of money for each “live” application, but what if you have several small websites that don’t require many resources? Can you combine them under one moderately priced application? YES YOU CAN. With the combined powers of .htaccess, .gitignore, and the mystical Boxfile, you too can achieve multisite triumph. I have tested this configuration with sites developed in CakePHP, Drupal, WordPress, and plain ol’ PHP, each of which requires slightly different treatment. Here are the necessary revisions:

Boxfile

web1:
  php_session_save_handler: redis
  php_session_save_path: "tcp://tunnel.pagodabox.com:6379"
  php_extensions:
    - apc
    - curl
    - gd
    - mbstring
    - mysql
    - pdo_mysql
    - redis
    - uploadprogress
  shared_writable_dirs:
    - cakephp_site/app/tmp/logs
    - drupal_site/sites/drupal_url.com/files
    - wordpress_site/wp-content/uploads
  after_build:
    - "cp .htaccess-pagoda .htaccess"
    - "cp index-pagoda.php index.php"
    - "cp cakephp_site/app/Config/core-pagoda.php cakephp_site/app/Config/core.php"
    - "cp cakephp_site/app/Config/database-pagoda.php cakephp_site/app/Config/database.php"
    - "cp wordpress_site/wp-config-pagoda.php wordpress_site/wp-config.php"

.htaccess-pagoda

<IfModule mod_rewrite.c>
RewriteEngine on

# CakePHP
RewriteCond %{HTTP_HOST} ^cakephp_url.com$
RewriteRule ^$ cakephp_site/app/webroot/ [L]
RewriteCond %{HTTP_HOST} ^cakephp_url.com$
RewriteRule .* cakephp_site/app/webroot/$0 [L]

# Drupal
RewriteCond %{HTTP_HOST} ^drupal_url.com$
RewriteRule ^$ drupal_site/index.php [L]
RewriteCond %{HTTP_HOST} ^drupal_url.com$
RewriteCond %{DOCUMENT_ROOT}/drupal_site%{REQUEST_URI} -f
RewriteRule .* drupal_site/$0 [L]
RewriteCond %{HTTP_HOST} ^drupal_url.com$
RewriteRule .* drupal_site/index.php?q=$0 [QSA,L]

# WordPress
RewriteCond %{HTTP_HOST} ^wordpress_url.com$
RewriteRule .* wordpress_site/$0 [L]

# Static
RewriteCond %{HTTP_HOST} ^static_url.com$
RewriteCond %{DOCUMENT_ROOT}/static_site%{REQUEST_URI} -f
RewriteRule .* static_site/$0 [L]

</IfModule>

.gitignore

*/app/tmp/*
*/app/Config/core.php
*/app/Config/database.php

*/sites/*/files
*/sites/*/private

*/wp-content/uploads
*/wp-config.php

Got all that? Cool, let’s discuss. In Boxfile, the two lines beginning with php_session_save are optional but recommended. The php_extensions are simply the ones required by one or more of the frameworks we are using, but you are mostly free to tweak these as you see fit.

The shared_writable_dirs section is where things start to get important. These directories should be familiar to you if you have worked with these frameworks before—they can also be tweaked if necessary, but for the most part these are the typical directories where logs or uploaded files are stored (and thus not version-controlled in the underlying Git project). Note that Drupal sites require the name of the main site directory and the URL-based subdirectory.

The after_build section is the other important piece. Here we are moving certain files in the repository when the project is deployed to the server. I prefer to keep my local copy of .htaccess separate from the rules that are specific to Pagoda Box, so that’s why I create another file called .htaccess-pagoda which is renamed to .htaccess once the project is deployed. The same idea applies to index-pagoda.php, which simply contains a redirect to the site of my choice in case someone happens to access the site via its pagodabox.com URL. The other lines are simply copying the relevant configuration files for the CakePHP and WordPress sites. Drupal conveniently allows for domain-based directories with their own configuration files, so we can keep all of them in the repository.

Next up is the .htaccess-pagoda file, which is really the most crucial piece (and required the most trial and error as I slowly discovered the proper way to set it up). I could spend a lot of time talking about the various rewrite rules and their effect, but maybe you should just either trust them or study them closely based on your own level of curiosity. I can tell you that the Drupal section was a bear to figure out, especially for the URL’s generated by the Overlay module. Also note the difference between the pieces ending in “_site” and “_url”—the first applies to the directory name in your project where the site is stored, while the second applies to the live URL of that site.

Last but not least is the .gitignore file. These lines should be somewhat familiar if you have developed sites with these frameworks under version control. We are simply telling Git not to track certain temp files, log files, or config files. The asterisk at the beginning of each line allows us to apply these rules once, no matter how many sites exist in our project for each framework. But you are free to be more precise if you want. You will also likely have additional ignore rules based on your operating system and IDE. Note that local configuration files are often ignored so that we can copy server-specific configuration files in their place as specified in Boxfile.

But Wait, There’s More

This is all great and wonderful for redirecting URL requests to the appropriate directories within our project, but there are a few settings within each site directory that need to be set properly as well, mainly so we can use the same database for each website. In each CakePHP site, open app/Config/core-pagoda.php (which is mainly just a copy of core.php with “debug” set to 0) and add the following line:

Configure::write('App.base', '');

Also set the $prefix variable to something unique. Then open app/Config/database-pagoda.php and set a unique prefix value here as well. Each table that belongs to this website will need to begin with this prefix.

For Drupal sites, open the sites/drupal_url.com/settings.php file (where drupal_url.com is the live site’s URL) and add a prefix to the $databases array. Also uncomment and set the $base_url variable to the live site’s URL.

For WordPress sites, open wp-config-pagoda.php (again, basically a copy of wp-config.php with debug turned off) and set the $table_prefix variable. Voila, you are ready to rock.

Alright, take a deep breath, because this odyssey is finally concluded. While all these settings were somewhat tricky to discover, the payoff is more than worth it. I can now take advantage of everything Pagoda Box has to offer, but group my smaller sites together under one paid “application.” Server administration (and its heart-stopping alarms) can now be considered a thing of the past.

No Comments

Leave a Comment