Installing Ruby Enterprise Edition, Apache, MySQL, and Passenger for deploying Rails 3.0 applications.
Get a Linode, and set it up with Ubuntu 10.04 LTS so that you have till April 2013 to get updates. Once the Linode is formatted, boot it and continue on.
Set up an 'A' record in your DNS, pointing to the IP of your Linode. I'm using demo.napcs.com
here.
Log in with ssh root@your_ip
Add a user
adduser deploy
Add the user to the SUDOERS list with visudo
# User privilege specification
root ALL=(ALL) ALL
deploy ALL=(ALL) ALL
Change the default SSH port and disallow root acces. vim /etc/ssh/sshd_config
# What ports, IPs and protocols we listen for
Port 16888
...
PermitRootLogin no
Logout and reboot your linode via the console. Don't attempt to restart SSHD while connected. :)
Test the new settings - Log back in with ssh deploy@your_ip -p 16888
and log out again
Create your authorized keys file
mkdir ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Logout and upload your public key
cat ~/.ssh/id_rsa.pub | ssh deploy@your_ip -p 16888 'cat >> .ssh/authorized_keys'
That looks a little complex, but we're just printing out the SSH key,
piping the output to SSH and directing it into the authorized_keys
on the remote server.
You could do this many ways, but this is something you could turn into a script and use this
to add multiple keys.
Log back in and you're set with keys.
sudo apt-get install apache2 git-core
Now disable the default site.
sudo a2dissite default
sudo /etc/init.d/apache2 restart
sudo wget --no-check-certificate https://github.com/j2fly/oh-my-zsh/raw/master/tools/install.sh -O - | sh
-
Edit the ~/.oh-my-zsh/lib/rvm.zsh so that it points to /usr/local/rvm/bin/rvm-prompt
-
edit the ~/.oh-my-zsh/themes/j2fly.zsh-theme so that it points to /usr/local/rvm/bin/rvm-prompt as well
-
Edit your ~/.zshrc so that it has the RVM stuff in it.
-
You may also need to edit/move the export PATH= line to be above the zsh load line
---
gem: --no-rdoc --no-ri
:benchmark: false
:backtrace: false
:update_sources: true
:verbose: true
:bulk_threshold: 1000
:sources:
- http://rubygems.org/
We'll use Ruby Enterprise Edition through RVM
-
Install RVM
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
-
Install some required libraries to allow for RVM to build REE
sudo apt-get install build-essential patch zlib1g-dev libssl-dev libreadline5-dev
-
Install Ruby Enterprise Edition
rvmsudo rvm install ree
-
Use the global gemset and install bundler into it
rvm gemset use global gem install bundler
-
set default ruby
rvmsudo rvm --default use ree
We install MySQL with the package manager:
sudo apt-get install mysql-server libmysqlclient-dev
gem install mysql
Now log into mysql with mysql -u root -p
and create a user
create user 'rails'@'localhost' identified by 'rails';
create databse projects_production;
grant all on projects_production.* to 'rails'@'localhost';
SET PASSWORD FOR 'rails'@'localhost' = PASSWORD('newpass');
These permissions are not the greatest. They could be hardened. But you have to make sure you don't tighten them too much to the point where you can't run migrations. Read a good MySQL book.
rvm use ree
rvm gemset use global
rvmsudo gem install passenger
sudo apt-get install libcurl4-openssl-dev apache2-prefork-dev libapr1-dev libaprutil1-dev
rvmsudo /usr/local/rvm/gems/ree-1.8.7-2011.03@global/bin/passenger-install-apache2-module
Follow the instructions.
CD to /etc/apache2/conf.d
and add a file called "passenger.conf" which has the following contents:
LoadModule passenger_module /usr/local/rvm/gems/ree-1.8.7-2011.03@global/gems/passenger-3.0.7/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/rvm/gems/ree-1.8.7-2011.03@global/gems/passenger-3.0.7
PassengerRuby /usr/local/rvm/wrappers/ree-1.8.7-2011.03@global/ruby
Create a new vhost
sudo vim /etc/apache2/sites-available/demo.napcs.com
Put this code in the file:
<VirtualHost *:80>
ServerName demo.napcs.com
DocumentRoot /var/www/demo.napcs.com/current/public
<Directory /var/www/demo.napcs.com/current/public>
AllowOverride all
Options -MultiViews
Then enable the site
sudo a2ensite demo.napcs.com
sudo /etc/init.d/apache2 restart
And give the deploy
user permissions to the /var/www
root folder:
sudo chown -R deploy:deploy /var/www
Again, not the best approach, but an acceptable one.
We're done with server setup!
Create the Rails 3 application. We'll do a simple one with a single table.
rails new demo
cd demo
rails g scaffold projects name:string description:text
rake db:migrate
rm public/index.html
Add a root route to config/routes.rb
root :to => "projects#index"
Add the mysql2
gem to your Gemfile and get the sqlite3 one only in dev mode. Specify the version numbers for the gems or you'll get burned!'
group :development do
gem 'sqlite3', '1.3.3'
end
group :production do
gem 'mysql2', '0.2.7'
end
Then
bundle
Let's deploy!
Generate the capistrano config file:
capify .
Modify the config/deploy.rb
file with our settings for our server.
require 'bundler/capistrano'
set :application, "demo.napcs.com"
# Deploy from your local Git repo by cloning and uploading a tarball
set :scm, :git
set :repository, "."
set :deploy_via, :copy
set :user, :deploy
set :deploy_to, "/var/www/#{application}"
set :use_sudo, false
role :web, "demo.napcs.com" # Your HTTP server, Apache/etc
role :app, "demo.napcs.com" # This may be the same as your `Web` server
role :db, "demo.napcs.com", :primary => true # This is where Rails migrations will run
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
Pay attention to this part:
set :scm, :git
set :repository, "."
set :deploy_via, :copy
This lets you from your local Git repo by cloning and uploading a tarball. This means you can push code from your computer to your server, rather than having to pull code from your remote Git repository to your server. Or if Github is down.
Now specify your production database info in database.yml
:
production:
adapter: mysql2
host: localhost
database: projects_production
username: rails
password: rails
Here, we're putting our production db password in our database.yml
file.
You probably want to keep this file out of your repository, and instead
write a custom Capistrano task to build the database.yml
file during
deployment. That's something you can Google on your own.
Now make a Git repo
git init
git add .
git commit -a -m "Initial import"
Create the application directory on the server:
cd /var/www/
sudo mkdir domain.com
sudo chown deploy:www-data domain.com
sudo chmod 775 domain.com
Finally, set up the app to the server:
cap deploy:setup
Deploy the app
cap deploy:cold
And we're done! At this point, make changes to your code, commit them, redeploy with
cap deploy
Add this to deploy.rb
desc "tail production log files"
task :tail_logs, :roles => :app do
run "tail -f #{shared_path}/log/production.log" do |channel, stream, data|
puts # for an extra line break before the host name
puts "#{channel[:host]}: #{data}"
break if stream == :err
end
end
Then run it with
cap tail_logs
Capistrano isn't just for deploying Rails apps. You can use it to automate anything you do with SSH.