Drupal 8 DevOps: Leveraging OpenShift Online PaaS
Note: all, or parts of this article may be out of date
In my free time recently, I've been designing and developing a little Drupal 8 site that I'd like to bring online. From the start, I knew I'd need a decent web host with all the fixins' Drush, Git and most of all, PHP 5.4 as that's the minimum required for Drupal 8.
The first place I thought of was Pantheon but as it turns out, as of this writing, they only have PHP 5.3. I also took a look at Linode but admittedly I'm not a huge fan as it requires a fair amount of server setup and management.
Enter, OpenShift Online, Red Hat's scalable PaaS or Platform as a Service in the cloud. OpenShift is an all in one development, hosting and deployment platform which supports PHP, Java, Node.js, Python and more. The idea behind this is to let the developer / designer focus on what matters, code and apps rather than tedious server administration and management. For me, this is a huge win and best of all, Red Hat has a basic plan that gets you everything you need for free.
Apps, Gears, and Cartridges
OpenShift's terminology takes a little getting used to but I'll break it down and try to define what's what. Think of an Application as just an instance of a website. Gears are an allocated amount of server resources ranging in size from small to large for scalability. Think of a Cartridge as an a la carte style add on for your app. Need Jenkins, phpMyAdmin or cron? No problem, just browse the list of available cartridges or add one from a URL and OpenShift does all the installation work for you.
Build Your App
My workflow involves developing a website locally and then bringing it into dev / production via Git. With OpenShift, this is no different, however with a few caveats. Normally you'd use .gitignore for persistent non-tracked data files, i.e. Drupal's files directory and then these untracked items can just sit on your server happy to go about their business. However, with OpenShift, anything not in Git gets deleted on the next push regardless of .gitignore. OpenShift handles the untracked files via their data directory - ${OPENSHIFT_DATA_DIR}
- and symbolic links. So while .gitignore is fine for your local, you'll need to do a little wrangling on the OpenShift end and I'll show you how.
We can automate file handling by designing a custom deploy script. This can have any command you'd normally execute directly on the server but with added logic to test for certain conditions, e.g whether a file or folder already exists. I wrote a full scale deploy script (Gist) from scratch which turned out to be extremely challenging and a lot of fun. The script executes on each git push.
Getting Started
First, create an account at OpenShift Online, login and create your first app. The best way is to simply click the "Add Application" button in your app console and then search for PHP. I added PHP 5.4 since I was going to use Drupal 8. You'll be asked to name your app and can follow the simple steps there. This creates your base app which is now up and running with the flavor of PHP you chose.
Here's the other OpenShift cartridges I use in my Drupal 8 app.
{.styled-list}There's also an option to install PHPmyAdmin as well. Note for Drush, enter the URL in the Cartridge UI page, i.e. "Install your own cartridge" You can also use Red Hat's RHC language to setup Cartridges from your local, it does require Ruby. I'm sure I'll get in to that next, I just have not had time to work on it yet but it looks pretty cool.
Local Setup
Once you've got all your cartridges installed, you can now pull from Git and get your local dev environment setup, ready to push your code up. Here's a general outline of what I do in Terminal that woks well.
# Within your project directory:
$ git clone [git_url] [project_site]
$ cd [project_site]
# Remove OpenShift's default index file:
$ rm index.php
# Now download drupal (latest 8.x Alpha)
$ drush dl drupal-8.0-alpha11
# Rename the drupal folder to "php"
$ mv drupal-8.0-alpha11 php
```
<p>With the above setup, you'll note that we rename the Drupal directory to php. That's because OpenShift best serves web files if you have a sub directory named php. They also automatically alias this for you so you don't see php in the URL. Here's how my local directory structure looks once I'm done.</p>
```bash
|\_**\_project_directory
| |\_\_**project_site
| | |\_**\_.git
| | |\_\_**.openshift
| | | |\_**\_action_hooks
| | | | |\_\_**build
| | | | |\_**\_deploy
| | | | |\_\_**README.md
| | |\_**\_php
| | | |\_\_**[drupal-files-here]
```
## Push and Deploy
<p>To get around the persistent non-tracked files / folders issue, we can implement the deploy script I mentioned above in our local OpenShift repo that runs on each git push. Essentially this creates a <em>sites/default/files</em> directory in your Openshift data directory or <code>${OPENSHIFT_DATA_DIR}</code> and then symlinks it to your repo or <code>${OPENSHIFT_REPO_DIR}</code> In addition, it copies <em>default.settings.php</em> as <em>settings.php</em> to the data directory and proceeds to symlink that as well. The deploy script should be located at:</p>
```bash
.openshift/action_hooks/deploy
```
<p>My deploy script has conditional statements to insure that already existing files and folders in the <code>${OPENSHIFT_DATA_DIR}</code> don't get overwritten. For your deploy script to be recognized, be sure to give it appropriate permissions. Once you set with all this, it's time to commit and push for the first time.</p>
```bash
# Commit your changes and push to OpenShift
$ git commit -a -m 'Initial commit'
$ git push
```
<p>On first push, I noticed that my deploy script did not run and that was a real mystery. In the end, it turned out to be a permissions issue on the file. It was set to 644 so a <em>chmod</em> to 777 took care of it. Once git has been pushed and the deploy script runs, here is what my OpenShift <code>/repo/php/sites/all/files</code> directory looks like:</p>
```bash
default.settings.php
files -> /var/lib/openshift/[app_id]/app-root/data/sites/default/files
settings.php -> /var/lib/openshift/[app_id]/app-root/data/sites/default/settings.php
```
<p>Once you either import your database or install Drupal, you'll want to reset the permissions on settings.php in the data directory to not be writable.</p>
## A note about settings.php
<p>I could not find much documentation with regard to Drupal's settings.php and OpenShift. Suffice it to say, I found this snippet. (See further below with regard to QuickStarts.)</p>
```php
if (array_key_exists('OPENSHIFT_APP_NAME', $_SERVER)) {
$src = $_SERVER;
} else {
$src = $_ENV;
}
$databases = array (
'default' =>
array (
'default' =>
array (
'database' => $src['OPENSHIFT_APP_NAME'],
'username' => $src['OPENSHIFT_MYSQL_DB_USERNAME'],
'password' => $src['OPENSHIFT_MYSQL_DB_PASSWORD'],
'host' => $src['OPENSHIFT_MYSQL_DB_HOST'],
'port' => $src['OPENSHIFT_MYSQL_DB_PORT'],
'driver' => 'mysql',
'prefix' => '',
),
),
);
```
<p>The code above use OpenShift <em>Environment Variables</em> to connect to your database, this is the preferred method, especially if you build a scaleable app. If you want to print out all the variables, you can SSH in and simply do <code>env</code> in terminal or you can add a build file in your action_hooks directory with the line of code <code>export</code>. The next time you <code>git push</code>, you'll see all these vars print out. Pretty cool!</p>
## QuickStarts Alternative
<p>As an alternative to the process I've outlined above and to get up and running super fast on OpenShift, you can choose from a variety of <a href="https://www.openshift.com/quickstarts">Quickstarts</a> that are offered, these are one click app installs pre-configured with the cartridges you need. An eclectic list is offered appealing to any designer or developer including Ghost, WordPress, Ruby, JBoss and of course Drupal. In the Drupal category sits a Drupal 8 app ready to deploy.</p>
<p>With this method, you'll want to create symlinks from your repo to the themes and modules directory of Drupal. From what I can tell, this method is not meant for a ton of customization and is probably more akin to something like simplytest.me. <a href="https://twitter.com/Srdjan_Popovic">@Srdjan_Popovic</a> blogged about this method for a Drupal 7 QuickStart and you check out his <a href="http://bortolete-popovic.com/blog/using-git-to-add-custom-code-to-drupal-7-instant-app-on-openshift">post</a>). What he outlines could be adapted for the Drupal 8 QuickStart as well. I tested Popovic's method out and it worked well.</p>
## Is PaaS the Future?
<p>In the end, OpenShift seems to have a lot of promise, especially with a Drupal 8 beta, RC and final release not too far around the corner. Compared to a cPanel hosting paradigm, OpenShift feels modern, fresh and the way forward. It seems like they've adapted to the needs of and the way in which developers are now working.</p>
## Resources
- ["Getting Started With Openshift", a free ebook written by Steve Pousty & Katie J. Miller](https://www.openshift.com/promotions/ebook)
- [OpenShift General Documentation](https://www.openshift.com/documentation)
- [OpenShift Technology Cartridges](https://www.openshift.com/developers/technologies)
- [OpenShift Environment Variables](https://www.openshift.com/developers/openshift-environment-variables)
- [Installing OpenShift RHC Client Tools](https://www.openshift.com/developers/rhc-client-tools-install)
- [Drupal 8 Quickstart](https://www.openshift.com/quickstarts/drupal-8)
- [Using Git to add custom code to Drupal 7 Instant App on OpenShift](http://bortolete-popovic.com/blog/using-git-to-add-custom-code-to-drupal-7-instant-app-on-openshift)
- [Drupal 8 beta on OpenShift ](https://github.com/phase2/drupal-quickstart)
{.styled-list}