Running Ruby on Rails on EC2 with Bitnami

Bitnami makes it easy to get started with Rails with their Amazon Machine Image (AMI) which creates a server for your app with all of the software you need already installed.  For my apps, I’m using Apache and Passenger, but Nginx is also installed if you prefer that.

Here are some instructions for setting up Rails using Apache / Passenger / MySQL

(1) sign-up for your Amazon Web Services account

(2) log in, and go to your AWS Management console

(3) go to the EC2 section

(4) click on the security groups link

(5) change the default security group to allow inbound requests:

http, https and ssh access from ip 0.0.0.0/0

(this allows people to access your app over http or https and allows you shell access to the server)

(6) click on the key pairs link and create a key pair (you’ll need this to access your EC2 instance)

(7) click the instances link

(8) click the ‘launch instance’ button and then select to create an instance from the Amazon Marketplace.  In the search box, enter Ruby on Rails

(9) select the Bitnami Ruby on Rails image and then follow the steps to create the instance

(10) while your instance is getting created, you’ll want to create your MySQL database.  In the Console, off the top menu, click “Services” and then RDS (under databases)

(11) click the “launch a DB instance” button in RDS, click MySQL on the next screen

(12) on the next screen, select a class (based on how powerful the server you want running your DB), enter the other required fields and record or remember what you entered here as you’ll need them to access your database

(13) Click on the “DB Security Groups” link.  Click on the default group, and down below you should be able to alter the permissions.  If you want to be able to access your database from your PC, add one for CIDR/IP and then copy the CIDR detected (it will show as AWS’s best guess in small font once your select CIDR).  You will need to add one for “EC2 Security Group” and select the “Default” EC2 security group.  This does not mean that you are adopting the settings of the  EC2 security group – it means that you are allowing members of that group to access the DB – this way your EC2 server with the application can access the database.

(14) Next you’ll have to update your database.yml file to make sure it connects to your RDS.  Once your instance has finished creating (green light next to the instance), click on the DB Instances tab on the left, and then on the next screen click on your instance.  This should bring up the properties of the instance in the lower frame of the web page.  Note the “endpoint” as this is the host you will use in your database.yml.

In your database.yml, for production enter this:

production:
adapter: mysql2
encoding: utf8
database: (your database name from step 12)
username: (your database user name from step 12)
password: (your database password from step 12)
host: (your endpoint)
port: 3306

(15)next you’ll want to log in to your EC2 instance, which should have been created by now to finish setting that up.  to log in, you can use the Putty program or you can use the Java shell client that AWS provides.  To use the the client AWS provides, go to Services > EC2 in the AWS management console.  Click on the Instances tab, and then right click your running instance and select “connect”.

(16) In the Java pop-up, change the user name from ubuntu to bitnami, and change the private key path to the path that the .pem file you downloaded to (in step 6), and then click “Launch SSH instance”.  If you are prompted to add the remote host, click ‘yes’.

(17) once you’re in, you can create a directory for your app, i put mine in /home/bitnami/apps/myappname

cd /home/bitnami/apps

sudo mkdir myappname

(18)  you can follow these steps to set-up git on your EC2 instance.  For my EC2 instance, I put my repo in: /home/bitnami/repo  (so you may want to change the directories in the set-up git link)

(19) we want to make sure your permissions are correct, otherwise your app will get 403 errors (Permission Denied) when accessing pages of your app.  Go to the directory above the one where you put your app.  For example, I used /home/bitnami/apps/myappname, so I would go to the /home/bitnami/apps folder:

cd /home/bitnami/apps

sudo chown -R bitnami:bitnami myappname

chmod -R 775 myappname

chmod -R 755 myappname

(20) after you’ve pushed your code, it should be in the directory you set-up for your app (in my example, /home/bitnami/apps/myappname).  run these three commands:

cd /home/bitnami/apps/myappname

bundle install

rake db:create

(21) with apache and passenger already installed, your app is ready to run.  the one last thing you have to do is to point Apache to your app.  to do that, go into your shell client and enter this command:

cd /opt/bitnami/apach2/conf

pico httpd.conf

(22) you should now be editing the httpd.conf file which is apache’s configuration for routing.  find this line and delete it:

DocumentRoot “/opt/bitnami/apache2/htdocs”

(23) paste (shift + insert key) in this (replace “myappname” with your app’s name):

<VirtualHost *:80>
DocumentRoot /home/bitnami/apps/myappname/public
<Directory /home/bitnami/apps/myappname/public>
Allow from all
Options -MultiViews
</Directory>
</VirtualHost>

(24) exit and save (CNTL + x, then click enter when it asks you if you want to save)

(25) run these commands to stop and restart your server so the changes take effect:

sudo apachectl -k stop

sudo apachectl -k graceful

(26) go to the public IP for your EC2 instance (you can find this if you go into the AWS Management Console, then go to the EC2 section – Services > EC2 – and click on your running instance to see the attributes – it’s “Public DNS”)

You’re app should now be available on the web at this address.

Hosting Ruby on Rails on Amazon Web Services

I’m experimenting with moving my apps onto Amazon EC2 from Heroku.  To do some, I’m using Amazon Elastic Beanstalk service.  Elastic Beanstalk is a free Amazon service (you don’t pay for the EB, but you pay for the resource consumption – for example your EC2 server, Elastic Load Balancing, and RDS for the database) that sets up the environment for you, including the various tools you’ll need to manage your scalable app:

  • EC2 – server for computing
  • RDS – relational database
  • Elastic Load Balancing – to help manage traffic
  • Cloud Watch – monitor performance of EC2
  • Autoscale – based on performance measures, scale up EC2 resources
  1. Start your Amazon Web Services account
  2. Go to Services > EC2
  3. Set-up a key pair, you’ll need this for SSH access to your server
  4. Use these directions on signing up for your EB account and creating the environment
    1. I used a 32-bit Linux with Ruby 1.9.3
    2. I checked the box to set-up an RDS instance (I allocated 20GB) for my MySQL DB to be hosted on Amazon as well.  Don’t forget to record your user name and password
    3. In the options for “Existing Key Pair” enter the name of the key pair you created in step 3
  5. Next, you’ll want to upload your code.  Follow these directions, with these additional considerations I learned:
    1. when I started with the commands, I thought that they were meant for Git Bash, but for me, as a Windows users, they were just meant for the standard command prompt
    2. I had trouble with the PATH command syntax on the page, but followed the syntax in the Read me file that came with the EB CLI download instead: set PATH=<path to eb>;%PATH% (Windows only).  For me this ended up: PATH=C:\Users\Me\Downloads\AWS-ElasticBeanstalk-CLI-2.3\AWS-ElasticBeanstalk-CLI-2.3\eb\windows;%PATH%
    3. I commit my code using Git GUI and then push using the Windows command prompt window
  6. To access your RDS database remotely, you need to change the security credentials for your RDS instance.  To do this, go to Services > RDS
    1. click on your DB instance link
    2. note what security groups are assigned
    3. click DB security groups in the left nav menu
    4. edit the one that was assigned to your instance (in the lower panel once you’ve clicked on the security group)
    5. add CIDR/IP and note what range AWS thinks your IP is in (it will say in small grey font under the CIDR text box) and enter that
    6. you should now be able to access your database using your favorite DB viewer from the IP you are at.  Use the endpoint as your host name and the DB user name and password you indicated in the EB set-up (step 4) to log-in
  7. To get shell access to your server, you’ll also need to adjust the security group it’s assigned:
    1. go to Services > EC2
    2. click on the link for your instance
    3. note the security group it’s assigned
    4. click on the security group on the left menu
    5. click on your security group
    6. in the panel below the security group, click the inbound tab
    7. Select create a new rule for “SSH”
    8. Add the Rule and Apply Rule Changes
    9. You should now be able to access your EC2 instance by right clicking on the instance link you saw in step 7.2
  8. To route a URL to your app, go to Services > Route 53
    1. create a “Hosted Zone” indicating your domain name
    2. take the four addresses given to you and specify them as the name servers to point your domain to, with whoever you registered your domain with
    3. open another browser window and go to Services > EC2
    4. click on the link for Load Balancers
    5. click on the record shown and below you’ll be given the A  record address to record
    6. go back to your hosted zone in Route 53
    7. click create record sets
    8. Add a new record for Type: A, click “Yes” for Alias Target, and in the Alias Target field, enter the A record address from step 5
    9. you should now be able to access your app by using your domain name

Creating a Sitemap Automagically for Rails App

Sitemaps help in making sure that your app is properly indexed, so it would help to automatically have them generated (and updated) so a search engine knows when a new web page is created, or an old one updated.  Luckily, there’s a gem, SitemapGenerator that makes it extremely easy to do this.

All you have to do  in Rails 3 is:

  1. add: gem ‘sitemap_generator’ to your gemfile
  2. run “rake sitemap:install” which creates config/sitemap.rb
  3. customize sitemap.rb

A simple example (where “Content” is a model name)

SitemapGenerator::Sitemap.default_host = "http://www.example.com"
SitemapGenerator::Sitemap.create do
  add '/contact_us'
  Content.find_each do |content|
    add content_path(content), :lastmod => content.updated_at
  end
end

4. run “rake sitemap:refresh”

5.  change your robots.txt file (if you have one) to include this line (so search engines can find it easy):

Sitemap: http://www.example.com/sitemap_index.xml.gz

6.  if you’re using Heroku, like me, you’ll have to take extra steps, as in this example, to write the files to somewhere else since Heroku is read-only.

7.  Also, if you’re using Heroku, you may want to use Heroku Scheduler to automatically refresh the sitemap by adding this task:

$ rake sitemap:refresh

8.  Lastly, to make sure Google indexes your site better, you’ll want to enter the path to your sitemap in a Google Webmaster Tools account for your site – the same as the address in step 5, unless you are using Heroku or another read-only system (and the sitemap is stored on another domain).  In this case, since Google Webmaster tools only accepts url’s from your domain (for the sitemap location), you’ll have to re-route them to the external location.  To do that you can make a simple controller like this example from Bill Rowell or you can use the rack-rewite gem.

Getting ActiveAdmin to Work on Heroku

The ActiveAdmin gem was working for me in development, but not in production.  The reason, I found, was because not all of the assets used by ActiveAdmin were getting precompiled by Heroku.  To solve the issue, I used the code by Ryan Long’s answer on Stack Overflow (in production.rb).

# Precompile additional assets. Defaults to [application.js, application.css, non-JS/CSS]
config.assets.precompile += ['active_admin.css', 'active_admin/print.css', 'active_admin.js']

Sign Out Wasn’t Working with Devise for Me

Devise’s Sign Out wasn’t working for me. I’ve seen other solutions, but they didn’t worked for me. However, I found an answer that worked for me on Devise’s wiki.

Previously, I used this link:

<%= link_to "Logout", destroy_user_session_path, method: :delete %>

However, that wasn’t working, so I changed (in config/initializers/devise.rb in ):

config.sign_out_via = :delete

to:

config.sign_out_via = :get

and revised the link to (removed “method: :delete”):

<%= link_to "Logout", destroy_user_session_path %>

Error: mysql2 gem compiled for wrong mysql client library

I was receiving this error after switching to the MySQL2. It turns out the reason is because I needed to update my MySQL connector.

To do that I
(1) went to: http://www.mysql.com/downloads/connector/
(2) I selected Connector/C (libmysql)
(3) I downloaded the Windows (x86, 32-bit), ZIP Archive no-install
(4) I placed it in my ruby/bin directory, which for me was in: C:\RailsInstaller\Ruby1.9.3\bin