How to deploy a Rails 3 application with Phusion Passenger
About this tutorial
This tutorial will show you how to deploy a brand new Rails 3 application to either the root domain (http://yourdomain.com/) of your account, or a sub-domain (http://sub.yourdomain.com/). Deploying to a sub-directory (http://yourdomain.com/railsapp/) is also possible, but you will need to make sure to modify your routes configuration (routes.rb), which will be shown later.
Notes: Most of these steps can only be completed via command line, so we do assume that you are fairly comfortable with SSH and using command-line tools and editors. I will be using the ‘vim’ editor in my demonstration, but you are free to use any editor you prefer.
Deployment method: Phusion Passenger
Although cPanel has chosen to go with a Mongrel-based system for Rails deployment, we do not use that configuration and instead have chosen to use Phusion Passenger for all Rails deployment across our fleet. We have found that Passenger is more reliable and performs better. We use Phusion Passenger on many of our internal projects at Site5 too!
Gem management with Bundler
If you are familiar with Rails 3, you will know that Bundler is now the standard way to manage and install your gems within a Rails 3 application. It is also possible to use Bundler with a Rails 2.3 application, which we highly recommend. You can read more about that here: http://gembundler.com/rails23.html.
Most of our servers already have the Rails 3 gem pre-installed (or will soon), but in the event that you don’t have it on your server, you can easily install it yourself inside your account. To check which version of Rails you have configured, type the following command while logged in via SSH:
DON’T SKIP: Please check our tutorial on setting up a custom RubyGems environment, which will also show you how to install the latest version of Rails. This is needed to move forward.
NOTE: Where you see the USERNAME in capital letters is a location where you need to fill in your actual Site5 account username. Additionally, when you see the tilde (~) used, this is just a method in Linux to reference your home directory without having to write it out in full. The $HOME environment variable will also do the same thing. It’s helpful for tutorials so you can simply copy and paste the commands in without having to modify a bunch of the paths. As an example:
-jailshell-3.2$ echo ~ /home/USERNAME
-jailshell-3.2$ echo $HOME /home/USERNAME
-jailshell-3.2$ pwd /home/USERNAME
Creating a test application
1. Now that we have Rails 3 configured, let’s get a test application setup. I will be storing my application in /home/USERNAME/rails3test. You are free to install your application wherever you want, but this guide will reference the rails3test directory.
To create a blank project, run the following command (notice that it has changed since Rails 2.x):
rails new ~/rails3test -d mysql
2. I’m going to be setting up my application in my root public_html, but you are free to install anywhere you would like. We need to move the existing public_html out of the way:
mv ~/public_html ~/public_html.moved
And setup the symbolic link:
ln -s ~/rails3test/public ~/public_html
3. As usual, we need to remove the default index.html installed with the default application:
rm -f ~/rails3test/public/index.html
Now would also be a good time to enable Phusion Passenger. You may run the following one line command to add the necessary lines:
echo -e "PassengerEnabled On\nPassengerAppRoot $HOME/rails3test\n" > ~/rails3test/public/.htaccess
Or you may add the lines below manually to the .htaccess file (/home/USERNAME/rails3test/public/.htaccess):
PassengerEnabled On PassengerAppRoot /home/USERNAME/rails3test
4. Now we need to configure Bundler (it is already installed on your Site5 server). Bundler manages all gems in a file called “Gemfile” in the root directory of your application (~/rails3test/Gemfile). If you ever want to install more gems for this application, that is the file you need to edit. Open it up in your text editor and you can see that the format is fairly easy to understand. Your Gemfile should look similar to the one below:
Please ensure that you have at least the same gems as listed in our Gemfile when first setting up your application. You can add more items later, as needed.
source 'http://rubygems.org' gem 'rails', '3.1.0' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'mysql2' gem 'json' # Gems used only for assets and not required # in production environments by default. group :assets do gem 'sass-rails', ' ~> 3.1.0' gem 'execjs' gem 'libv8', '188.8.131.52' gem 'therubyracer', '0.10.2' gem 'coffee-rails', ' ~> 3.1.0' gem 'uglifier' end gem 'jquery-rails' # Use unicorn as the web server # gem 'unicorn' # Deploy with Capistrano # gem 'capistrano' # To use debugger # gem 'ruby-debug'
NOTE: This would be a good time to add any other gems you would need (nokogiri, etc.). Ryan over at Railscasts.com has a great screencast on Bundler if you want to learn more: http://railscasts.com/episodes/201-bundler.
5. Now that we have our Bundler Gemfile setup, we need to install them! Run the following command to install those gems and their dependencies:
cd ~/rails3test/; bundle install --path vendor/bundle
That command will install all of those gems into ‘vendor/bundle’ inside your application directory. Remember, this means that you will need to setup Bundler and the Gemfile for each separate application on your account.
6. At this point your application will now have Passenger properly detecting Bundler and Rails 3, but if we want to get a fully functioning app we must setup MySQL and our routing.
Start by logging in to your control panel (or SiteAdmin) and create a new MySQL username and database. Once you have those created, save the information somewhere safe as we’ll need it in a second. Now, open up the following file on your account in your text editor:
You will see the database configuration settings for the development, test, and production environments. Passenger runs under the production environment, so we will be editing that section. It should look something like this when finished but filled in with your database login information:
production: adapter: mysql2 encoding: utf8 reconnect: true database: USERNAME_rails3test pool: 5 username: USERNAME_rails3test password: myverysecurepassword
Save that file and close it.
7. Next, let’s generate some scaffolding. In this example we’ll call it ‘User’ and it will store a name and the age of that person. Run the following command from inside your application directory:
cd ~/rails3test/; rails generate scaffold User name:string age:integer
As you can see, the generator changed in Rails 3.x. That command will create a controller called ‘Users’ and all the necessary methods (index/edit/show/new) to interact with our database. It will also create a migration file (db/migrate/20101007121721_create_users.rb) for our database.
Next thing you need to do is run a database migration so the new table is created in our MySQL database:
cd ~/rails3test/; rake db:migrate --trace RAILS_ENV='production'
You should see something like this:
(in /home/USERNAME/rails3test) ** Invoke db:migrate (first_time) ** Invoke environment (first_time) ** Execute environment ** Invoke db:load_config (first_time) ** Invoke rails_env (first_time) ** Execute rails_env ** Execute db:load_config ** Execute db:migrate == CreateUsers: migrating ==================================================== -- create_table(:users) -> 0.0795s == CreateUsers: migrated (0.0796s) =========================================== ** Invoke db:schema:dump (first_time) ** Invoke db:load_config ** Execute db:schema:dump
8. Now we need to setup our routing so the ‘Users’ controller is the default route and the first thing you see when you go to our site. Open up the following file:
Look for the “root :to =>” line towards the bottom of the file (it will be commented out). Adjust that line to say the following:
root :to => "users#index"
(it is important that the # is removed from the beginning of the line)
Save your changes and close the file.
9. If you’ve accessed your site during this tutorial, you will need to force Passenger to restart the app to detect these changes. Run the following command to force a restart:
Then refresh your website in your web browser and everything should be working. Success!
You should be presented with a simple page displaying the users in the database. It will look like this:
Listing users Name Age New User
Click on “New User” to create a new user.
Common Problems & Errors
1. If you are trying to use any of the “rails” commands (generate scaffolding) and the following error comes up:
Fix: You are missing the “execjs” and “therubyracer” gems. Simply add those gems to your Gemfile then re-bundle:
cd ~/rails3test/; echo -e "gem 'execjs'\ngem 'therubyracer'" >> Gemfile; bundle install --path vendor/bundle
2.If your application won’t start and you are receiving the following error in your production.log:
Processing by UsersController#index as HTML Rendered users/index.html.erb within layouts/application (0.3ms) Completed 500 Internal Server Error in 2ms ActionView::Template::Error (application.css isn't precompiled):
Fix: You need to precompile your CSS when you’re in a production environment (you will always use production with Passenger):
cd ~/rails3test/; rake assets:precompile
Then, make sure you restart your app:
3. If you are receiving a 404 error when accessing your site, that is most likely a routing issue. Check your routes.rb file and also run a ‘rake routes’ in your application directory to make sure you have everything configured properly.
4. If you receive a “Access denied for user ‘root’@'localhost’ (using password: NO)” when attempting to ‘rake db:migrate’ make sure you have the RAILS_ENV variable specified or else it will default to migrating your development database when we want to migrate our production database.
5. If you still receive a “Access denied for user ‘USERNAME_rails2@’localhost’ then you might have forgot to add the MySQL user to your database in your control panel. Creating a MySQL user is not enough to grant the appropriate access, the user must be granted privileges to the specific database. This can be done from your control panel (or SiteAdmin) interface.
Feel free to post any comments or suggestions you may have below. You may also contact our Support Team if you need assistance setting this up on your account. You may submit a support ticket via Backstage.