<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Blog entries tagged cloud :: mwop.net</title>
  <updated>2012-12-30T09:52:00-06:00</updated>
  <generator uri="https://getlaminas.org" version="2">Laminas_Feed_Writer</generator>
  <link rel="alternate" type="text/html" href="https://mwop.net/blog/tag/cloud"/>
  <link rel="self" type="application/atom+xml" href="https://mwop.net/blog/tag/cloud/atom.xml"/>
  <id>https://mwop.net/blog/tag/cloud</id>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[OpenShift, Cron, and Naked Domains]]></title>
    <published>2012-12-30T09:52:00-06:00</published>
    <updated>2012-12-30T09:52:00-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2012-12-30-openshift-cron-and-naked-domains.html"/>
    <id>https://mwop.net/blog/2012-12-30-openshift-cron-and-naked-domains.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>As an experiment, I migrated my website over to <xhtml:a href="http://openshift.redhat.com">OpenShift</xhtml:a> yesterday. I've been
hosting a pastebin there already, and have found the service to be
both straightforward and flexible; it was time to put it to a more
thorough test.</xhtml:p>
<xhtml:p>In the process, I ran into a number of interesting issues, some
of which took quite some time to resolve; this post is both to help
inform other potential users of the service, as well as act as a
reminder to myself.</xhtml:p>
<xhtml:h2>Cron</xhtml:h2>
<xhtml:p>OpenShift offers a <xhtml:a href="http://en.wikipedia.org/wiki/Cron">Cron</xhtml:a> cartridge, which I was
excited to try out.<xhtml:sup id="ref-1"><xhtml:a href="#f1">1</xhtml:a></xhtml:sup></xhtml:p>
<xhtml:p>The basics are quite easy. In your repository's
<xhtml:code>.openshift</xhtml:code> directory is a <xhtml:code>cron</xhtml:code>
subdirectory, further divided into <xhtml:code>minutely</xhtml:code>,
<xhtml:code>hourly</xhtml:code>, <xhtml:code>daily</xhtml:code>, <xhtml:code>weekly</xhtml:code>, and
<xhtml:code>monthly</xhtml:code> subdirectories. You drop a script you want to
run into one of these directories, and push your changes
upstream.</xhtml:p>
<xhtml:p>The problem is: what if I want a job to run at a specific time
daily? or on the quarter hour? or on a specific day of the
week?</xhtml:p>
<xhtml:p>As it turns out, you can manage all of the above, just not quite
as succinctly as you would in a normal crontab. Here, for example,
is a script that I run at 5AM daily; I placed it in the
<xhtml:code>hourly</xhtml:code> directory so that it can test more
frequently:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash"><xhtml:span class="hljs-meta">#!/bin/bash</xhtml:span>
<xhtml:span class="hljs-keyword">if</xhtml:span> [ `date +%H` == <xhtml:span class="hljs-string">"05"</xhtml:span> ]
<xhtml:span class="hljs-keyword">then</xhtml:span>
    (
        <xhtml:span class="hljs-built_in">export</xhtml:span> PHP=/usr/<xhtml:span class="hljs-built_in">local</xhtml:span>/zend/bin/php ;
        <xhtml:span class="hljs-built_in">cd</xhtml:span> <xhtml:span class="hljs-variable">$OPENSHIFT_REPO_DIR</xhtml:span> ; 
        <xhtml:span class="hljs-variable">$PHP</xhtml:span> public/index.php phlycomic fetch all ; 
        <xhtml:span class="hljs-variable">$PHP</xhtml:span> public/index.php phlysimplepage cache clear --page=pages/comics 
    )
<xhtml:span class="hljs-keyword">fi</xhtml:span>
</xhtml:code></xhtml:pre>
<xhtml:p>And here's one that runs on the quarter-hour, placed in the
<xhtml:code>minutely</xhtml:code> directory:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash"><xhtml:span class="hljs-meta">#!/bin/bash</xhtml:span>
MINUTES=`date +%M`

<xhtml:span class="hljs-keyword">for</xhtml:span> i <xhtml:span class="hljs-keyword">in</xhtml:span> <xhtml:span class="hljs-string">"00"</xhtml:span> <xhtml:span class="hljs-string">"15"</xhtml:span> <xhtml:span class="hljs-string">"30"</xhtml:span> <xhtml:span class="hljs-string">"45"</xhtml:span>;<xhtml:span class="hljs-keyword">do</xhtml:span>
    <xhtml:span class="hljs-keyword">if</xhtml:span> [ <xhtml:span class="hljs-string">"<xhtml:span class="hljs-variable">$MINUTES</xhtml:span>"</xhtml:span> == <xhtml:span class="hljs-string">"<xhtml:span class="hljs-variable">$i</xhtml:span>"</xhtml:span> ];<xhtml:span class="hljs-keyword">then</xhtml:span>
        (
            <xhtml:span class="hljs-built_in">export</xhtml:span> PHP=/usr/<xhtml:span class="hljs-built_in">local</xhtml:span>/zend/bin/php ;
            <xhtml:span class="hljs-built_in">cd</xhtml:span> <xhtml:span class="hljs-variable">$OPENSHIFT_REPO_DIR</xhtml:span> ;
            <xhtml:span class="hljs-variable">$PHP</xhtml:span> public/index.php githubfeed fetch 
        )
    <xhtml:span class="hljs-keyword">fi</xhtml:span>
<xhtml:span class="hljs-keyword">done</xhtml:span>
</xhtml:code></xhtml:pre>
<xhtml:p>The point is that if you need more specificity, push the script
into the next more specific directory, and test against the time of
execution.</xhtml:p>
<xhtml:h2>Naked Domains</xhtml:h2>
<xhtml:p>Naked domains are domains without a preceding subdomain. In my
case, this means "mwop.net", vs. "www.mwop.net".</xhtml:p>
<xhtml:p>The problem that cloud hosting presents is that the IP address
on which you are hosted can change at any time, for a variety of
reasons. As such, you typically cannot use DNS A records to point
to your domain; the recommendation is to use a CNAME record that
points the domain to a "virtual" domain registered with your cloud
hosting provider.</xhtml:p>
<xhtml:p>However, most domain registrars and DNS providers do not let you
do this for a naked domain, particularly if you also have MX or
other records associated with that naked domain.</xhtml:p>
<xhtml:p>Some registrars will allow you to forward the A record to a
subdomain. I tried this, but had limited success; I personally
found that I ended up in an infinite loop situation when doing the
DNS lookup.</xhtml:p>
<xhtml:p>Another solution is to have a redirect in place for your naked
domain to the subdomain, which can then be a CNAME record.
Typically, this would require you have a web server under your
control with a fixed IP that then simply redirects to the
subdomain. Fortunately, there's an easier solution: <xhtml:a href="http://wwwizer.com/naked-domain-redirect">wwwizer</xhtml:a>. You simply
point your naked domain A record to the wwwizer IP address, and
they will do a redirect to your <xhtml:code>www</xhtml:code> subdomain.</xhtml:p>
<xhtml:p>I implemented wwwizer on my domain (which is why you'll see
"www.mwop.net" in your location bar), and it's been working
flawlessly since doing so.</xhtml:p>
<xhtml:h4>Private repositories</xhtml:h4>
<xhtml:p>I keep my critical site settings in a private repository, which
allows me to version them while keeping the credentials they hold
out of the public eye. This means, however, that I need to use
<xhtml:a href="https://help.github.com/articles/managing-deploy-keys">GitHub
deploy keys</xhtml:a> on my server in order to retrieve changes.</xhtml:p>
<xhtml:p>This was simple enough: I created an <xhtml:code>ssh</xhtml:code>
subdirectory in my <xhtml:code>$OPENSHIFT_DATA_DIR</xhtml:code> directory, and
generated a new SSH keypair.</xhtml:p>
<xhtml:p>The problem was telling SSH to <xhtml:em>use</xhtml:em> this key when
fetching changes.</xhtml:p>
<xhtml:p>The solution is to use a combination of <xhtml:code>ssh-agent</xhtml:code>
and <xhtml:code>ssh-add</xhtml:code>, and it looks something like this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash"><xhtml:span class="hljs-meta">#!/bin/bash</xhtml:span>
ssh-agent `ssh-add <xhtml:span class="hljs-variable">$OPENSHIFT_DATA_DIR</xhtml:span>/ssh/github-key &amp;&amp; (
    <xhtml:span class="hljs-built_in">cd</xhtml:span> <xhtml:span class="hljs-variable">$OPENSHIFT_DATA_DIR</xhtml:span>/config ; 
    git fetch origin ; 
    git rebase origin/mwop.net.config
)`
</xhtml:code></xhtml:pre>
<xhtml:p>After testing the above, I put this in a <xhtml:code>pre_build</xhtml:code>
script in my OpenShift configuration so that I can autoupdate my
private configuration on each build. However, I discovered a new
problem: when a build is being done, the <xhtml:code>ssh-agent</xhtml:code> is
not available, which means the above cannot be executed. I'm still
trying to find a solution.</xhtml:p>
<xhtml:h2>Fin</xhtml:h2>
<xhtml:p>I'm pretty happy with the move. I don't have to do anything
special to automate deployment, and all my cronjobs and deployment
scripts are now self-contained in the repository, which makes my
site more portable. While a few things could use more
documentation, all the pieces are there and discoverable with a
small amount of work.</xhtml:p>
<xhtml:p>I'll likely give some other PaaS providers a try in the future,
but for the moment, I'm quite happy with the functionality and
flexibility of OpenShift.</xhtml:p>
<xhtml:h4>Footnotes</xhtml:h4>
<xhtml:ul>
<xhtml:li><xhtml:sup id="f1"><xhtml:a href="#1">1</xhtml:a></xhtml:sup> Zend Server's JobQueue
can also be used as a cron replacement, but I was not keen on
exposing the job functionality via HTTP.</xhtml:li>
</xhtml:ul>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-12-30-openshift-cron-and-naked-domains.html">
OpenShift, Cron, and Naked Domains</xhtml:a> was originally published
<xhtml:time class="dt-published" datetime="2012-12-30T09:52:00-06:00">30
December 2012</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[OpenShift, ZF2, and Composer]]></title>
    <published>2012-11-01T15:25:00-05:00</published>
    <updated>2012-11-01T15:25:00-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2012-11-01-openshift-zf2-composer.html"/>
    <id>https://mwop.net/blog/2012-11-01-openshift-zf2-composer.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I was recently shopping around for inexpensive cloud hosting; I
want to try out a couple of ideas that may or may not have much
traffic, but which aren't suited for my VPS setup (the excellent
<xhtml:a href="http://servergrove.com/">ServerGrove</xhtml:a>); additionally,
I'm unsure how long I will maintain these projects. My budget for
this is quite small as a result; I'm already paying for hosting,
and am quite happy with it, so this is really for experimental
stuff.</xhtml:p>
<xhtml:p>I considered Amazon, Orchestra.io, and a few others, but was
concerned about the idea of a ~$50/month cost for something I'm
uncertain about.</xhtml:p>
<xhtml:p>When I asked in <xhtml:a href="irc://irc.freenode.net/zftalk.dev">#zftalk.dev</xhtml:a>, someone
suggested <xhtml:a href="http://openshift.redhat.com/">OpenShift</xhtml:a> as
an idea, and coincidentally, the very next day <xhtml:a href="http://www.zend.com/en/company/news/press/379_red-hat-expands-openshift-ecosystem-with-zend-partnership-to-offer-professional-grade-environment-for-php-developers">
Zend announced a partnership with RedHat surrounding OpenShift</xhtml:a>.
The stars were in alignment.</xhtml:p>
<xhtml:p>In the past month, in the few spare moments I've had (which
included an excellent OpenShift hackathon at ZendCon), I've created
a quick application that I've deployed and tested in OpenShift.
These are my findings.</xhtml:p>
<xhtml:h2>ZF2</xhtml:h2>
<xhtml:p>I didn't really have to do anything different to have <xhtml:a href="http://framework.zend.com/">zf2</xhtml:a> work; the standard
<xhtml:code>.htaccess</xhtml:code> provided in the skeleton application worked
flawlessly the first time (I've worked with some cloud environments
where this is not the case).</xhtml:p>
<xhtml:p>The only frustration I had was the default directory structure
OpenShift foists upon us:</xhtml:p>
<xhtml:pre><xhtml:code class="language-powershell hljs powershell" data-lang="powershell"><xhtml:span class="hljs-keyword">data</xhtml:span>/
libs/
misc/
php/
</xhtml:code></xhtml:pre>
<xhtml:p>This is not terrible, by any stretch. However, it's attempting
to dictate the application structure, which I'm not terribly happy
with — particularly as my structure may vary based on the framework
I'm using (or not!), and because I may already have a project
written that I simply want to deploy.</xhtml:p>
<xhtml:p>In particular, the <xhtml:code>php</xhtml:code> directory is galling — it's
simply the document root. Most frameworks I've used or seen call
the equivalent directory <xhtml:code>public</xhtml:code>, or <xhtml:code>web</xhtml:code>,
or <xhtml:code>html</xhtml:code> — but never <xhtml:code>php</xhtml:code> (in large part
because the only PHP file under the document root in most
frameworks is the <xhtml:code>index.php</xhtml:code> that acts as the front
controller). It would be nice if this were configurable.</xhtml:p>
<xhtml:p>This conflicts a bit with how a ZF2 app is structured. I ended
up doing the following:</xhtml:p>
<xhtml:ul>
<xhtml:li>Removed <xhtml:code>php</xhtml:code> and symlinked my <xhtml:code>public</xhtml:code>
directory to it.</xhtml:li>
<xhtml:li>Removed <xhtml:code>libs</xhtml:code> and symlinked my <xhtml:code>vendor</xhtml:code>
directory to it.</xhtml:li>
<xhtml:li>Removed <xhtml:code>misc</xhtml:code> as I had no need to it.</xhtml:li>
</xhtml:ul>
<xhtml:p>Nothing too big, thankfully — but problematic from the
perspective of, "I've already developed this app, but now I have to
make changes for it to work on a specific cloud vendor."</xhtml:p>
<xhtml:h2>Composer</xhtml:h2>
<xhtml:p>My next question was how to use <xhtml:a href="http://getcomposer.org/">Composer</xhtml:a> during my deployment
process, and some some googling <xhtml:a href="https://openshift.redhat.com/community/content/support-for-git-clone-on-the-server-aka-support-php-composerphar">
found some answers for me</xhtml:a>.</xhtml:p>
<xhtml:p>Basically, I needed to create a <xhtml:code>deploy</xhtml:code> task that
does two things:</xhtml:p>
<xhtml:ul>
<xhtml:li>Unset the <xhtml:code>GIT_DIR</xhtml:code> environment variable. Evidently,
the build process operates as part of a git hook, and since
Composer often uses git repositories, this can lead to
problems.</xhtml:li>
<xhtml:li>Change directory to <xhtml:code>OPENSHIFT_REPO_DIR</xhtml:code>, which is
where the application root (not document root!) lives.</xhtml:li>
</xhtml:ul>
<xhtml:p>Once I did those, I could run my normal composer installation.
The <xhtml:code>deploy</xhtml:code> task looks like this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash"><xhtml:span class="hljs-meta">#!/bin/bash</xhtml:span>
<xhtml:span class="hljs-comment"># .openshift/action_hooks/deploy</xhtml:span>
( <xhtml:span class="hljs-built_in">unset</xhtml:span> GIT_DIR ; <xhtml:span class="hljs-built_in">cd</xhtml:span> <xhtml:span class="hljs-variable">$OPENSHIFT_REPO_DIR</xhtml:span> ; /usr/<xhtml:span class="hljs-built_in">local</xhtml:span>/zend/bin/php composer.phar install )
</xhtml:code></xhtml:pre>
<xhtml:p>This leads into my next topic.</xhtml:p>
<xhtml:h2>Deployment</xhtml:h2>
<xhtml:p>First off, as you probably guessed from that last secton, there
<xhtml:strong>are</xhtml:strong> hooks for deployment — it doesn't have to be
simply git. I like this, as I may have additional things I want to
do during deployment, such as retrieving and installing
site-specific configuration files, installing Composer-defined
dependencies (as already noted), etc.</xhtml:p>
<xhtml:p>Over all, this is pretty seamless, but it's not without issues.
I've been told that some of my issues are being worked on, so those
I won't bring up here. The ones that were a bit strange, and which
caught me by surprise, though, were:</xhtml:p>
<xhtml:ul>
<xhtml:li>Though the build process creates the site build from git, your
<xhtml:strong>submodules are not updated recursively</xhtml:strong>. This
tripped me up, as I was using <xhtml:a href="https://github.com/EvanDotPro/EdpMarkdown">EdpMarkdown</xhtml:a>, and
had installed it as a submodule. I ended up having to import it,
and its own submodule, directly into my project so that it would
work.</xhtml:li>
<xhtml:li>I installed the <xhtml:a href="http://www.mongodb.org/">MongoDB</xhtml:a>
cartridge. Ironically, it was not then enabled in Zend Server, and
I had to go do this. This should be turnkey.</xhtml:li>
<xhtml:li><xhtml:code>/usr/bin/php</xhtml:code> is not the same as
<xhtml:code>/usr/local/zend/bin/php</xhtml:code>. This makes no sense to me if
I've installed Zend Server as my base gear. Considering they're
different versions, this can be hugely misleading and lead to
errors. I understand there are reasons to have both — so simply be
aware that if you use the Zend Server gear, your tasks likely
should use <xhtml:code>/usr/local/zend/bin/php</xhtml:code>.</xhtml:li>
</xhtml:ul>
<xhtml:h2>The good parts?</xhtml:h2>
<xhtml:ul>
<xhtml:li><xhtml:a href="https://openshift.redhat.com/community/faq/i-have-deployed-my-app-but-i-don%E2%80%99t-like-telling-people-to-visit-myapp-myusernamerhcloudcom-how-c">
You can alias an application to a DNS CNAME</xhtml:a> — meaning you can
point your domain name to your OpenShift applications.
Awesome!</xhtml:li>
<xhtml:li>Simplicity of adding capabilities, such as Mongo, MySQL, Cron,
and others. In most cases, this is simply a "click on the button"
and it's installed and available.</xhtml:li>
<xhtml:li><xhtml:a href="http://www.zend.com/en/products/server">Zend
Server</xhtml:a>. For most PHP extensions, I can turn them on or off with
a few mouse clicks. If I want page-level caching, I don't have to
do anything to my application; I can simply setup some rules in the
Zend Server interface and get on with it, and enjoy tremendous
boosts to performance. I used to enjoy taming and tuning servers;
most days anymore, I just want them to work.</xhtml:li>
<xhtml:li><xhtml:a href="https://openshift.redhat.com/community/developers/remote-access">SSH</xhtml:a>
access to the server, with a number of commands to which I've been
given <xhtml:code>sudoer</xhtml:code> access. If you're going to sandbox
somebody, this is a fantastic way to do it. Oh, also: SSH tunnels
to services like Mongo and MySQL just work (via the
<xhtml:code>rhc-port-forward</xhtml:code> command).</xhtml:li>
</xhtml:ul>
<xhtml:h2>Summary</xhtml:h2>
<xhtml:p>Over all, I'm quite pleased. While it took me a bit to find the
various incantations I needed, the service is quite flexible. For
my needs, considering I'm doing experimental stuff, the price can't
be beat (the current developer preview is free). Considering most
stuff I do will fall into this or the basic tier, and that most
cartridges do not end up counting against your alotment of gears,
the pricing ($0.05/hour) is extremely competitive.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-11-01-openshift-zf2-composer.html">OpenShift,
ZF2, and Composer</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2012-11-01T15:25:00-05:00">1 November
2012</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by
<xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
</feed>
