Torquebox is JRuby application server based on JBoss. What’s an application server? It’s a bundle of web server, messaging queue, JRuby runtime and websocket infrastructure. It is pretty cool and we use it in AmberBit to deploy a few hight-traffic web applications we developed for our clients.
As nice as it is, having it’s roots in Java world, and being sponsored by Red Hat (who we send lots of love doing that, BTW), Torquebox is also quite hard to set up and get running on Ubuntu 12.04, unless you know exactly what you are doing.
This is a step-by-step guide on setting up Torquebox 3.0.1 on Ubuntu 12.04. I am using DigitalOcean VPS with 2GB RAM, but anything else will also do the job. Just give it some RAM, remember: JRuby and Java are memory-hungry!
Dependencies
We’ll need a few tools, most notably git, JavaScript runtime and JRE.
apt-get install git unzip nodejs openjdk-7-jre-headless wget
Torquebox installation
wget http://torquebox.org/release/org/torquebox/torquebox-dist/3.0.1/torquebox-dist-3.0.1-bin.zip
unzip torquebox-dist-3.0.1-bin.zip
mv torquebox-3.0.1/ /opt/torquebox
We want to create “torquebox” user in the system and make him owner of Torquebox installation with:
adduser torquebox
chown torquebox.torquebox -R /opt/torquebox/
To set up environment variables, we create /etc/profile.d/torquebox.sh with following contents:
export TORQUEBOX_HOME=/opt/torquebox
export JBOSS_HOME=$TORQUEBOX_HOME/jboss
export JRUBY_HOME=$TORQUEBOX_HOME/jruby
export PATH=$JRUBY_HOME/bin:$PATH
Do not forget to source that file or sign out and log into your server again so the environment variables should pick up. We can verify that our JRuby/Torquebox installation is working with:
jruby -S irb
If it brings up IRB prompt, our Torquebox/JRuby installation is probably good to go.
One last bit is to set up init scripts, you can do it with:
cd /opt/torquebox
rake torquebox:upstart:install
This should create the /etc/init/torquebox.conf. Unfortunately the file did not autostart Torquebox for me, as it depends on non-existing service - I think it’s created for different version of Ubuntu. I had to slightly change it to work on our company’s VPS:
/etc/init/torquebox.conf:
description "This is an upstart job file for TorqueBox"
pre-start script
bash << "EOF"
mkdir -p /var/log/torquebox
chown -R torquebox /var/log/torquebox
EOF
end script
start on started network-interface
stop on stopped network-interface
respawn
limit nofile 4096 4096
script
bash << "EOF"
su - torquebox
/opt/torquebox/jboss/bin/standalone.sh >> /var/log/torquebox/torquebox.log 2>&1
EOF
end script
We can now start our Torquebox application server with:
service torquebox start
Torquebox will also be started automatically on server restarts. This means our Ruby on Rails web applications will start itself up even when you need to do a hard restart. Pretty sweet.
Torquebox will listen on http://localhost:8080 and happily serve blank white 404 page for you. It will not listen on any public interface by default. If you, however, want it to - change all occurences of 127.0.0.1 to 0.0.0.0 in file /opt/torquebox/jboss/standalone/configuration/standalone.xml.
Nginx as a proxy
You don’t need Nginx to do the proxy web traffic for you. I just like it. You can use iptables rule to forward your public IP port 80 to port 8080, use rinetd, run Torquebox as root (sic!) and bind directly to port 80 etc. Nginx, however, gives you some nice options like setting maximum body size, logging, more control over HTTP headers.
apt-get install nginx
/etc/nginx/sites-enabled/default:
server {
listen 80;
server_name example.com; # do change me!
location / {
access_log off;
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Restart your Nginx and you’ll server should now also serve you a white blank web page, directly from Torquebox:
service nginx restart
Ruby on Rails application and Capistrano (v2) recipe
Capistrano is one of the simplest ways to deploy Ruby on Rails web applications. We will use version 2 here, since Torquebox has integration for this version at the moment. The recipe, however, should work with some modifications on Capistrano 3 as well.
Add these two lines to your Gemfile:
gem 'capistrano', '~> 2.15.4'
gem 'torquebox'
gem 'torquebox-capistrano-support'
and run “bundle install”.
You also want to add this Capistrano recipe to your Ruby on Rails application (config/deploy.rb):
require 'torquebox-capistrano-support'
require 'bundler/capistrano'
set :application, "myapp"
set :torquebox_home, '/opt/torquebox'
set :jboss_home, "#{torquebox_home}/jboss"
set :jruby_home, "#{torquebox_home}/jruby"
set :bundle_dir, "~/shared"
set :default_environment, {
"TORQUEBOX_HOME"=>"/opt/torquebox",
"JBOSS_HOME"=>"/opt/torquebox/jboss",
"JRUBY_HOME"=>"/opt/torquebox/jruby",
"PATH"=>"/opt/torquebox/jruby/bin:$PATH"
}
role :web, "XXX.XXX.XXX.XXX" # Your IP here
role :app, "XXX.XXX.XXX.XXX"
role :db, "XXX.XXX.XXX.XXX", :primary => true
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
set :user, -> { "torquebox" }
set :group, -> { "torquebox" }
set :use_sudo, false
set :scm, :git
set :stage, "production"
set :repository, "git://github.com/yourcompany/yourwebapp.git" # Address of your Git repository goes here
set :deploy_to, -> { "/home/#{user}" } # Change this if you want to deploy to other directory
set :deploy_via, :remote_cache
set :deploy_env, -> { "production" }
set :rails_env, -> { "production" }
set :app_context, "/"
namespace :deploy do
desc "Symlink shared configs and folders on each release."
task :finalize_update do
# If this task fails, please make sure you put config/database.yml and config/app_config.yml in the shared directory
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
desc "Start the server"
task :start do
run "cd #{current_path} && RAILS_ENV=production bundle exec torquebox deploy --name=myapp" # change name
end
task :stop do
run "cd #{current_path} && RAILS_ENV=production bundle exec torquebox undeploy --name=myapp" # change name
end
desc "Hot-restart the server"
task :restart do
run "cd #{current_path} && touch tmp/restart.txt" # hot deployment made easy!
end
end
Don’t forget to customize it to your needs, mind the comments above. There are some important bits here:
- deploy:start and deploy:stop tasks - you should always specify name of your app/knob file here. Otherwise it will try to deploy the app multiple times under the same context with different names and it will fail badly except first deployment.
- Torquebox 3 will do zero downtime deployments only if you overwrite restart task or ‘touch tmp/restart.txt’ file manually. This is consistent with behavior of Phusion Passenger. The default Torquebox’s restart task will shutdown the old application before booting new one, which can save you some RAM but users can notice the app being down for a few seconds.
Now set up your deployment files structure:
bundle exec cap deploy:setup
SSH to the server and place /home/torquebox/shared/config/database.yml file:
production:
adapter: jdbcpostgresql
encoding: unicode
database: myapp-production
pool: 5
username: torquebox
password: mypassword
host: localhost
port: 5432
You need to amend the config file above to match your PostgreSQL settings. Of course you can also use MySQL if you really want, we won’t judge you ;).
Now you can do first deployment:
bundle exec cap deploy:cold
And all the following deployments, you simply need to run:
bundle exec cap deploy
Summary
We just set up and deployed an Ruby on Rails app to Torquebox running as a service on Ubuntu 12.04. The web application will be deployed with virtually zero downtime and we can use full potential of Torquebox, including messaging, services, scheduler and clustering. If you are not using JRuby and Torquebox yet in production for your company - consider it as an option.
More info
Post by Hubert Łępicki
Hubert is partner at AmberBit. Rails, Elixir and functional programming are his areas of expertise.