Using CloudFront with S3 and Paperclip

I wanted to cache my S3 images for my Rails app, so I changed my app to serve images using AWS CloudFront, a CDN.

Doing this was pretty simple.

(1) Set-up a AWS CloudFront instance and your S3 bucket as your origin

(2) Change your Paperclip settings to use the new CloudFront instance.  I did this in production.rb (make sure neither the url or s3_host_alias values are being written by Paperclip settings in your model):

config.paperclip_defaults = {
storage: :s3,
:url => “:s3_alias_url”,
:s3_host_alias => “”,
:path => “:rails_env/:class/:attachment/:id/:style/:filename”,
:bucket => “your-bucket-name”,
s3_credentials: {
bucket: ENV[‘AWS_S3_BUCKET’],
access_key_id: ENV[‘AWS_ACCESS_KEY_ID’],
secret_access_key: ENV[‘AWS_SECRET_ACCESS_KEY’],

and that’s it!

Now, if you check the URL of your images, it should see that their source is prefaced with your CloudFront URL.

Adding a Sitemap to Google for Sites on Heroku

I’m using the awesome Sitemap Generator gem for Rails  and also hosting my app on Heroku.  Since I’m updating my sitemap daily, and Heroku forces me to write to somewhere else, I need to create the sitemap nightly on Amazon Web Services (S3), instead.

The problem I ran into is that when I went to Google Webmaster Tools, it only allowed me to specify a url for the sitemap beginning with the name of my domain.  However, since the sitemap is hosted on AWS, it has an address that starts with an Amazon URL.

I found an answer here.

Basically what you need to do is to add a second property in Google Webmaster Tools for your S3 bucket.  I added a property to my directory with the sitemap (i.e. and then verified that I owned the property by placing the Google supplied HTML file in the sitemaps folder on S3.

The last step is adding the URL to the sitemap in settings for the new [S3] property that was added to Google Webmaster Tools.

Using Route 53 to Map your Domains

Route 53 is an Amazon Web Service (AWS) tool for routing domain names to your AWS servers.

It’s very easy to do:

(1) log in to your Amazon Web Services account and go to the AWS Management Console

(2) go to Services > Route 53

(3) in Route 53, click the “Create Hosted Zone” button

(4) once your zone has created, you should have four “Delegation Sets”.  The Delegation Sets are the addresses that you will need to point your domain name servers to.  You do this typically by logging into your account with the company that you registered your domain with (ie Yahoo or Go Daddy), and then for this domain finding the section to edit or change your name servers.

(5) after you have updated your name servers with the domain registering company, go back to the AWS Management Console.  In the console, go to Services > EC2.

(6) If you haven’t already, you will probably want to either create a static IP or elastic load balancing, and have whichever you create point to your EC2 instance

(7) if you are using an elastic IP, it will have an IP associated with it.  Copy that and go back to your hosted zone in Route 53

(8) For your hosted zone, click “Go to Record Sets”

(9) Next, click “Create Record Sets”

(10) select:

    • IPv4 for the type
    • if you are using elastic load balancing:
      • click “yes” for alias
      • select your load balancer from the menu that appears
    • if you are using elastic IP
      • leave “no” for alias
      • enter your IP in the “value” box
    • save

(11) Most likely, you’ll want to do this at least twice – once for your domain with “www” and one without – that way people can reach your app if they type www and if they don’t.

Your domain name change will take awhile to propagate, but once it does, your domain will be pointing to your AWS server(s) now.

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

(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:

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

(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.

Getting EC2 to Use Git for Rails App

I wanted to use git to push my code.  Since I used an Amazon Machine Image (AMI) that installed Ruby on Rails that also included git, git was already installed on my Linux server, and I just needed to make it work.

(1) go into Services > EC2 and make sure that you have a key pair attached to your instance.  If not click the key pairs link on the left side, create a key pair and make a new instance that using this, so you have SSH access to your server.

(2) log into your instance using SSH

(3) go to the home directory, enter:

cd /home

(4) create a new directory in home (this is not where your Rails app will go):

mkdir repo

(5) go into repo:

cd repo

(6) initiate git for repo:

git init –bare

(7) create the directory where your Rails app will go.  Mine went into /var/www/app, so:

cd /var/www

mkdir app

(7) next go to the repo/hooks directory:

cd /home/repo/hooks

(8) hooks are scripts that run at given points in the git process.  we need to edit the receive-post file – this is triggered each time a new git push is made.  enter this:

cat > post-receive

(9) after hitting enter, type this:


GIT_WORK_TREE=/var/www/app (or wherever you want to put you Rails app)


git checkout -f

(10) after saving that you should be able to see your changes:

pico post-receive

(11) once you’ve confirmed that, run:

chmod +x hooks/post-receive

(12) next, when you do git pushes, you may have a personal ssh that is used, it’s an “” file.  for me, on windows, it was located in C:/Users/Me/.ssh

(13) copy the contents of that file (open it with notepad)

(14) go back to your SSH session and go to the ssh directory:

cd ~/.ssh

(15) In that directory, there is an authorized_keys file that contains a key that must match yours to do the git.  You can use the pico command to edit the file.  If you’ve never edited in pico, here are commands.

pico authorized_keys

(16) remove anything that is in there, paste your SSH details from step 8, then save the file

(17) go to git bash and add this new remote (if you have trouble with using your public ip, assign an elastic ip to your instance in the aws management console, in services > ec2):

git remote add origin ssh://[ec2 instance user name]@[public ip for your ec2]/home/repo

(18) in git bash:

git push origin


Using Amazon SES to Send Emails from Rails

I wanted to switch from Sendgrid to Amazon SES to send emails because of the difference in pricing.  Adding Amazon SES to your Rails app is just as simple as adding Sendgrid would be.  I was able to set it up based on one of the answers to this Stack Overflow questions.  There’s a gem for this, but I prefer not using a gem when the solution is this simple.

  1. Sign-up for your Amazon SES account
  2. In your management console for Amazon SES, click the button for “Verify a New Sender”
  3. Specify the email address you want to send your emails from
  4. Add an email to test receiving emails at (you can only send to verified email addresses until you get production access)
  5. Verify your email by clicking the confirmation link from the automated email Amazon sends you
  6. Go back to Amazon SES, and click on the left side for SMTP settings
  7. Click the button for “Create My SMTP credentials”
  8. Record the user name and password created
  9. Add this to your development and production.rb files:
config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
      :address => "",
      :user_name => "..." # Your SMTP user here.
      :password => "...", # Your SMTP password here.
      :authentication => :login,
      :enable_starttls_auto => true

You should be all set - request production access once you've tested that your app is sending the emails ok.