Rails setup on Linode

Posted by chris olsen on September 13, 2007

******
An updated version of this post has been made here.
******
I like Rails. I like its elegance. I like how adhering to the DRY principle is made easy and I like the way that I can look at code written by someone else and instantly understand what they were doing. With all this likeness going around you would think that I am on cloud 9. The truth is there is something that makes me a little nervous about it, and that is deployment.

So how do you deploy a Rails application? Not too long ago I was browsing the internet for the answer to this question and in almost every response there was the lack of an actual answer, and the ones that consisted of an answer were clearly wrong. The truth is that there is no one answer, and you just have to accept that.

A couple of days ago Bryan Liles put together a nice video run through of setting up a VPS at Linode and gave some very good instructions on how to do so from the start to the finish. Personally, I like having documented instructions to allow for easy later reference and that is what this is. All the instructions are shown below along with some extras in case you are lacking an SVN repository server.

Before you start you have to decide where you are deploying to. If you would like to deploy to a VPS at linode that’s cool, but if you would like to deploy to a local server that’s cool too. The only catch is that the local server either has to provide you with a VPS within it, or you are able to re-install a fresh linux distro on it.

If you are working with a local server you will have to download the distro. All the instructions within this article are for Debian 4.0 so that is what I would recommend. Download the iso file, burn it to a CD, pop it in to server, re-boot and install.

If you have decided to go with Linode, sign in, click on the Dashboard, then click on the “Deploy a Linux Distribution” link. Here you will be able to select a distro and set up the disk partitions. The setup should only take a couple minutes.

Whether you are working on a local or remote machine all the instructions consist of remotely logging into the server with ssh.

#linode machine
ssh root@ip_address
#local machine
ssh root_name@ip_address

Server

Once logged into the server we need to ensure everything is up to date

apt-get update
apt-get upgrade

If you are installing to a local machine you will have to install openssh.

apt-get install openssh-server

For a local server you will also want a static ip address for the server, so you will have to make a couple tweaks to the interfaces file. Make a backup of the file then open the networks file with your editor of choice.

cp /etc/network/interfaces /etc/network/interfaces.old
vi /etc/network/interfaces

The updates that you make will depend on how you have your network setup, but what is below will probably work for most people.

allow-hotplug eth0
iface eth0 inet static
address 192.168.1.202
network 192.168.1.0
gateway 192.168.1.1
broadcast 192.168.1.255
netmask 255.255.255.0

Then to ensure that ip address is updated restart the network

/etc/init.d/networking restart

We will also have to install a few other libraries. ***Write the password mysql asks you for down so you don’t forget it later. I know you aren’t supposed to write them down, but you have to trust me that it can save you a lot of headache later if you are overly creative with passwords and you suddenly can’t remember what you came up with later on in the setup.

apt-get install ruby1.8-dev ri irb rdoc libmysql-ruby mysql-server nginx subversion build-essential sudo

We will also need the ruby gems. At the time of writing the below is the most recent, but you may want to check if a new release is available.

wget http://rubyforge.org/frs/download.php/20989/rubygems-0.9.4.tgz
tar xzvf rubygems-0.9.4.tgz
cd rubygems-0.9.4
ruby setup.rb

When I was setting things up the first time rails did not install properly when including it in the previous apt-get, so to keep on the safe side we will install it separately. If you get an error when running the following just run it again. This is a well known quirk, but is definitely not something that is overly obvious to someone who hasn’t seen it before.

gem install rails --include-dependencies

Let’s also install mongrel and the mongrel cluster.

gem install mongrel -y
gem install mongrel_cluster -y

To allow Capistrano to access the server on deploy grant permissions to mongrel (we will create this user in a bit). The export command is only called if you would like to use vi to make the updates. I believe Pico is the default.

export VISUAL=vi
visudo

Add the following line just under where root is granted all permissions. More information on this can be found here.

mongrel ALL=(ALL) NOPASSWD:ALL

Local

Let us first make sure that Capistrano v2.x is installed.

cap --version

If you see some output like $ Capistrano v2.x.x then all is good if not run the following:

sudo gem install capistrano -y

If you do not currently have an ssh key, you can create one with the commands below. If you would rather create an rsa key just replace the dsa with, you guessed it, rsa. Then we need to upload the public key to the server.

For for more info on the differences check this post out.

ssh-keygen -t dsa
scp ~/.ssh/id_dsa.pub root@ip_address:~/my_id

Now that the key is copied up onto the server we will make sure that it is in the proper folder. So back to the server we go. Can you now understand why accessing the server remotely is the best option?

Server

Since we earlier granted access to the mongrel user we really should create a user that goes by the name of mongrel. If you also set up Subversion on the server you will have to perform the following steps for each of the developers that will be working on the project (although there is other ways of granting access, but that is out of scope right now).

useradd -m mongrel
su - mongrel
mkdir ~/.ssh
chmod 700 ~/.ssh
cat /root/my_id >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Time to setup a folder where all the subversion repositories will be kept.

** I am a little unsure of the last line below, but that is the only way that I could get things to work. The access denial is a common problem, but solutions that have worked for others would not work for me so this is what I’ve had to settle with for now.

mkdir /svn
mkdir /svn/project_name
svnadmin create /svn/my_first_project/trunk
chmod -R 777 /svn/project_name/trunk/db

Local

If this is a brand spankin’ new project we will have to create the root folder and check out the empty project from the server. The following will create a main project folder, then the svn command will create a trunk folder within it. We will then create a new project within the trunk folder by calling on the rails command and check in the required folders and contents.

cd ~/your_rails_project_dir
mkdir project_name
cd project_name
svn co svn+ssh://ip_address/svn/project_name/trunk trunk
rails trunk
svn add test/ app/ Rakefile db/ components/ vendor/ README Capfile script/ doc/ config/ lib/ public/

If you have an existing project that is very close to making you famous you will just have to checkout the latest version.

cd project_name
svn co svn+ssh://ip_address/svn/project_name/trunk trunk

It is now time to bring Capistrano into the picture.

cd project_name/trunk
capify .

We now have to make some adjustments to the deploy.rb file. Bryan provides a custom version of the file that will be used. So download it from here and replace the current one.

Next we need to create a file named “spin” in the config folder.

vi config/spin

Then insert the following and save it

mongrel_rails cluster::start

Let’s now add the new file to the project and give make it executable.

svn add config/spin
svn propset svn:executable on config/spin

Before deploying we have to make sure that the repository is fully up to date, so let’s check on the status, add any files that files that have not yet been added, then commit.

svn status
svn add
svn ci -m "Ready to deploy"

There are some changes that have to be made to the nginx.conf file and Brian was kind enough to provide them to us. So all we have to do is replace the current one on the server.

scp ~/Desktop/smarticast_railsrumble/nginx.conf ip_address:~/nginx.conf

Server

su - mongrel   #unless you are already logged in as mongrel
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.old
mv ~/nginx.conf /etc/nginx/nginx.conf

Update the nginx.conf file server { root /var/rails/project_name/current/public } value to contain the name of your project. Then restart the server.

/etc/init.d/nginx restart

While we are on the server let’s create the database.

mysqladmin -u root -p create database_name

Local

Now that everything that is checked in, and the server is setup, it is time to deploy. This is the part that I have yet to not get thrown some errors. Most of them are due to an incorrect password, a HostKeyMismatch, or permission issues. I thought I would give you a heads up on this so your heart doesn’t break like that first time you got stood up…I mean everyone has been stood up at least once…right?

cap deploy:setup deploy:cold deploy:migrate

If you are getting a HostKeyMismatch error, check if the .ssh folder and the .ssh/authenticated_keys file on the server in the /home/mongrel folder has the proper ownership. If they were created while not logged in as mongrel that is likely the problem. The following should fix that.

Server

chown -R mongrel:mongrel /home/mongrel/.ssh

I have also seen permission issues due to the mongrel user being unable to create the /var/rails folder. If that is the case we can create it ourselves, make the mongrel user the owner of it and ensure it is writable.

mkdir /var/rails
chown root:mongrel /var/rails
chmod g+w /var/rails

If you have gotten this far then congrats are in order. The last thing that has to be done is to ensure that the mongrel cluster will be started if the server is rebooted.

Server

mkdir /etc/mongrel_cluster
sudo ln -s /var/rails/my_app/current/config/mongrel_cluster.yml /etc/mongrel_cluster/my_app.yml
cp /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.2/resources/mongrel_cluster /etc/init.d
sudo chmod 755 /etc/init.d/mongrel_cluster
sudo /usr/sbin/update-rc.d -f mongrel_cluster defaults

Now let’s remove the public key that we uploaded earlier.

rm ~/my_id

It is now time to reboot the server, and once it starts back up if the site is accessible it is time to celebrate. If errors are being thrown the best place to find the problem is by checking out the log files on the server.

All code updates from here on just have to be checked into the subversion repository by one of the following:

cap deploy
# or
cap deploy deploy:migrate  # if any database updates were made

I have to give a huge thanks to Bryan Liles for putting the video together. Most of the steps on here are taken straight from the video with a couple of modifications where I had problems. Hope this will help a few other people become famous after deploying the next Facebook application.

Trackbacks

Trackbacks are closed.

Comments

Leave a response

  1. Walter Cruz Sat, 16 Aug 2008 22:04:19 MDT

    Your link to the updated version has a extra dot after http!

Comments