Curse you, CNAME
When I first moved this blog, it was found at
blog-stufftoddknows.rhcloud.com, visibly exposing the underlying OpenShift Online hosting platform and, well, ugly.
Mind you, I had the same problem when I was hosting my WordPress-based blog on Azure. At that time, the solution was easy -- just create a CNAME DNS record with my registrar, point it at Azure, and get on with life.
So why not just do the same now?
Well, a terrible thing happened on the way to DNS. There is an on-going debate on what the DNS RFC says regarding CNAME records which point to root domain names. And I really, really want
stufftoddknows.com (a root record) to work, not just
www.stufftoddknows.com. My domain registrar, 1&1, either due to a policy change or a software change, flipped sides in this debate. During my WordPress/Azure days, I was able to create a CNAME record for
stufftoddknows.com. When launching my new Ghost/OpenShift Online blog, creating this kind of CNAME record was no longer possible. (I couldn't even edit the existing CNAME record!)
Therefore, the only real answer I could find was to create an A record. But, enjoying the benefits of a zero-cost OpenShift Online instance means that the IP address of my blog can change at essentially anytime. Therefore, I'd be on the hook to update the A record whenever my blog's IP address changed.
Dynamic DNS to the Rescue
Unsurprisingly, I decided that I needed to find a dynamic DNS solution. I'd already had good success with afraid.org for another website which was facing the same issue. But that other website was moved from one instance of Windows Server to another, and, being a Windows guy, it was easy for me to figure out how to get the dynamic updating working. More importantly, the website was moved to a Windows Server running in my own house, for which I had full access and control.
Essentially none of those facts apply to OpenShift Online.
So I had to go about figuring out a solution to getting a reasonable analog working within the OpenShift Online infrastructure.
Now, if you are not familiar with how Dynamic DNS works, it's really quite simple. The host machine simply needs to tell the remote DNS server 'hey, my IP address currently is A.B.C.D', and it either needs to do that at some regular interval (easy) or whenever it detects that the IP address has changed (slightly harder).
Let's consider the easier scenario of updating DNS at some regular interval. In Windows, I would have used task scheduler. In Linux, the analog is
cron. And it happens to be the case that cron is a cartridge for OpenShift Online.
Navigating to my application page in the OpenShift Online web console, there is a link to see the list of cartridges I can add.
Clicking it gives me a list of available cartridges; cron is there and ready to be installed.
A quick click on the tile and then selecting to install the cartridge gets cron added to my application quickly.
And then I was lost.
Once installed, here are the helpful instructions provided to me:
And while I'm not saying that's uninformative, I was still confused. Where did these files live? How would I go about creating or editing them? What's a Windows guy to do?
Now, I had already figured out how to remotely log into my OpenShift Online instance via
ssh. Doing so, I was able to find all sorts of interesting directories which had the potential to be the same as the ones referenced in the above screenshot. But, try as I might, I could not definitively determine the right place to go.
It's good that I couldn't, because even if I did, I would have still been wrong.
Use the source
Even if I had found the right directory to configure my cron job, and even if it seemed to work, it would have ultimately been a mistake. The usage model for OpenShift Online for these sorts of changes is to make your changes remotely in source control and then push those changes up to the service. Git is the source code provider for OpenShift Online. I already had git installed on Windows, and, thanks to my prior work to get ssh configured properly, git was also capable of interfacing with my OpenShift Online application.
My first step was to drop to a command prompt on my local Windows machine, change to a directory into which I wanted to place a copy of the source code, and then use a clone command to grab a copy of all of the files for my application. From my OpenShift Online application web console, it was easy to get the URL of my git repository (found on the right hand side of the screen).
From my command prompt, I simply had to
ssh clone <repo url>
and then wait for everything to download.
Now things made a lot more sense. From here, I was able to see that the instructed directory did exist. I decided that I wanted to update my DNS settings once per minute (yes, that's way too often...I need to change this to be far less aggressive), so I changed to the appropriate directory:
I didn't even have to create the directory -- it was already there. (YMMV).
All that I needed was a script to do the updating. Thankfully, on afraid.org there are tons of sample scripts, daemons, services, apps, etc. that can perform dynamic DNS updates. But, ignoring those, there are links to download super-simple scripts specifically configured for your registered domains. One of these scripts does a single
wget to a carefully crafted URL, the net result of which is that your DNS A record is updated to match the IP address from which the wget originated. (To my Windows friends, Linux wget is a command-line utility to grab the contents of a URL. Think of it like a command-line web browser. In this instance, it's being used like an HTTP version of ping.)
With the wget command in hand, I fired up notepad and created a new file named ddns.txt. In it, I placed the following:
#!/bin/sh wget -q --read-timeout=0.0 --waitretry=5 --tries=400 --background http://freedns.afraid.org/dynamic/update.php?<my-api-key>
<my-api-key> is specific to my domain. (Note that this script is just 2 lines long -- word-wrapping in your browser may fool you into thinking it's more than 2.) (And, to my Windows friends, the
#!/bin/sh on the first line just lets the system know which shell to use to execute the script.)
Finally, to be more Linux-like, I renamed the file from
Creating the script file locally was nice and easy, but I still needed to do two things to make this a meaningful exercise. First, I needed to get the script file up to OpenShift Online. And, second, I potentially needed to restart the cron service.
In order to get the script file uploaded, it needed to be added to my local git repository. Instructing git to add the file and commit that change was easy:
git add .openshift\cron\minutely\ddns git commit -a -m "add ddns minutely cron script"
Unfortunately, there is an extra step that is needed, highlighting a difference between Windows and Linux. Both operating systems have a notion of "is this an executable file," but the two models are pretty different. Moreover, in Linux, even script files must be marked as executable. Git exposes these attributed via metadata, so it is possible to set that attribute on the file. Here's how I did it:
git update-index --chmod=+x ddns git commit -a -m "setting execute bit on script"
Lastly, I had to push the change up to OpenShift Online:
With that one command, not only was the file uploaded, all of my OpenShift Services were restarted. After a few minutes, I jumped onto afraid.orf and verified that my domain stufftoddknows.com had a valid IP address.
Need an Alias
There were still a few more pieces to the puzzle. Granted, stufftoddknows.com was pointing to the right location, but somethings were out of whack. For example, any of the links on my blog where still using the fully qualified domain name (FQDN) of blog-stufftoddknows.rhcloud.com. Within the OpenShift Online web console, it was easy to change the alias assigned to the application -- by clicking on the
and adding a domain name:
I figured I was finally done! But, no, I was not...
Alias Not Good Enough on Its Own
Attempts to log into my blog as an administrator failed, telling me that the url within my
config.js file did not match the url I was using to access the site.
Learning from my trials above, I went to my local git repository and found the config.js file right in the root directory. Within this file, there were several instances of the
url configuration parameter -- even several marked as for 'production'. They all looked like this:
which simply sets the url to match that of the environment variable
OPENSHIFT_APP_DNS. But, it turns out, that variable is set to the original DNS name and never seemed to update to match the new alias. Hey, maybe I did something wrong, but I happily took a heavy-handed solution to the problem.
I replaced all instances of this url setting using the environment variable with
I saved the file, did a
and watched the change get uploaded and all of the OpenShift Online services restarted. Volia! My site was on-the-air under my custom domain name!