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 script
Configuring 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.
--config
tells us where to put the generated file and under which name--chdir
tells us which dir to use to start the thin server--environment
tells us about the Rails environment--socket
tells us the unix socket file path in/var/run
--daemonize
to run server as Unix daemon--log
tells us location where to dump log file--pid
is the unix pid file--user
and-- group
under which Unix user and group to run the server--servers
(how many servers to run--prefix
tells 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)--prefix
can 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