Tuesday, November 11, 2014

Deploy ownCloud with Bitnami in Google Cloud Platform

Google Cloud Platform recently announced the availability of Ubuntu images for Google Compute Engine. To take a test drive on this favorite operating system of mine, I decided to deploy an application on the new operating system.

The first thing came to mind was ownCloud, an open-source alternative for document sync solutions such as Dropbox, Box, etc. Traditionally, ownCloud is a software package that is deployed on-premise. With virtual machines (VM) available from IaaS providers, it is conceivable that one may be able to run ownCloud in a public cloud, so that a personal version of Dropbox can be had without dealing with concerns of security and privacy issues. (There are commercial file sync solutions that address this issue by design, including SpiderOak and Wuala.)

Initial deployment

First, I created an Ubuntu image with in Google Compute Engine. I made sure to select both "Allow HTTP traffic" and "Allow HTTPS traffic". Doing so would add the tags http-server and https-server to the instance, allowing the native firewall to open ports for the VM.

The complete stack of ownCloud requires a web server supporting PHP (such as Apache), and MySQL as the supporting database. It could get quite complex if one has to deploy the ownCloud software, as well as all the necessary dependencies on a VM. So I chose Bitnami, who specializes in packaged solutions for easier deployment.

There are two ways one can use Bitnami stacks.
  1. Deploy the standalone Bitnami installer for ownCloud.
  2. Deploy the Bitnami installer for LAMP stack, and then add the Bitnami module for ownCloud.
For my purpose, I wanted something to go live in hours, so I wanted to fiddle as little as possible. The first option turned out to be my natural choice.

After having downloaded the Bitnami installer on my Ubuntu image (via wget), I simply ran the installer script (via sudo). Only a few essential items needed I to be prepared before the installation.
  • Admin user info (username, password, and a descriptive name). Email is optional since I don't intend to enable SMTP for ownCloud.
  • Accessing address for ownCloud. Choose the external IP address for the Ubuntu VM instance running in Google Compute Engine. Do not use the internal IP, even though it is the default setting. Since you always need remote access to the VM, consenting to the internal IP would prevent you from accessing the web user interface (UI) without having to change the trusted domain further.
  • Choose production settings (i.e., option 2) for the installation type.
At the end of the installation, the script asks you if you want to launch ownCloud. If the answer is no, you can manually start it by running the following script from the installation directory.
$ ./ctlscript.sh start
More info is published here.

Change the web root

By default, the Bitnami installation runs ownCloud from the web URI of /owncloud. This is intended for installing ownCloud on a shared web service. Since I only intend to run ownCloud alone on this VM, I would very much like it to run from the root path. I have learned to make this adjustment before configuring any desktop clients. The ownCloud way is a bit kluncky as it requires code change. I find that the Bitnami way to be much easier to work with. Do restart the ownCloud stack after the change.

Now that the ownCloud was live and well, I still needed to further configure secure access.

Set up the domain

I used Google Domains to register a domain name that I liked, which is reasonably affordable.

The recommended steps are as follows.
  1. Create an A record for the host DNS name such as mycloud.mycompany.com, and assign the current ephemeral IP address to it. Note that the IP address is temporary, we need to set the TTL to something as short as a few minutes. (More on this later.)
  2. Change the trusted domains settings in ownCloud to use the host name instead of that IP address. I decided to just modify the PHP file directly, and only allow accessing from that host name.
  3. Restart Apache.
  4. Access the web UI using the host name and make sure it works.

Set up the SSL certificate

I acquired a cheap SSL certificate from Namecheap, where its PositiveSSL single-domain certificate cost only $9 a year, and it is available almost instantly, pending domain ownership verification. (Note, Namecheap's certificates use Comodo as the certificate authority.)

Now we move on to digital certificate. We need to create a private key first with the following command.
$ sudo openssl genrsa 2048 -des3 \
    -out {
host__dns_name}.key
Next, prepare for the certificate signing request (CSR). On the VM, run the following to generate a key with SHA-256 hash. This is important because of the recent Chrome controversy about deprecating SHA-1.
$ sudo openssl req -new -sha256 \
    -key {
host_dns_name}.key \
    -out
 {host_dns_name}.csr \
    -subj "/C=US/CN={
host_dns_name}
You would need to fill out a request form on Namecheap's web page using the blob in the generated .csr file. Also, choose the web server type as apache2.

Because I couldn't receive emails from the domain that I used (for lack of MX records), I worked with Comodo technical support over a web chat session. My request was approved via domain verification using a temporary CNAME entry. At the end of the live chat, I received two .crt files - one for the signed certificate (which I renamed to {host_dns_name}.crt) and the other is a combined file of the root and other intermediate certificates.

I still received a ZIP file from Comodo in the email, but the root and intermediate certificates are separate files, which requires you to manually concatenate the certificate blobs together into a single .crt file.

I ran these two commands to ensure that the hash values of the private key and of the certificate match.
$ sudo openssl rsa -noout -modulus \
    -in {
host_dns_name}.key \
    | openssl sha256
$ sudo openssl x509 -noout -modulus \
    -in {
host_dns_name}.crt \
    | openssl sha256
Needless to say, one has to deal all three files with care. Other than proper backup, I created a folder that stores these files with only read access by root.

These two files, along with the private key, are all you need to configure the Apache. The nice thing about Bitnami is that the changes can be made outside of Apache in {bitnami_installation_folder}/apache2/conf/binami/bitnami.conf. The relevant entries to point to these files are SSLCertificateFile, SSLCertificateKeyFile, and SSLCertificateChainFile. These entries point to a dummy self-signed certificate by default. Remember to use the approved digital certificate file, not the original CSR file for SSLCertificateFile, even though both may be using the .crt file extension.

Lastly, restart Apache and verify that the web UI works with HTTPS.

Finalize the deployment

After having proved my ownCloud instance can be accessed via HTTPS, the first thing I did was to remove the tag http-server from the VM instance. This effectively changed the firewall rule, forcing all communications only through TLS. There are other ways to enforce that in Apache or ownCloud, but I have found this to be the most expedient.

Immediately afterwards, I changed the admin password again, since I had used the initial password several times in the clear before HTTPS was configured.

Now I need to make a few final touches to make the VM permanent.
  1. Un-checking the option "Delete boot disk when instance is deleted", so that the ownCloud deployment can survive a VM reboot.
  2. Create a new static IP and assign to the VM. This way, I can always make use of the fixed IP address in the future if I have to restart the instance.
  3. Change the DNS entry with the fixed IP address, now with a much longer TTL (such as a week or so).

For further piece of mind, I created a snapshot of the persistent disk associated with the VM.

Configure the sync client(s)

There are cross-platform desktop clients available from ownCloud. Mobile clients are available for iTunes, Google Play, and Amazon Appstore. Desktop clients are free to use, but mobile clients cost 99 cents each.


Bitnami pros and cons

The Bitnami advantage for deploying ownCloud (or other packaged solution) is fast time-to-market. All the dependencies are pre-packaged and the entire solution is self-contained. For example, it does not require individual installation of Apache, PHP, or MySQL. All components can be managed using Bitnami scripts and/or tools.

That said, using Bitnami also implies that you are not using operating system's package management tools. For example, Apache is not installed via apt-get, and you won't be able to get the most recent security patches pushed to Ubuntu's package repository. Instead, you would rely on Bitnami to package the next version to upgrade.

It is possible, however, to enhance the initial Bitnami installation with more advanced configuration. For example, one can configure to have ownCloud start upon system start, instead of having to manually invoke the start-up script. It is further possible to replace the MySQL back-end to, say, Google Cloud SQL, or introduce Nginx as the web server. Yet, all of which would imply that one has deviated from Bitnami and started down the path of self-administration of ownCloud.

Benefits of ownCloud in the cloud

So why am I doing this?

To start off, for the essential file sync functionality, ownCloud does pretty much what Dropbox offers, with fewer concerns about privacy and security. Granted, my data reside with the IaaS provider, which is Google in this case. However, the industry should move forward with custom-managed keys. When Google Cloud Platform supports custom-managed keys, it is the next step to further secure the data.

Secondly, using public clouds takes advantage of the IaaS infrasture. All the current commercial solutions impose storage caps. Dropbox has 1TB limit. In the case of Google Compute Engine, I could technically provision a persistent disk as large as 10TB, and attach four of them to the VM. Also, the sync client would enjoy the great sync bandwidth from the cloud, comparing with hosting ownCloud from a personal server built at home, where the upstream limit is capped by most ISPs to a few Mbps, orders of magnitude lower than using IaaS providers.

There is also cost advantage to deploying ownCloud in the cloud. The majority of the monthly spend is on persistent disks and network egress. Assuming 10% of storage is network egress, this renders the cost for 1TB of data to about $53, plus the computing hours. This is costlier than Dropbox Pro's $9.99, but most unlimited solutions (such as SpiderOak Professional) would charge $100 for the same 1TB.

If you opt for building your ownCloud hardware, the cloud would still be ahead. The hardware cost of a reasonable server is $600 and let's amortized the amount over three years. Then there is the electricity bill (100W at the rate of 15 cents per kWh). Further factor in the notion that 3 hours are needed each month for maintenance and care, using the minimum wage of $7.25. The total monthly spend is now $53. This is with almost no redundancy and difficulty in hardware migration down the road.

Last but not the least, with your own ownCloud, you never have to worry about the file sync provider went out of the business.

Now I'm going to sip a cup of coffee while my initial file sync is in progress.