September 18, 2016

Get your Ruby app onto the internet, without Heroku

In an earlier post, I wrote about the easiest way to get your Ruby application onto the internet, using Heroku. Whilst Heroku is a very good option, and a good way to get started, there are valid reasons as to why you might not want to use it, or even be able to. If you find yourself in this situation though, what do you need to do? How do you proceed?

Choose a place to host

First you need to choose where you would like to host your application. There are plenty of good Virtual Private Servers, VPS, hosting companies. I have used and would recommend either of Digital Ocean or Linode, referral codes in those links. Of course there is Amazon web hosting as well, but they probably need less of a plug.

Setting up a server

Unfortunately, choosing where to host your server, that's the easy part. Setting up and getting it ready to run your application, that's a bit more involved.

To get going on setting up your server, you'll need to login into it via ssh as the root user, and setup a user that can run deployments. You'll need to add an ssh public key, make it the same as one you will use to access github, and also lock down openssh so that you can only login via public key, then add the deployment user to the sudoers file so that you can install things and manage them on the server without operating as the root user all the time, that is a big no no.

Install the dependencies

Once you have done that, you need to logout and log back in as your regular deploy user, this user will be able to do server management with sudo, but also just run the application as a regular unprivileged user too. First up now is to install the dependencies that you have for setting up and running your Ruby on Rails application. This is the list of dependencies that you will need.

Install Ruby

Once you have these installed, it's time to install Ruby and the way I'd recommend to do that is with Rbenv and ruby-build. With those installed you are able to install the version(s) of Ruby that you want, then with that bundler and be ready for your Ruby app to use your ruby.

What about a webserver

Of course the ruby application is to be put on the internet, so we need a web server. Nginx with passenger is a great choice, especially for lower RAM setups like a cheaper VPS can be as it runs a lower memory foot print then Apache.

Nginx can handle serving your static assets, but what about your dynamic requests to your Ruby code? For this we should really use Phusion Passenger, it can built straight into Nginx or Apache and whilst there may be more high powered ruby application server software out there, for getting started having one less moving part is good, as there are already a lot of dependencies.

Lastly on the webserver front, we'll need virtual host definitions for the application, for both the domain name, and www.domainname.com

Other Dependencies

Of course you can't forget, you still need a database, and possibly some caching software, and there is a good chance that you are running background workers, or will need to at some point. For these I use PostgreSQL for the database, Memcached for caching, and Redis for doing background jobs with Sidekiq

Once all that is done, you are ready to turn on your firewall and then you can use Capistrano to deploy your app to your server.

It's a lot

If that feels a little bit daunting, don't sweat it, it is a lot of stuff, and even if you go and type it all onto a server to get your app running, I've done this too many times, what happens when you have another app to deploy? You have to remember all that? Sounds like a pain, especially if you're anything like me and you have a hard time remembering the code that you wrote a few months ago. That means that when you come to buildig your next server, be it for a new application, or adding another server to an existing one, how can you guarantee that those servers are the same, that setting them up is repeatable, predictable and easy to do. Unfortunately doing it this way, you can't.

Automation

Of course as developers, we want to automate things. Then we don't have to do things ourselves, and they are done each time in a repeatable, predictable fashion, you know what you are going to get. To do that for a Ruby app server, I use Ansible, it's how I built the server that runs this blog. Using that Ansible playbook I went from having an empty Ubuntu distribution, to having a running application in 4 commands run on the terminal, and you can do it to, I'm offering that exact same Ansible playbook, and some instructions on how to use it to people who subscribe to my mailing list. Of course if you don't want to, no worries, there is a list of commands you can run to setup a server here.