My last week, I’ve spent my time on something that I wanted to achieve for years. Running Ruby on Rails applications on a Cpanel installation. I can even say that it was ‘the holy grail’ of development for me, because I always create small meaningless projects, but then always got uninterested in them because keeping them alive would be a lot of work for stupid gimmicks.

In PHP world, they always had the perfect solution. Any hosting that you can get for less then 50$/year, could supply all your needs, including hosting, routing, e-mail accounts, ftp accounts, webDav storage… And you can also serve most PHP applications without any modifications on a domain of your choice. It’s simply perfect. All these years, since I started programming, I always had a hosting that I use for simple websites that I host for myself and my friends. But I wasn’t able to use it with any Ruby applications. Then Cpanel attempted to host Ruby on Rails applications, with worst possible implementation.

Ruby on Rails done wrong!...

The screenshot that I’ve inserted here, has all the horrible things about Cpanel combined for a Ruby on Rails developer. First of all, on this old Cpanel system, Ruby version locked to 1.8.7. The ruby version that I’ve first written with. More then 9 years old(Release date 31 May 2008). And then, Rails version, locked to; 2.3.8. Which is around the same age. The current Ruby version is 2.5.1 and Rails version is 5.1 as a reference. So this system was un-upgradable, native gem extensions nearly always failed to install because of the outdatedness of the system.

I’ve actually never managed to run a Ruby application via this old interface.

So is there something new?

Yes. A lot.

First of all, instead of using this horrible locked down system, now we have something called Application Manager.

Ruby on Rails done right!...

On my current hosting, hawkhost.com(affiliate link), the application manager is hidden behind two buttons, “Setup Python App” and “Setup Ruby App”. I am going to cover the “Setup Python App” option in another post, but for this post, I will focus on creating a Ruby on Rails application. Let’s start by creating the simplest “hello world” example of Rails.

Create a simple Ruby on Rails Application

I am not going to cover everything related to rails basics. I assume you have a working rails installation. To create a new rails application, you just need to run,

rails new hello_world

this should create a new application in a folder called hello_world. Let’s create a controller and a model after changing our working directory to our app.

cd hello_world
rails g controller hello
rails g model user name:string

This should create a hello_controller.rb controller in our controllers folder, and a model with migrations named User. Let modify our routes.rb file to handle navigation. We will only have one root route for this example.

Rails.application.routes.draw do
    root to:'hello#welcome'
end

The welcome method should return all the users we have in db in json format. Modify the HelloController like following.

class HelloController < ApplicationController
  def welcome
    render json:{users:User.all.to_a}
  end
end

The last thing we need for our application to have some sorf of meaning. So we need some users in our database, otherwise it’s just going to return an empty array all the time. To fix this issue, we need to add some seeds to our db/seeds.rb file.

User.create(name: 'User One')
User.create(name: 'User Two')
User.create(name: 'User Three')
User.create(name: 'User Four')
User.create(name: 'User Five')

After adding seeds, let’s create our database and seed. With default options, rails should use sqlite, but we will modify it to use mysql. Let’s run out migrations and seeds.

rake db:create
rake db:migrate
rake db:seed

Let’s run our application, and see that it returns users when ran locally.

rails s

After running the application, just browse to ‘http://localhost:3000/’, and you should see the following json returned to you.

{"users":[{"id":1,"name":"User One","created_at":"2018-04-02T10:26:11.431Z","updated_at":"2018-04-02T10:26:11.431Z"},{"id":2,"name":"User Two","created_at":"2018-04-02T10:26:11.462Z","updated_at":"2018-04-02T10:26:11.462Z"},{"id":3,"name":"User Three","created_at":"2018-04-02T10:26:11.494Z","updated_at":"2018-04-02T10:26:11.494Z"},{"id":4,"name":"User Four","created_at":"2018-04-02T10:26:11.533Z","updated_at":"2018-04-02T10:26:11.533Z"},{"id":5,"name":"User Five","created_at":"2018-04-02T10:26:11.563Z","updated_at":"2018-04-02T10:26:11.563Z"}]}

So now we have a working application. We just need to prepare our hosting for our new application, which -for this example- is just creating a new database for our new application.

Create a database and subdomain in Cpanel

Just navigate to your cpanel installation, find MySQL Database Wizard. After clicking on it, choose a database name, create a user, give it a password and give all the priviledges to that user on the newly created database. Take a note of everyting you type in. For my setup, my variable names were as following.

database:"gokaykuc_blog_test"
username:"gokaykuc_blog_test"
password:"c!v[3AiUfXSs"

We also need a domain to serve our application from. I can safely assume that you have a root domain assigned to your cpanel installation. So to make this tutorial simpler, let’s just create a subdomain, and install our application to that subdomain. Click on Subdomains button on your cpanel installation. Create a subdomain with the following name, Creating the subdomain. Set your document root to something you’ll remember, and just create the subdomain.

Modify the Rails app

Let’s modify the rails application to accomodate to our new database in Cpanel. Open the config/database.yml file, and modify it’s development key.

development:
  adapter: mysql2
  database: gokaykuc_blog_test
  username: gokaykuc_blog_test
  password: "c!v[3AiUfXSs"

Our new setup here, expects a mysql server to run on same machine. Because we haven’t provided any host and port values, it’s going to try to connect to mysql server via socket connection(which might be a problem on windows machines.) Also because we are using mysql now, we need to add mysql2 gem to our Gemfile. Also one other particular issue is, for some reason if i don’t include ‘bigdecimal’ gem, none of my rails applications worked, so let’s add that too.

gem 'mysql2'
gem 'bigdecimal'

If you want to run the application locally again, just run ‘bundle install’ before trying ‘rails s’.

Before uploading our changes, there is one last modification we need to apply. Open up config/secrets.yml file. Run rails secret on a terminal. This command will generate a long random string for you to use as your applications secret. Copy and paste it into config/secrets.yml files secret_key_base key under production key.

Setup secret.

After these modifications, now we are ready to create our application. Open up your Cpanel, and click on Setup Ruby App. Select a ruby version that will work with your ruby app. For our demo, 2.4 is the safe bet for now. In my experience 2.5 had some issues with compiling native gems(But I have to give it to them, hawkhost support was amazing while I was trying to figure our what’s wrong with my first setup). Select the correct sub-domain and App Directory then click on Setup. Setup Ruby App form. Allright, now we are halfway there. On our next step, we need to upload the entire project directory to the directory we specified in the previous step. You might want to remove db/development.sqlite3 before uploading you project, because we are not going to use it. Fire up your favorite FTP client(Filezilla for me at the moment), connect to your hosting account, and upload the entire rails directory to your application directory. There will be files in the application directory, just select overwrite when there is a file collision while uploading.

SSH

The last steps include connecting to the server via SSH, and installing required gems. You can manually use modules system to install all the dependencies by hand, but it just takes too much time, and pretty error prone.

To start, we need an ssh connection. If you need more help on SSH connectivity to your hosting, I will create another blog post explaining that process. For now, I assume you have a working ssh connection to your hosting provider, and from there we can continue.

First step is locating “Command for entering to virtual environment”. It should be just at the bottom of you application’s setup screen. Get the virtualenv command. After locating the command just head to your ssh’ed terminal, and copy paste the command from there. It should prepend the name of the environment and ruby version of the environment to your shell. Activate the virtualenv. Then cd into your application’s directory. Then run,

gem install bundler
bundle install

This commands should download all the libaries that your rails app needs.

Just before finishing up with our installation, we just need to append one line to our environment initializer. We’ve already got the command to run for activating our environment. We just need to add one line to it. RAILS_ENV=production.

Add rails_env variable.

At this point, the only thing you application needs is to have it’s migrations run. Just append the RAILS_ENV variables in front of them too before running them.

RAILS_ENV=production rake db:migrate 
RAILS_ENV=production rake db:seed

Run rails migrations.

After running migrations, you might need to restart your application, or wait a little bit. For my case, it takes a while to apply the changes.

It's alive.

There it is, alive and stuff :).