Screencast: Deploying to AWS/EC2, Part 2
The screencast link is at the bottom; read the screencast “script” first!
In this screencast, we’ll set up a server with all of the necessary software for Apache2, MySQL, and building Ruby.
Note that for the course, I will be supplying a pre-built AMI, so you can skip this step if you just want to deploy to EC2.
Note as well that to follow this screencast, you must edit some files; in the screencast, I use vi (or vim). If you don’t know how to edit files on Linux, this will be a problem. If it is a problem, let me know and I can suggest ways to get this done without an editor.
Here we go:
- In the previous screencast, I advised you to open up port 3000 for the “basic” security group. Make sure you’ve done this.
- Create an instance using AMI image ami-1515f67c, in the us-east-1a availability zone (see the prior screencast for more on how to do this). And do not forget to include the “basic” security group!
- Log in with your key. For a public key named id-jgn-demo and a public DNS name of ec2-174-129-169-212.compute-1.amazonaws.com (to get the public instance name, right click on the instance in Elasticfox, and you will see a menu item to copy it to the clipboard), it would look like this:
ssh -i id-jgn-demo ubuntu@ec2-174-129-169-212.compute-1.amazonaws.com
- You’re logged in as ubuntu. For the installation process, you will need to be root. So . . .
sudo bash
- apt-get is the Ubuntu utility for managing installed packages. First, update your package system:
apt-get update
Then install a selection of packages (to find out what each package is for, you can check this list: http://packages.ubuntu.com/karmic/allpackages?format=txt.gz):
apt-get -y install libc6-dev libssl-dev libmysql++-dev libsqlite3-dev make build-essential libssl-dev libreadline5-dev zlib1g-dev mysql-server mysql-client libmysqlclient15-dev apache2-mpm-prefork apache2-prefork-dev libapr1-dev libaprutil1-dev postfix
When you are asked multiple times for a password for the MySQL root user, I would recommend that you press return for an empty password. This is not especially secure, but it will make some later setup easier. This is not a course in system management or security. You will also be asked some questions about Postfix (SMTP server); take the defaults.
- Download, compile, and install Ruby 1.9:
cd /tmp wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz tar xzf ruby-1.9.1-p243.tar.gz cd ruby-1.9.1-p243 ./configure --enable-shared make make install
- Download and install RubyGems:
cd /tmp wget http://files.rubyforge.vm.bytemark.co.uk/rubygems/rubygems-1.3.5.tgz tar xzf rubygems-1.3.5.tgz cd rubygems-1.3.5 ruby setup.rb
- Download, compile, and install the native MySQL driver:
cd /tmp wget http://rubyforge.org/frs/download.php/51087/mysql-ruby-2.8.1.tar.gz tar xzvf mysql-ruby-2.8.1.tar.gz cd mysql-ruby-2.8.1 sudo ruby extconf.rb make sudo make install
- Now, a few Gems. We’ll want the Sqlite3 Gem, which may be handy if you decide not to use MySQL, the Gem for Passenger (Rails/Apache2 integration), and the Rails Gem (for 2.3.3). We are specifying “–no-ri –no-rdoc” to suppress the installation of the docs, since we shouldn’t need them on our production system.
gem install rake sqlite3-ruby passenger --no-ri --no-rdoc gem install rails -v 2.3.3 --no-ri --no-rdoc
- Remember that you’re currently root. Press Control-D to end your sudo session, and return to being the “ubuntu” user.
- Now let’s create a quick test application. Notice that we’re going to run our migrations a second time in production mode:
rails myapp cd myapp script/generate scaffold Publication title:string description:text rake db:migrate RAILS_ENV=production rake db:migrate
For a quick verification, we’re just going to run the server in development mode on port 3000:
script/server
And browse into your server from your own computer, and try out the Publications scaffold. For the public name given above, it would be: http://ec2-174-129-169-212.compute-1.amazonaws.com/publications
By the way, the main reason to run your server at this point in development mode is so that you can see exception traces. If you ran it in production mode, and there was an error, the browser would just give you a standard error page. To be sure, we could look at the server output, but at this stage it is convenient to see any error that a single request generates.
- Works? Great. Control-C. Now take note of the directory in which you’ve created your application; we’re going to need that directory for the next step. For example, if you’ve followed these instructions scrupulously, your test app is in /home/ubuntu/myapp. You can check with the “pwd” command.
- To set up Passenger, we’ll need to be root again. So sudo bash, and then install the Passenger module for Apache2:
sudo bash passenger-install-apache2-module
During this install, some instructions were displayed regarding the configuration of Apache2. Here they are:
Please edit your Apache configuration file, and add these lines: LoadModule passenger_module /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.7/ext/apache2/mod_passenger.so PassengerRoot /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.7 PassengerRuby /usr/local/bin/ruby After you restart Apache, you are ready to deploy any number of Ruby on Rails applications on Apache, without any further Ruby on Rails-specific configuration!
and
Suppose you have a Rails application in /somewhere. Add a virtual host to your Apache configuration file and set its DocumentRoot to /somewhere/public: <VirtualHost *:80> ServerName www.yourhost.com DocumentRoot /somewhere/public # <-- be sure to point to 'public'! <Directory /somewhere/public> AllowOverride all # <-- relax Apache security settings Options -MultiViews # <-- MultiViews must be turned off </Directory> </VirtualHost>Additional configuration for Apache2 goes into files in /etc/apache2/conf.d, so we are going to put the first set of configurations i /etc/apache2/conf.d/passenger. Mine looks like this:
LoadModule passenger_module /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.7/ext/apache2/mod_passenger.so PassengerRoot /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.7 PassengerRuby /usr/local/bin/ruby
Next, we’re going to put the second block of configuration into /etc/apache2/sites-available/default — there is already a file there, but you can overwrite it.
Mine looks like this:
<VirtualHost *:80> ServerName ec2-174-129-169-212.compute-1.amazonaws.com DocumentRoot /home/ubuntu/myapp/public <Directory /home/ubuntu/myapp/public> AllowOverride all Options -MultiViews </Directory> </VirtualHost>(There is also a directory called under /etc/apache2 called sites-enabled/ — the files here are symlinked to the files in sites/available. If you look, you’ll see a file in /etc/apache2/sites-enabled/000-default; that’s symlinked to /etc/apache2/sites-available/default)
- Regrettably, there is a nasty bug in the version of Rack (server layer) that ships with Passenger. You must edit the file /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.7/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb and change the line
if filesystem_has_posix_semantics?
to
if filesystem_has_posix_semantics? && "#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" < "1.9.1.152" - To restart Apache2, make sure you’re currently root, and enter
/etc/init.d/apache2 restart
Now browse in again to verify. Apps running under Passenger are running in production mode, and production apps will run on port 80. So you would browse to (changing your host name with mine) http://ec2-174-129-169-212.compute-1.amazonaws.com/publications
- Everything work? Great. On to the Capistrano! (Next screencast.)
On Windows, using the cmd as the shell, the windows that pop up during the MySQL installation are not nicely rendered. An upper ASCII problem. Maybe this is better from Cygwin bash?
@Ken
Hmm . . . you might try switching into bash first, and see if that helps.
Another possibility would be to use putty (google for the download) as your ssh client; but this requires converting the Unix-style ssh key to a format compatiblity with putty; still, putty is very, very good. And free).
In the screencast on step 14, you neglect to paste the && into the altered line. You only paste "#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" < "1.9.1.152".
@Ken
I think I added a comment to that effect a bit further in the screencast (when I go in and fix the wrongly-pasted code).
This instructions were easy to follow -- even on Windows.
Is there a pre-built ami instances for the class yet?
I saw it mentioned above that one was comming but haven't been able to find it.
@DavidL
Here's the AMI id for the pre-built instance: ami-c045a7a9
This has all of the software and the sample project in the ubuntu user's root dir. It is tweaked so that I or the staff can log into it (if you give us your public DNS name).
I'll add a bit to the screencast script that talks about this -- later.