Wednesday, August 4, 2010

Weaving Redmine, RVM, Ruby, Rails, Rack, Thin, and nginx as a reverse proxy

Yesterday, it came down from On High.

Bossman say 'We need a trouble ticket system.' and Kami say "yes massa!"

A quick trawl of wikipedia's list later, and Redmine's the winner.
Time Tracking, Revision control integration, and full RBAC + lockdown, and all written in my favorite language, Ruby.

So, we'll be starting from where my previous post in the series left off.

You should have Lucid + nginx + php5-fastcgi + phpmyadmin set up already. (Honestly, you can skip the PHP stuff if you're not interested; I keep it around for Drupal and phpmyadmin.)

First: Get some required packages.

apt-get install curl patch git-core subversion autoconf build-essential bison libreadline6 libreadline-dev zlib1g zlib1g-dev libssl-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libmysqlclient-dev libpq-dev

Second, install rvm.
bash < <( curl -L http://bit.ly/rvm-install-system-wide )
tee -a ~/.bashrc <<-\EOA
[[ -s '/usr/local/lib/rvm' ]] && source '/usr/local/lib/rvm'
EOA
source '/usr/local/lib/rvm'

Disable ruby's documentation generation (Don't need it on rackspace; skip this if you're on a dev box.)
echo "gem: --no-rdoc --no-ri" >> /etc/gemrc

Install ruby 1.8.7.
rvm install 1.8.7

Now set it as the default.
rvm use --default 1.8.7

Get the sqlite3 gem compiled
gem install sqlite3-ruby
IF this fails, you're probably missing libsqlite3-dev

Get the mysql gem compiled
gem install mysql
IF this fails, you're probably missing libmysqlclient-dev

Get the pg gem compiled
gem install pg
IF this fails, you're probably missing libpq-dev


Install rack 1.0.1







gem install rack -v=1.0.1

Install rails 2.3.5




gem install rails -v=2.3.5

If you want the optional gantt chart generation, you'll need rmagick.
apt-get install libmagick9-dev imagemagick
That will pull down a bunch of -dev packages; now build the native extensions.
gem install rmagick

Now we need a better appserver than webrick. Let's go get thin.













gem install thin
Decide on where you'd like the redmine app to live; I like the private directory under the hostname.
mkdir -p /var/www/redmine.domain.com/private/ && cd /var/www/redmine.domain.com/private/

Now, checkout version 1.0's latest revision.

svn co http://redmine.rubyforge.org/svn/branches/1.0-stable redmine

Okay, we've got redmine; now to configure it. First, let's setup the database. Run this SQL in phpmyadmin:

create database redmine_core character set utf8;
create user 'redmine_user'@'localhost' identified by 'my_password';
grant all privileges on redmine_core.* to 'redmine_user'@'localhost';
Or phppgadmin: (Paste each line separately.)

CREATE ROLE redmine_user LOGIN ENCRYPTED PASSWORD 'my_password' NOINHERIT VALID UNTIL 'infinity'; 
CREATE DATABASE redmine_core WITH ENCODING='UTF8' OWNER=redmine_user;


Edit the config/database.yml and configure the database settings.
cd redmine/config/ && cp database.yml.example database.yml
production:
  adapter: mysql
  database: redmine_core
  host: localhost
  username: redmine_user
  password: my_password
  encoding: utf8

Or for Postgresql:


production:
  adapter: postgresql
  database: redmine_core
  host: localhost
  username: redmine_user
  password: my_password
  encoding: utf8


Now return to the redmine root (cd ..) and generate the session store.
rake generate_session_store

Now, we'll have redmine populate the database.
RAILS_ENV=production rake db:migrate

You'll be prompted to choose a language here; just hit enter for english.
RAILS_ENV=production rake redmine:load_default_data

Wooo! Let's test it.








ruby script/server thin -e production
Now visit port 3000. You should get a nice blank redmine instance.

Now, for configuring nginx for a reverse proxy test:
server {
        listen                  80;
        server_name             redmine.domain.com;
        access_log              /var/www/redmine.domain.com/log/access.log;
        error_log               /var/www/redmine.domain.com/log/error.log;
        root                    /var/www/redmine.domain.com/public/;

        location / {
                try_files       $uri @fallback;
                }

        location @fallback {
                proxy_pass              http://127.0.0.1:3000;
                proxy_connect_timeout   15;
                proxy_redirect          default;
                proxy_set_header        Host    $host;
                proxy_set_header        X-Real-IP       $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                #proxy_set_header       X-Forwarded-Proto       https;
                }
        }
Okay, this works!

Next step: Setting up thin clusters on boot.
thin install

Set up the icky old init-scripts:
update-rc.d -f thin defaults

Now we can add YAML config files in /etc/thin/ !
--- 
pid: tmp/pids/thin-redmine.pid
group: rvm
wait: 30
timeout: 30
log: log/thin.log
max_conns: 1024
require: []

environment: production
max_persistent_conns: 512
servers: 2
daemonize: true
user: www-data
socket: /tmp/thin-redmine.sock
chdir: /var/www/redmine.domain.com/private/redmine 

Okay, let's start thin.
service thin start

And fix up our nginx proxy config:
upstream thin_redmine {
   server   unix:/tmp/thin-redmine.0.sock;
   server   unix:/tmp/thin-redmine.1.sock;
}

server {
        listen                  80;
        server_name             redmine.domain.com;
        access_log              /var/www/redmine.domain.com/log/access.log;
        error_log               /var/www/redmine.domain.com/log/error.log;
        root                    /var/www/redmine.domain.com/public/;

        location / {
                try_files       $uri @fallback;
                }

        location @fallback {
                proxy_pass              http://thin_redmine;
                proxy_connect_timeout   15;
                proxy_redirect          default;
                proxy_set_header        Host    $host;
                proxy_set_header        X-Real-IP       $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                #proxy_set_header       X-Forwarded-Proto       https;
                }
        }

Enable your configuration and restart nginx.
service nginx reload
...

PROFIT!



Here's some links:



1 comment:

Anonymous said...

Thanks !!