Redmine on Debian 6 with Unicorn and NGINX

Jump To:   «  1 2 3  View All »

A unicorn with it's refelction in water.Redmine is perhaps my favorite Bug tracking, ticketing, wiki, forum, documentation software there is. My only complaint in the past about Redmine was the fact that you needed to use Passanger to run it (which is a RAM hog). Having a bunch of low end VPS’s (Virtual Private Servers) I decided to attempt hacking Redmine onto a 128MB Ram box. Well after doing my research I came upon a neat little trick, Unicorn. Unicorn is a webserver that we can use in place of Passanger to serve Redmine to NGINX, our main webserver. Time to gallop to the setup.

First install Debian 6 aka Squeeze and do an aptitude update. For the non savy, either apt-get update or aptitude update in the shell. Next do the installs via aptitude, you can remove the mysql-server if it is not going to be hosted on the same server or change it to another engine (sqlite or pgsql) but also change the redmine-mysql to be redmine-db if you decide to not use MySQL

#: aptitude install redmine ruby1.8 ruby1.8-dev rails rake redmine-mysql gem make mysql-common mysql-server 

For the prompts, answer the following:

Configure database for redmine:  Yes
Choose whatever db engine you want to use. 
Database name: redmine

If for some reason you wanted to do a different database setup then other than the one you selected run this command after installing the database:

#: dpkg-reconfigure -plow redmine

Once you have the database setup and figured out we are now ready to look into installing our secret trick, Unicorn!

——————————————————————————-

The first step will be to utilize gem and install the Unicorn server by issuing the following shell command:

#: gem install unicorn

If there are any errors that show up, attempt to fix them (Google is a great resource) and retry the Unicorn installation. Once Unicorn has been installed, we will need to do the configuration. In order to setup and configure Unicorn we are going to issue the following commands:

#: mkdir -p /usr/share/redmine/tmp/sockets
#: mkdir  /usr/share/redmine/tmp/pids
#: mkdir /usr/share/redmine/log
#: cd /usr/share/redmine/config
#: nano unicorn.rb

The commands will create our directory structure and the config file (unicorn.rb). Inside the unicorn.rb file, we are going to paste the follow:

#unicorn.rb Starts here
worker_processes 1
working_directory "/usr/share/redmine" # needs to be the correct directory for redmine

# This loads the application in the master process before forking
# worker processes
# Read more about it here:
# http://unicorn.bogomips.org/Unicorn/Configurator.html
preload_app true
timeout 45

# This is where we specify the socket.
# We will point the upstream Nginx module to this socket later on
listen "/usr/share/redmine/tmp/sockets/unicorn.sock", :backlog => 64 #directory structure needs to be created. 
pid "/usr/share/redmine/tmp/pids/unicorn.pid" # make sure this points to a valid directory.

# Set the path of the log files inside the log folder of the testapp
stderr_path "/usr/share/redmine/log/unicorn.stderr.log"
stdout_path "/usr/share/redmine/log/unicorn.stdout.log"

before_fork do |server, worker|
# This option works in together with preload_app true setting
# What is does is prevent the master process from holding
# the database connection
  defined?(ActiveRecord::Base) and
  ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
# Here we are establishing the connection after forking worker
# processes
  defined?(ActiveRecord::Base) and
  ActiveRecord::Base.establish_connection
  # change below if your redmine instance is running differently
      worker.user('www-data', 'www-data') if Process.euid == 0
end
#unicorn.rb Ends here
									

To exit save with Nano, use Ctrl+X. If you chose to use VIM or another editor, save the file. Once the configuration file has been saved we will issue another set of commands:

#: chown www-data:www-data unicorn.rb
#: chown -R www-data:www-data ../tmp
#: ln -s /var/lib/gems/1.8/bin/unicorn_rails /usr/bin
#: nano /etc/rc.local

To ensure that Unicorn will start if the server is rebooted, we add this line to the rc.local file:

# add this line before exit 0; so it starts on boot.
unicorn_rails -E production -c /usr/share/redmine/config/unicorn.rb -D

Now that Unicorn is able to be ran on startup (note the -D above daemonizes Unicorn), let’s test the Unicorn server to make sure it runs (if this does not error out then it works and you can use Ctrl+C to kill the process).

#: unicorn_rails -E production -c /usr/share/redmine/config/unicorn.rb

If the Unicorn install went well, the server will have started and you would see no errors. If you do see errors, Google them to attempt to fix them. Once the errors are fixed, we move on to the next phase, NGINX.

——————————————————————————-

NGINX is perhaps my favorite webserver of choice. NGINX is light weight, extremely stable and reliable. Since we are looking for a light weight server mainly, NGINX was the first choice that came to mind. We are going to be hacking this NGINX setup to proxy incoming connections for Redmine to the Unicorn Server. Using this method we get the benefit of NGINX’s process, which should make Redmine all the more stable.

Since we are running the setup on Debian, I am going to use the sites-available, which Debian sets up automatically. If you are using Arch or CentOS, you will need to either add this to the nginx.conf or setup the sites-available / sites-enabled virtual hosts. Let’s start the install:

# apt-get install nginx
# cd /etc/nginx/sites-available
# rm ../sites-enabled/default 
# nano redmine

What we do here is install nginx, delete the default site symbolic link from the enabled directory. This will disable the default site configuration without having to actually delete the actual file. Here is the NGINX configuration I worked out, paste this into the nano for redmine:

upstream unicorn_server {
   # This is the socket we configured in unicorn.rb
   server unix:/usr/share/redmine/tmp/sockets/unicorn.sock
   fail_timeout=0;
}

server {

    listen   80; ## listen for ipv4

    server_name redmine.yoursite.com;

    access_log  /var/log/nginx/yoursite.access.log;
    error_log  /var/log/nginx/yoursite.error.log;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;

      if (!-f $request_filename) {
        proxy_pass http://unicorn_server;
        break;
      }
    }
}
									

Save it in Nano with Ctrl+X. If you feel the need for hacking, you can change the configuration up to suit your needs. The setup provided is for redmine to be placed in a subdomain, redmine.yoursite.com. I have yet to find a trick to get it to work as a subfolder, so if you feel like hacking a little but, go ahead and try. If you do figure out how to get redmine to work under a subfolder, please post the solution in the comments section.

Now that the configuration is saved, we want to enable the site, luckily it is a simple command:

#: ln -s /etc/nginx/sites-available/redmine /etc/nginx/sites-enabled/redmine

Redmine is now running on a low end VPS using Unicorn and NGINX. Restart or reload NGINX and redmine should now be accessible through redmine.yoursite.com (as long as the redmine subdomain points to your server’s IP address). If you want to get extra credit, attempt to implement a Subversion repository on the VPS server, in the future I may decide to write an article to assist you with adding Subversion to Redmine. Until then, enjoy my little hacking trick to install Redmine using way less ram than it used to on Apache with Passanger!

Jump To:   «  1 2 3  View All »

1 Comment

Leave us a comment

Leave a Comment

↑ BACK TO THE TOP ↑