Friday, February 10, 2017

Install Rails 5 on Elastic Beanstalk

My posts are mainly notes-to-self.  I try to add in supporting links to help anyone who can benefit from them.

Heroku has been my go to method for deploying Ruby on Rails apps.  However, I find that I want to create inexpensive web apps that do not go to sleep as the Heroku free apps do.  I also do not want to rack up multiple apps with a minimum $7 per month hosting fee for each idea I want to explore.

I have decided to try out Rails 5 on Amazon Web Services using Elastic Beanstalk for my next project to keep costs down and have apps that load immediately.

The project:
I have a Raspberry Pi earthworm bin temperature monitor served on my local network.  The Pi grabs temperatures from soil and air sensors, saves them to a text file, then the web site displays them on a graph with the help of Node.js.  The Node based site is slow and error prone.  I did not build the web interface, but rather grabbed it from an old tutorial on Raspberry Pi.  Since I am more familiar with Rails than Node and I want my site to be public, the idea I have is to write the temperature values to a cloud Postgres database, then graph them with Rails 5, and a graphing gem like Chartkick.

Install Elastic Beanstalk CLI 

I started by following these steps:

My specific steps:

Since I am on Ubuntu v 16.04, I cd to my projects folder to get started.
$ cd ~/projects

Check my python version.
$ python --version => Python 2.7.12

Install EB CLI
$ pip install --upgrade --user awsebcli

Figure out your shell then edit your PATH. (see the aws link above for detailed explanation) Since I use Bash I edited like:
$ nano ~/.profile

but I found that 
export PATH=~/.local/bin:$PATH
was already there so I exited out without changing.

Check my EB version
$ eb --version
=> EB CLI 3.9.0 (Python 2.7.1)

Create Rails 5 Instance

I am following along with this Rails and Beanstalk how-to

I already have ruby and rails installed so I go ahead and create a new Rails project.  If you want to install ruby and rails check this out: https://gorailrails new

I check my Rails version:
$ rails -v
=> Rails 5.0.1

Create Rails project
$ rails new wormbin
$ cd wormbin

Initialize git:
$ git init && git add -A && git commit -m "new rails 5 setup for elastic beanstalk"

First Model

My basic first need is to log the time and temperature.  I already have many months of data written to csv file on my pi.  I will need to begin writing the new values to the database we are creating now with our Elastic Beanstalk implementation.

$ rails g scaffold outside_temp date:datetime temperature:decimal$ rails db:migrate
$ git add .
$ git commit -am "Add outside temp"
$ git push

Note: to use git push you need someplace to push to.  I use github.   Check this out  

I create a remote repository on github.  Then with the url I create remote git:

$ git remote add origin $ push -u origin master

You can check your remotes with 
$ git remote

Initialize ElasticBeanstalk

$ eb init 

follow the choices shown on above tutorial or choose your own.  I went with ruby 2.3 and puma along with region = US-EAST-1

$ git commit -am "Post EB init"
$ eb create production

this part looks like it will take a while... about 5 minutes.  once done I can

$ eb status

If you head to url provided by status you will get error because of missing rails secret, so add it

$ eb setenv SECRET_KEY_BASE=$(rails secret)

to update 
$ eb deploy

I headed over to the public url and it gave me page not found. I did public-url/outside_temps and everything worked fine.  (I'll need to review muli word model name convention to avoid having underscore in url in the future)

Ok- I need to fix the above mistake with underscore before I go any further.  To do that
$ rake db:rollback
$ rails d scaffold outside_temp date:datetime temperature:decimal

$ rails g scaffold OutsideTemperature date:datetime temperature:decimal
$ rake db:migrate
$ git add .
$ git commit -m "change outside temperatur model name"
$ git push
$ eb deploy

hmm- that worked and it didn't.  I still have underscores.  I will come back to that later.

Setup Postgres Database

gem 'pg' #add to Gemfile
$ bundle install

edit config/database.yaml 
###noticealbe gap in info here###
I originally added a Beanstalk instance with automatic RDS created in it.  If you follow along with the above tutorial to setup Beanstalk it has you add the RDS database in Beanstalk instance.  You should not add rds instance within Beanstalk, but rather add it separately.  The security setup when doing it manually is the biggest hassle.  This explains how to setup:

I eventually worked out how to link my external RDS instance with Beanstalk but my appoach was not documented.  Sorry.  It has to do with security groups and making sure the RDS instance and the Beanstalk instance are in the same group.  I also added my local machine's ip to the firewall on AWS to allow me to manually connect to SQL with a Postgres a client to look at data independent of the web site.

In a future post I will demonstrate the python involved in writing to the database.