Running Redmine with Nginx and Thin
Nginx (pronounced Engine X) is an HTTP and reverse-proxy server with generic TCP proxying features. It is known for its stability, speed, and security. As such, it's often chosen by many web server and Redmine administrators. Thin is a fast and very simple Ruby web server. Combining these two servers provides additional flexibility and scalability in configuration. However, you are free to test/adjust this recipe and use any other server such as Puma or Unicorn instead of Thin.
Getting ready
Install Redmine from a repository, as explained in the Installing Redmine on Ubuntu recipe. If you are using Windows, then install Redmine by following the Windows installation recipe.
How to do it…
First, install Nginx and Thin by typing the following:
sudo apt-get install nginx thin
As we are using Ubuntu, the Aptitude installer will install Nginx and its required libraries for us, perform basic configuration, and start it. To test that it is installed and working correctly, navigate to your server's IP and you should see Nginx's welcome screen:

Configuring thin
To configure thin, it is better to perform the following commands as root, so we type the following:
sudo su
Then, we type one big line (explained later):
thin config --config /etc/thin1.9.1/redmine.yml --chdir /usr/share/redmine --environment production --socket /var/run/redmine/sockets/thin.sock --daemonize --log /var/log/thin/redmine.log --pid /var/run/thin/redmine.pid --user www-data --group www-data --servers 1 --prefix /redmine
Create the required directories, as follows:
mkdir /var/run/redmine /var/run/redmine/sockets/ /var/run/thin/ /var/log/thin/ chown www-data:www-data /var/run/redmine/sockets/ /var/run/thin/ nano /etc/logrotate.d/thin
Enter the following content to nano:
/var/log/thin/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
/etc/init.d/thin restart >/dev/null
endscript
}We need to make sure that thin will work properly after restart. To ensure this, we edit /etc/init.d/thin by typing nano /etc/init.d/thin.
We then add the following just before DAEMON=/usr/bin/thin:
pre-start script
mkdir -p -m0755 /var/run/redmine
mkdir -p -m0755 /var/run/redmine/sockets
mkdir -p -m0755 /var/run/thin
chown www-data:www-data /var/run/redmine/sockets
chown www-data:www-data /var/run/thin
end scriptConfiguring Nginx
Add a new server to Nginx by typing the following:
nano /etc/nginx/sites-available/redmine
Add the following content that is updated to fit your server name needs:
upstream redmine_thin_servers {
server unix:/var/run/redmine/sockets/thin.0.sock;
# Add additional copies if using multiple Thin servers
#server unix:/var/run/redmine/sockets/thin.1.sock;
}
server {
listen 80; ## listen for ipv4
listen [::]:80 default ipv6only=on; ## listen for ipv6
# Set appropriately for virtual hosting and to use server_name_in_redirect
server_name localhost;
server_name_in_redirect off;
access_log /var/log/nginx/localhost.access.log;
error_log /var/log/nginx/localhost.error.log;
# Note: Documentation says proxy_set_header should work in location
# block, but testing did not support this statement so it has
# been placed here in server block
include /etc/nginx/proxy_params;
proxy_redirect off;
# Note: Must match the prefix used in Thin configuration for Redmine
# or / if no prefix configured
location /redmine {
root /usr/share/redmine/public;
error_page 404 404.html;
error_page 500 502 503 504 500.html;
# Uncomment below lines if using HTTPS
# Note1: Change $host to SSL CN if multiple host names used
# Note2: Adjust prefix, if different in Thin Redmine config
#rewrite ^/redmine/login(.*) https://$host$request_uri permanent;
#rewrite ^/redmine/my/account(.*) https://$host$request_uri permanent;
#rewrite ^/redmine/my/password(.*) https://$host$request_uri permanent;
#rewrite ^/redmine/admin(.*) https://$host$request_uri permanent;
try_files $uri/index.html $uri.html $uri @redmine_thin_servers;
}
location @redmine_thin_servers {
proxy_pass http://redmine_thin_servers;
}
}Enable the Redmine site under Nginx:
ln –s /etc/nginx/sites-available/redmine /etc/nginx/sites-enabled/redmine
Configuring Redmine for sub-uri
Using
nano, open routes.rb, as follows:
nano /usr/share/redmine/config/routes.rb
Add the following line to Redmine's config file:
Redmine::Utils::relative_url_root = "/redmine"
Add this line just above the line that looks like this:
RedmineApp::Application.routes.draw do
Testing the installation
Restart both servers and test the installation:
service thin restart service nginx restart
Now, navigate to your server's IP or domain/Redmine, and Redmine's initial screen should await you.
How it works…
First, we performed a Redmine installation on an Ubuntu system, as explained in the recipe Installing Redmine on an Ubuntu server. Then, we installed the required servers: Thin and Nginx. Thin is a dedicated Ruby apps server, and Nginx is a dedicated web and reverse-proxy server. This way, we have multilayer architecture, allowing us to have, for example, one Nginx and multiple thin instances. In this case, it is connected through a Unix socket but more advanced versions of TCP upstream can be used to run multiple servers on multiple machines and load-balance this way.
Line thin config --config /etc/thin1.9.1/redmine.yml --chdir /usr/share/redmine --environment production --socket /var/run/redmine/sockets/thin.sock --daemonize --log /var/log/thin/redmine.log --pid /var/run/thin/redmine.pid --user www-data --group www-data --servers 1 --prefix /redmine uses the thin server to create config file.
--configtells us where to put the generated file and under which name--chdirtells us which dir to use to start the thin server--environmenttells us about the Rails environment--sockettells us the unix socket file path in/var/run--daemonizeto run server as Unix daemon--logtells us location where to dump log file--pidis the unix pid file--userand-- groupunder which Unix user and group to run the server--servers(how many servers to run--prefixtells us under which prefix to run it--servers(tells how many servers to run) for managing concurrent requests (if you put more than one, then the Nginx configuration needs to follow number of the servers specified in this command)--prefixcan be omitted if you want Redmine not to run as sub-uri (Nginx configuration also needs to be updated if using SSL)
After this, we create the necessary folders, set permissions, and add thin to logrotate. Nginx is already there, so we only add thin.
There's more…
You can use this recipe to set up Nginx and Thin on Windows; the only difference is Windows can't be daemonized. You need to start thin manually; set up a batch or registry file to do it. Also, the TCP port should be used instead of a Unix port.
Redmine can be forced to use SSL all the time through Nginx configuration. To do so, uncomment the SSL lines in Nginx config and copy and paste the server section, set the listen ports to 443, and add the path to your SSL key and certificate:
ssl on; ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
See also
A comparison of Ruby web servers can be found at:
http://www.madebymarket.com/blog/dev/ruby-web-benchmark-report.html