In my previous post, I introduced the idea of a hypothetical DevOps maturity model. This post is going to illustrate Level 0 from that model.

If you recall, Level 0 is basically pounding on keys until you have your software stack running on your server(s). There is no automation or testing of your infrastructure or deployment scripts, there’s no CI/CD pipeline to provision infrastructure and your servers are pets that need constant tender loving care. In this post we are going to mash some keys and deploy a simple Ruby on Rails application to an Azure virtual machine.

Please let me preface this post by saying this is not the most efficient way to deploy your Rails bits out to Azure, or any other remote compute resource for that matter. This post is simply to define all of the basics that are taking place as we mature the DevOps model in subsequent posts.

Prerequisites

Ruby (https://rvm.io/rvm/install)

Azure CLI (https://github.com/Azure/azure-cli)

Github account

SSH key pair ~/.ssh/id_rsa{.pub}

Create our Rails API Application

Let’s generate a simple Rails application, which we’ll deploy out to a VM running in Azure.

First off, create a new Github repository specifying repo name level0 . After the repo is created grab the clone URI as shown below.

Clone with SSH

In this quick snippet, we clone the repository, install Bundler and Rails gems, create a new Rails application and then start the application running on localhost:3000.

Generate your Rails Application

Provisioning an Azure VM

Now that we have a running Rails application, let’s provision our virtual machine to run our newly created Rails application.

Before we build the VM, let’s start with a bit of background on infrastructure in Azure. In Azure everything starts with a Resource Group. A resource group is a logical grouping of related Azure resources. Azure resources are the building blocks of your infrastructure. We’ll be building the following resources.

Virtual Machine : virtualized compute instance using managed storage

: virtualized compute instance using managed storage Virtual Network : software defined cloud network

: software defined cloud network Network Security Group : contains a list of access control rules that allow or deny network traffic to your VM instances

: contains a list of access control rules that allow or deny network traffic to your VM instances Network Interface : is the interconnection between a VM and the underlying software network

: is the interconnection between a VM and the underlying software network Public IP: publicly accessable IP endpoint

I find it’s a best practice to keep all of an application’s Azure resources within a single resource group.

Create an Ubuntu VM in Azure

As you can see from the resource listing above, the az vm create command has created all of the basic resources needed for a publicly accessible VM. Now that the VM has been created, you can access the VM via ssh deploy@${publicIpAddress} where publicIpAddress is the address returned by az vm create .

Configure the Azure VM

Now that we have a provisioned a VM in Azure, we are going to configure this server to run our Rails application. The basic software we need to run our Rails application is the following:

Nginx : reverse proxy to balance incoming requests across multiple Rails processes running via Puma

: reverse proxy to balance incoming requests across multiple Rails processes running via Puma RVM: to manage and install Ruby versions (Ruby 2.4 at this time)

The commands below should be run on the Azure VM after ssh’ing into the VM.

Configure Azure VM with Ruby, Nginx, Rails and RVM

Configure Capistrano Deployment in Rails

Capistrano is a framework for building automated deployment scripts. Although Capistrano itself is written in Ruby, it can easily be used to deploy projects of any language or framework, be it Rails, Java, or PHP. — Capistrano

We are going to take our vanilla Rails application and capify it. By leveraging Capistrano, it will help provide us a fast inner loop for develop, test and deploy.

Add the following to your Gemfile in the root of your Rails application.

Gemfile Additions

Run the following.

Initialize Capistrano

Replace the contents of the newly created Capfile with the following.

Capfile

At this point, we have a Capfile that will handle many of the Rails build / deployment tasks that can be kind of annoying such as using a specified verision of Ruby, installing gem dependencies from the Gemfile, pre-compiling of assets and git related tasks. Next, we’ll update our config/deploy.rb to prepare for our first deployment of the application.

Replace the contents of your config/deploy.rb file with the following deployment configuration.

config/deploy.rb

The above deployment configuration automates and simplifies some boilerplate tasks such as:

Ensure the latest git ref is up-to-date upon deployment

Restart or start Puma when new bits are deployed

Managing multiple release of the application for quick rollback

Run Rails in production mode

Link production secrets.yml file

Now that we have our Capistrano deployment configuration described, we move on to our Nginx configuration. Create config/nginx.conf in the root of your application directory.

nginx.conf

For more information about Nginx, check out https://www.nginx.com.

Deploying your Rails Application

All of our Rails deployment configuration is done. We now move onto deploying our application onto the VM in Azure.

Run the following commands to execute the initial deployment.

Initial Capistrano deployment

You should now be able to open your browser to the IP of the Azure VM and see your “Hello World” Rails application. If you want to keep going and continue to extend this application all you have to do is git commit , git push and cap production deploy . Enjoy!

If you’d like to pull down the code for this post, you can grab it here (https://github.com/devigned/level0).

Next Up: Level 1 + Todo List

We’ll extend this application to add functionality, data, a content distribution network (CDN) and ratchet the maturity level up to Level 1.