12.16.2013

Rails 4 Connect Existing Database

Once connect strings are specified in database.yml file, just add a model as follows:
class TestResult < ActiveRecord::Base
  self.table_name = "Test"
  self.primary_key = "testId"
end
Now, lets check from the console
$ rails c
Loading development environment (Rails 4.0.2)
2.0.0p353 :002 > TestResult.column_names
 => ["testId", "analysis", "archive", "baseline", "description", "engineer", "name", "project", "reference", "retention", "link", "errors"] 

12.11.2013

Deploying a Rails App Remotely With Capistrano

Modify Apache Config

1. Capistrano inserts a directory named "current" so change the DocumentRoot of the .conf file:
$ sudo vi /etc/httpd/sites-available/depot.conf
DocumentRoot /home/samdc/prod/depot/current/public
<Directory /home/samdc/prod/depot/current/public>

Setup Git Server

2. Create an empty repository on the git server
$ mkdir -p ~/git/depot.git
$ cd ~/git/depot.git
$ git --bare init
3. Generate a public key and use it to give ourselves permission to access our own server
$ test -e ~/.ssh/id_dsa.pub || ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/samdc/.ssh/id_dsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/samdc/.ssh/id_dsa.
Your public key has been saved in /home/samdc/.ssh/id_dsa.pub.

$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
4. Make sure that proper permissions are set for ssh. I got another post related to this..
$ chmod g-w /home/samdc
$ chmod 700 /home/samdc/.ssh
$ chmod 600 /home/samdc/.ssh/authorized_keys

Prepare Application

5. Update Gemfile to indicate that we are using capistrano
$ vi Gemfile
gem 'rvm-capistrano', group: :development
6. Install capistrano using bundle install
$ bundle install
7. If you havent done so, put project under git
$ cd app_directory
$ git init
$ git add .
Ignore files
$ vi .gitignore
.ruby-gemset
.ruby-version
$ git commit -m "initial commit"
8. Copy all the gems required by your application into the vendor/cache folder. This also includes dependencies required by the gems. This helps because at the time of deployment you can just run bundle install --local to avoid dependency on the gems repository (rubygems.org) and install all the gems from the cached folder
$ bundle package
$ git add Gemfile.lock vendor/cache
$ git commit -m "bundle gems"
9. Push our code to the Git server
$ git remote add origin ssh://samdc@host/~/git/depot.git
$ git push origin master

Remote Deployment

1. Add necessary capistrano files to the project
$ capify .
[add] writing './Capfile'
[add] writing './config/deploy.rb'
[done] capified!
2. Modify Capfile and uncomment one line
load 'deploy/assets'
3. Modify deploy.rb, this is the recipe that we will use for deployment
require 'bundler/capistrano'

# be sure to change these
set :user, 'samdc'
set :domain, 'depot.com'
set :application, 'depot'

# adjust if you are using RVM, remove if you are not
set :rvm_type, :user
set :rvm_ruby_string, 'ruby-2.0.0-p353'
require 'rvm/capistrano'

# file paths
set :repository,  "#{user}@#{domain}:git/#{application}.git" 

# stages
set :stages, ["staging", "production"]
set :default_stage, "staging"

# distribute your applications across servers (the instructions below put them
# all on the same server, defined above as 'domain', adjust as necessary)
role :app, domain
role :web, domain
role :db, domain, :primary => true

# you might need to set this if you aren't seeing password prompts
# default_run_options[:pty] = true

# As Capistrano executes in a non-interactive mode and therefore doesn't cause
# any of your shell profile scripts to be run, the following might be needed
# if (for example) you have locally installed gems or applications.  Note:
# this needs to contain the full values for the variables set, not simply
# the deltas.
# default_environment['PATH']=':/usr/local/bin:/usr/bin:/bin'
# default_environment['GEM_PATH']=':/usr/lib/ruby/gems/1.8'

# miscellaneous options
set :deploy_via, :remote_cache
set :scm, 'git'
set :branch, 'master'
set :scm_verbose, true
set :use_sudo, false
set :normalize_asset_timestamps, false

namespace :deploy do
  desc "cause Passenger to initiate a restart"
  task :restart do
    run "touch #{current_path}/tmp/restart.txt" 
  end

  desc "reload the database with seed data"
  task :seed do
    deploy.migrations
    run "cd #{current_path}; rake db:seed RAILS_ENV=#{rails_env}"
  end
end
4. Create staging and production deployment files
$ cd config
$ mkdir deploy
$ vi production.rb
require "rvm/capistrano"                  # Load RVM's capistrano plugin.
set :rvm_ruby_string, 'ruby-2.0.0-p353'   # Or whatever env you want it to run in.
set :rvm_bin_path, '/home/samdc/.rvm/bin'
server "deployment_server_name", :app, :web, :db, :primary => true
set :deploy_to, "/home/samdc/apps/depot"
$ vi staging.rb
require "rvm/capistrano"                  # Load RVM's capistrano plugin.
set :rvm_ruby_string, 'ruby-2.0.0-p353'   # Or whatever env you want it to run in.
set :rvm_bin_path, '/home/samdc/.rvm/bin'
server "deployment_server_name", :app, :web, :db, :primary => true
set :deploy_to, "/home/samdc/apps/depot_staging"
5. First time deployment, setup basic dir structure on deployment server
$ cap deploy:setup
Uncomment default_run_options line in deploy.rb if there is any failure.

6. Check the config.
$ cap deploy:check
7. We can load seed data.
$ cap deploy:seed
8. Deploy
$ git add .
$ git commit -m "add cap files"
$ git push
$ cap deploy
Remember this deploys to the default "staging" server. To deploy to production...
$ cap production deploy
9. Rollback deployment
$ cap deploy:rollback

Further reading:
http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html
https://github.com/capistrano/capistrano/wiki/2.x-From-The-Beginning

Install and Configure MariaDB on CentOS 6

1. Go to repository generator, select the desired repository. In my case, I got this:
# MariaDB 5.5 CentOS repository list - created 2013-12-07 02:35 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/5.5/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
2. Create a new repo, and put the generated text above.
$ sudo vi /etc/yum.repos.d/MariaDB.repo
3. Install
$ sudo yum install MariaDB-server MariaDB-client MariaDB-devel MariaDB-common
4. Start mysql
$ sudo /etc/init.d/mysql start
$ sudo /sbin/chkconfig mysql on
5. Autostart mysql
Find out the name of service’s script from /etc/init.d/ directory e.g. mysqld or httpd
Add it to chkconfig
$ sudo /sbin/chkconfig --add mysqld
Make sure it is in the chkconfig.
$ sudo /sbin/chkconfig --list mysqld
Set it to autostart
$ sudo /sbin/chkconfig mysqld on
6. Setup mysql Login as root:
[samdc@perfdb4 apps]$ mysql -u root
Set root password:
MariaDB [(none)]> set password for root@localhost=password('mypass');
MariaDB [(none)]> set password for root@'127.0.0.1'=password('mypass');
MariaDB [(none)]> set password for root@'machine.domain.com'=password('mypass');
Delete anonymous:
MariaDB [(none)]> delete from mysql.user where user='';
7. Create db and user: Create db:
MariaDB [(none)]> create database mydb;
Create user myuser with password mypass:
MariaDB [(none)]> grant all on mydb.* to 'mydb' identified by 'mypass';
MariaDB [(none)]> grant all on mydb.* to 'mydb'@'localhost' identified by 'mypass';
8. Show databases
MariaDB [(none)]> show databases;

SSH Issue While Deploying Rails App Via Capistrano

Learned some lessons today about SSH and how to troubleshoot. While setting up Capistrano to deploy for the first time, I was getting this error message:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)
As it turned out, SSH is very picky when it comes to permissions. The solution is to set proper permissions for ssh authorized_keys file. Symptom is this error message from /var/log/secure
Authentication refused: bad ownership or modes for file /home/samdc/.ssh/authorized_keys
Which means, its a file permission issue as noted in this post.

Following that...
$ chmod g-w /home/samdc
$ chmod 700 /home/samdc/.ssh
$ chmod 600 /home/samdc/.ssh/authorized_keys
One thing to note is that when accessing that location using a different account, we have to make sure to copy the public key of that different account to the same authorized_keys file.

12.04.2013

How to Deploy a Rails App to Apache with Passenger

This guide is for Fedora Core 19, but I think it should be fine for any Linux machines...

Prepare System

1. Create a local account that will be used for passenger config
$ sudo useradd samdc
$ sudo passwd samdc
$ su - samdc
2. Install RVM and Ruby using this post (How to Install RVM, Ruby and Rails), up to step 10.

Install Passenger

3. Start apache
$ sudo apachectl start
4. Install passenger
$ gem install passenger
$ passenger-install-apache2-module
This runs the installer...
Press enter. The installer will check for required software, if the dependencies are not met, it will tell you what to install...
5. Install all missing dependencies and re-run the install
$ sudo yum install httpd-devel
$ sudo yum install apr-devel
$ sudo yum install apr-util-devel
$ passenger-install-apache2-module
A number of sources will be compiled and after that it will ask to update our Apache config...
6. To find out where the Apache config file is, try these commands
$ apachectl -V | grep HTTPD_ROOT
 -D HTTPD_ROOT="/etc/httpd"
$ apachectl -V | grep SERVER_CONFIG_FILE
 -D SERVER_CONFIG_FILE="conf/httpd.conf"
From that, our config file is in /etc/httpd/conf/httpd.conf

7. Our Apache config has this at the end.
$ cat /etc/httpd/conf/httpd.conf
...
IncludeOptional conf.d/\*.conf
Which means we can maintain our extensions separately. In our case, what we want to do is to create a file called passenger.conf, then we can add the lines as indicated by the passenger installer from step 5 of this guide.
$ sudo vi /etc/httpd/conf.d/passenger.conf
$ cat /etc/httpd/conf.d/passenger.conf
LoadModule passenger_module /home/samdc/.rvm/gems/ruby-2.0.0-p353/gems/passenger-4.0.26/buildout/apache2/mod_passenger.so
PassengerRoot /home/samdc/.rvm/gems/ruby-2.0.0-p353/gems/passenger-4.0.26
PassengerDefaultRuby /home/samdc/.rvm/wrappers/ruby-2.0.0-p353/ruby

Configure Apache

8. Create directories that we will use later
$ sudo mkdir /etc/httpd/sites-available
$ sudo mkdir /etc/httpd/sites-enabled
9. Add a virtual host for our rails app
$ sudo vi /etc/httpd/sites-available/depot.conf
<VirtualHost *:80>
   ServerName www.depot.com
   ServerAlias depot.com
   DocumentRoot /home/samdc/prod/depot/public
   <Directory /home/samdc/prod/depot/public>
      AllowOverride all
      Options all 
      Require all granted
   </Directory>
</VirtualHost>
10. Tell Apache about our virtual hosts
$ vi /etc/httpd/conf/httpd.conf
Add this at the bottom:
Include sites-enabled/*.conf
11. Link the virtual host definition to sites-enabled
$ sudo ln -s /etc/httpd/sites-available/depot.conf /etc/httpd/sites-enabled/depot.conf
12. Add ServerName entry to /etc/hosts file
$ vi /etc/hosts
127.0.0.1 www.depot.com
127.0.0.1 depot.com

Configure SELinux

13. Suspend SELinux
$ sudo setenforce 0
14. Install checkpolicy
$ sudo yum install checkpolicy
15. Walk through SELinux log and generate new SELinux policy module
$ sudo grep httpd /var/log/audit/audit.log | /usr/bin/audit2allow -M passenger
16. Make policy active
$ sudo semodule -i passenger.pp
17. Switch SELinux back to enforcing mode
$ sudo setenforce 1
18. Restart Apache
$ sudo apachectl restart

Deploy Rails App

19. Copy all files to the deploy directory
$ cp -r /home/samdc/dev/depot/ /home/samdc/prod/
20. Install all gems required
$ cd /home/samdc/prod/depot/
If using a different db in production, e.g., mysql, change the Gemfile to add that for production
$ vi Gemfile
group :production do
  gem 'mysql2'
end
$ bundle install
21. Create the database
$ mysql -u root -p
> CREATE DATABASE depot_production DEFAULT CHARACTER SET utf8;
> GRANT ALL PRIVILEGES ON depot_production.* TO 'username'@'localhost' IDENTIFIED BY 'password';
> EXIT;
22. Configure rails production yml file
$ vi config/database.yml
production:
  adapter: mysql2
  encoding: utf8
  reconnect: false 
  database: depot_production
  pool: 5
  username: username
  password: password
  host: localhost
23. Lets load the database
$ rake db:setup RAILS_ENV="production"
$ rake db:seed
24. Change production environment settings
$ vi config/environments/production.rb
config.serve_static_assets = true
config.assets.compile = true
25. Precompile assets
$ rake assets:precompile
26. Now browse to http://depot.com