Synopsis
Deploying a Ruby on Rails application to a production Linux server can be a pain. Using Mina makes things easier.
Introduction
The Ruby on Rails framework bills itself as one of the easiest platforms for getting web applications published to the real world, and after using the framework for ten years now, I have to agree. It abstracts away the not-so-fun stuff like database connections, writing SQL queries, keeping track of session cookies at a low level, and the like.
What isn't so fun about Rails is deploying it to a production server. Admittedly, Rails has come a long way from the beginning, when you had to install Mongrel servers and some kind of proxy to talk to them manually on your Linux server. But it still has a high learning curve, particularly if you haven't spent a lot of time at the Linux command line. Even after a successful setup, pushing the latest features or bug fixes to your application wasn't an easy thing.
Lately, I've been using Mina for deploying my apps. When you setup your application with Mina and then tell it to deploy, it compiles your deployment to a bash script, uploads the script to your server via SSH, and then runs it. This means that there's only one SSH session per deploy, which is must faster than the one-SSH-session-per-command arrangement that other systems use. The net result is really fast deployment. We're talking seconds instead of minutes. Even on one of my large apps, it often takes less than three seconds to finish the deployment.
Wanna see how it works? Let's get started on how we can use Mina to deploy a simple Rails app. The command and code examples below assume your use of a Mac OS development environment deploying to a Linux server, and that you've already added your SSH key to the server.
First Steps
Open up your project's Gemfile, and add the following line:
gem 'mina'
Save the file, head over to the command line and type:
$ bundle install
After that command runs, you can now setup Mina with your project using the following command:
$ mina init
The init command will install a new file to your project, located at config/deploy.rb. Open that file up in your text editor of choice, and let's take a look. Make sure that you set the following lines to values that make sense with your application:
set :domain, 'mysite.com'
set :deploy_to, '/home/deployer/mysite/' #path on server you want to deploy to
set :repository, 'git@github.com:<user>/<project>.git' # change this to reflect your username and project.
set :branch, ENV["BRANCH"] || 'master'
You might be wondering about that last line regarding the branch to use for deployment. It means that Mina will assume you're wanting to use the master branch of your source control system, but you can specify a different branch on the command line at deploy-time if you want.
Take a look at a few more items:
set :shared_paths, ['config/database.yml', 'config/secrets.yml', 'log']
set :user, 'deployer' # Username in the server to SSH to...
set :forward_agent, true # SSH forward_agent.
Let's go through these one by one:
- The shared_paths directive tells Mina which files or directories you want to be symlink'ed into your application once it's deployed to your server. Generally speaking, you'll want your database.yml and secrets.yml files to be part of this arrangement, but your needs may vary. Including the log here is also a good idea, since you probably don't want to lose your Rails log every time you deploy.
- The user directive is simple - just specify the user on the server that Mina should login as. You'll have to uncomment this line.
- The forward agent line, if uncommented, will let you pass on the SSH key that you have on your local development computer through your server on to GitHub, or whoever hosts your source code. This prevents you from having to create a special deploy key for your server to use in working with GitHub. I always uncomment this line.
Setup, Then Deploy
You shouldn't need to change much, if anything, at the setup section, but it's a good idea to look it over anyway. Find the section of the config/deploy.rb file that looks like the following:
task :setup => :environment do
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/log"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/secrets.yml"]
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml' and 'secrets.yml'."]
if repository
repo_host = repository.split(%r{@|:
repo_port = /:([0-9]+)/.match(repository) && /:([0-9]+)/.match(repository)[1] || '22'
queue %[
if ! ssh-keygen -H -F #{repo_host} &>/dev/null; then
ssh-keyscan -t rsa -p #{repo_port} -H #{repo_host} >> ~/.ssh/known_hosts
fi
]
end
end
As you can see, based on these instructions, Mina will create the necessary files and or directories that need to be symlink'ed during the inital setup process. We're just using a simple example application to illustrate the basics for now, so there's no need for us to change anything here.
Save the config/deploy.rb file, then go to the command line and type the following:
$ mina setup -v
This will cause Mina to setup the necessary directories and symlinks on your server for deployment. The -v switch tells Mina to be verbose, so you can see what it's doing while it's doing it.
Once the setup finishes, you're ready to deploy. Enter the following command:
$ mina deploy
Once that finishes, you're done! Not too bad, is it? This simple setup and incredible speed have made Mina my deployment tool of choice for Rails.
If you used the branch tweak in your config/deploy.rb file that I illustrated earlier, you'd deploy a different branch using this syntax:
$ BRANCH=my-branch mina deploy
Cool, Cool Tasks
Another reason I've been so taken with Mina is that it includes some really nice tasks that make it easier to work on your production server. Here are a few of my favorites:
mina console # Starts an interactive console
mina log # Tail log from server
mina ssh # Open an ssh session to the server and cd to deploy_to folder
I frequently have to take a look at my server's log, or run something from the Rails console, so these tasks are real time-savers. You can see the full list of available tasks by running:
$ mina tasks
If you've been searching for a deployment option for Rails, give Mina a try. Even if you've been using the popular Capistrano system for deployment, Mina is worth a look. It'll make one of the few pain points in Rails development go away.
History
This is the first version of the article.