Lessons learned: migrating Ruby on Rails app to a private server

I needed to migrate a ruby on rails app from amazon web services to a privately owned hosting service. AWS has it’s own method of building and provisioning rails app (basically by using their in house tool called “beanstalk“), so provisioning and migrating the data to a normal, private server meant I took some quick notes I spent the better part of the morning learning the hard way.

First off, making a backup is just common sense, especially of the database (mysql in this particular case). Once you are sure you have all the data (usually this is just ruby app files and sql dump), you’re ready to go:

  • I followed the guide on installing the ruby on rails environment along with nginx + passenger here: https://www.digitalocean.com/community/articles/how-to-install-rails-and-nginx-with-passenger-on-ubuntu. This was quite painless and proceed according to plan. Only one note:
    • Make sure you select the version of ruby that is best for your application. In the above link, they use v1.9.3, which may or may not be adequate for you
  • Copy over your rails app files to a suitable location. Do the same for your SQL dump
  • Navigate into the rails app directory (eg cd /var/www/your-rails-app) and run the command bundle install. This will install all the necessary gems your application requires. Make sure you have all dependencies install before hand (like mysql-server, client, and development libraries) via apt-get install
  • If, like me, you are migrating from AWS to a private server, you probably need to change your production database connection string in database.yml to reflect your private server’s database settings
  • Restore your SQL file into the new database

Till here, all well and good. But, on attempting to open my app, it seemed that the server was simply responding with 404 for all the static assets in the rails app. Having followed the above guide to the letter, and make sure that the permissions were correct, I was stumped. This is what solved the issue for me:

  • In the production.rb environment config file, I noticed a line similar to the below, which essentially assumes that the webserver itself (nginx in this case) is going to serve the static files:

config.serve_static_assets = false

  • To make sure that the nginx server really was serving up static files, I added the following to the  file:

server {
listen 80;
server_name example.com;
root /var/www/xxxxxx/public;
passenger_enabled on;
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml|html|txt|manifest|eot|svg|ttf|woff)$ {
root /var/www/pms/public;
gzip_static on;
expires max;
add_header Cache-Control public;
}
}

  • On testing, I now got a 403 (unauthorized) error, which almost always is a filesystem permission error. This was quickly solved by making sure the files in the public dir
    • had an owner which matched the user under which nginx was running
    • had both read and execute permissions.