How to Install Redmine on Ubuntu 16.04 with Nginx & Unicorn

How to Install Redmine on Ubuntu 16.04 with Nginx & Unicorn

comments

Redmine is a open source project management tool written in Ruby on Rails. It's been around since 2006 and has a large community of users. If you're unfamiliar with it, there's a online demo available.

For users who have never used the Ruby on Rails framework, the installation of Redmine can be a bit confusing. So, I made this guide to simplify the installation process for people.

redmine-interface

Guide requirements

  • Ubuntu (with root access)
  • Nginx
  • MySQL or PostgreSQL

Install Ruby on Rails

Download the latest version of Ruby on Rails

curl -kLo ~/ruby-2.4.2.tar.gz http://ftp.ruby-lang.org/pub/ruby/2.4/ruby-2.4.2.tar.gz
tar -xzf ~/ruby-2.4.2.tar.gz
cd ~/ruby-2.4.2/
./configure
make
sudo make install
ruby -v

Install dependencies

Before you can install Redmine, you'll first to need to make sure that your system has the required dependencies.

sudo apt-get install curl git libssl-dev libreadline-dev zlib1g-dev imagemagick libmagickwand-dev

Redmine uses a package manager for Ruby gems called Bundler

sudo gem install bundler

If you're using MySQL, make sure you have the MySQL client installed

sudo apt-get install libmysqlclient-dev

Or if you're using PostgreSQL, make sure that you have the PostgreSQL client installed

sudo apt-get install postgresql-client

Create Redmine user

For security reasons, it's recommended that you create a new user to run Redmine under.

sudo adduser --disabled-login --gecos 'Redmine Project Management' redmine
sudo su - redmine

Create the database

For MySQL:

CREATE DATABASE redmine CHARACTER SET utf8;
CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'my_password';
GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';

For PostgreSQL:

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

Install Redmine

Clone the latest version of Redmine from its Git repository

mkdir ~/redmine
git clone git://github.com/redmine/redmine.git ~/redmine

Modify database config file

Copy config/database.yml.example to config/database.yml and edit it with your server's settings

cp ~/redmine/config/database.yml.example ~/redmine/config/database.yml
nano ~/redmine/config/database.yml

If you're using MySQL then edit

production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: my_password

If you're using PostgreSQL then edit

production:
  adapter: postgresql
  database: <your_database_name>
  host: <postgres_host>
  username: <postgres_user>
  password: <postgres_user_password>
  encoding: utf8
  schema_search_path: <database_schema> (default - public)

Install gems for Redmine

As you'll be using Unicorn as Redmine's web server , you'll need to add gem "unicorn" to Gemfile

echo "gem \"unicorn\"" >> ~/redmine/Gemfile

Now we can install the required gems

cd ~/redmine
bundle install --without development test

Generate secret token

Generate a secret token for Rails to encrypt cookies

bundle exec rake generate_secret_token

Prepare the database

Create database structure and populate it

RAILS_ENV=production bundle exec rake db:migrate

Set permissions

mkdir -p tmp/pids tmp/sockets public/plugin_assets
chmod -R 755 files log tmp public/plugin_assets

Configure Unicorn

Download Unicorn config file

curl -kLo ~/redmine/config/unicorn.rb https://raw.githubusercontent.com/defunkt/unicorn/master/examples/unicorn.conf.rb

Make the following changes to unicorn.rb

nano ~/redmine/config/unicorn.rb
  • working directory: /home/redmine/redmine
  • socket: /home/redmine/redmine/tmp/sockets/unicorn.sock
  • pid: /home/redmine/redmine/tmp/pids/unicorn.pid
  • log (change stderr_path and stdout_path) to have the path: /home/redmine/redmine/log

Configure Nginx

upstream unicorn_server { 
   # This is the socket we configured in unicorn.rb 
   server unix:/home/redmine/redmine/tmp/sockets/unicorn.sock 
   fail_timeout=0; 
} 
 
server { 
    listen 80;
    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; 
      } 
    } 
}

Reload Nginx's config

sudo service nginx reload

Test installation

At this point, you should be able to launch Unicorn and test your Redmine installation out.

unicorn_rails -E production -c /home/redmine/redmine/config/unicorn.rb

If there are no errors on your screen, go ahead and visit Redmine in your browser to confirm that your installation is working. You can hit Ctrl + C to kill Unicorn when you're done.

Default login information:

  • Login: admin
  • Password: admin

redmine-login

Add Redmine as a service

Now create a file in /etc/init.d/ and paste the following script to it

sudo nano /etc/init.d/redmine
#!/bin/bash

### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO

BUNDLE=/usr/local/bin/bundle
UNICORN=/usr/local/bin/unicorn_rails
KILL=/bin/kill
APP_ROOT=/home/redmine/redmine
PID=/home/redmine/redmine/tmp/pids/unicorn.pid
OLD_PID=/home/redmine/redmine/tmp/pids/unicorn.pid.oldbin
CONF=/home/redmine/redmine/config/unicorn.rb
USER=redmine

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

case "$1" in
  start)
    echo "Starting unicorn rails app ..."
    su - $USER -c "cd $APP_ROOT; $BUNDLE exec unicorn_rails -D -E production -c $CONF" &&
    echo "Unicorn rails app started!" ||
    echo "Unicorn rails app failed"
    ;;
  stop)
    echo "Stoping unicorn rails app ..."
    sig QUIT && exit 0
    echo "Not running"
    ;;
  restart)
    if [ -f $PID ];
    then
      echo "Unicorn PID $PID exists"
      /bin/kill -s USR2 `/bin/cat $PID`
      sleep 30
      echo "Old PID $OLD_PID"
      /bin/kill -9 `/bin/cat $OLD_PID`
    else
      echo "Unicorn rails app is not running. Lets start it up!"
      $0 start
    fi
    ;;
  status)
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    ;;
esac

Set permissions and activate service on server startup

sudo chmod 755 /etc/init.d/redmine
sudo update-rc.d redmine defaults

Start Redmine service

sudo service redmine start

Congratulations! You've successfully installed the Redmine project management tool. Did you have trouble during a certain step or a question that wasn't addressed in this guide? Let us know in the comment section below!

Backups

You should create daily backups of your Redmine data. You'll need to back the data up from two locations:

  • data (stored in the Redmine MySQL or PostgreSQL database)
  • file attachments (stored in the ~/redmine/files directory)
# Database
/usr/bin/mysqldump -u <username> -p<password> <redmine_database> | gzip > /path/to/backup/db/redmine_`date +%y_%m_%d`.gz

Troubleshooting

MySQL error during database migration

If you get an error about an invalid default value, this is because sql_mode is set incorrectly.

-- create_table(:email_addresses, {:id=>:integer})
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Invalid default value for 'updated_on': CREATE TABLE `email_addresses` (`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `user_id` int NOT NULL, `address` varchar(255) NOT NULL, `is_default` tinyint(1) DEFAULT 0 NOT NULL, `notify` tinyint(1) DEFAULT 1 NOT NULL, `created_on` timestamp NOT NULL, `updated_on` timestamp NOT NULL) ENGINE=InnoDB
/home/redmine/redmine/db/migrate/20150113194759_create_email_addresses.rb:3:in `change'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'

To view the current value of sql_mode, type:

SHOW VARIABLES LIKE 'sql_mode' 

Neither NO_ZERO_IN_DATE or NO_ZERO_DATE should be returned.

ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_...

If one of those values is in your sql_mode, then you need to modify your MySQL config file.

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Add the line:

sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Restart MySQL

sudo service mysql restart