Redmine on CentOS 7

     

NOTE: This tutorial is for Redmine 2. For Redmine 3, make sure to read Redmine 3 on CentOS 7 as well.

Preamble

This is a supplementary blogpost for my previous post, Installing, Migrating & Upgrading Redmine with LDAP on Ubuntu. I’m not going to cover the migration, upgrade, authentication, etc. parts again coz they’re almost 100% identical, so if you need those, please refer to the older guide. This guide will only show you how to install Redmine.

CentOS

As always, perform a minimal install. I recommend using the following partitions:

  • /boot: 1GB, standard
  • swap: 500MB, LVM
  • /: rest, LVM

I recommend ext4. After the installaltion’s complete, perform an initial update:

yum update

Correct the timezone (change path according to your location):

timedatectl set-timezone Your_Continent/Your_City

Then reboot.

Repositories

If you want Git integration, you gotta mount the NFS exports provided by the Git server. Install the required tools:

yum install git nfs-utils

Create a directory for accessing the repos:

mkdir -p /opt/git

Then add the following to /etc/fstab:

scm.ad.foo.bar:/nfs/git /opt/git nfs4 auto 0 0

Then mount with mount -a. If everything’s fine, the remote Git repos will be available under /opt/git.

PostgreSQL

Install the database and the development files required for Ruby gems:

yum install postgresql-server postgresql-devel

Initialize the database:

postgresql-setup initdb

Start the engine:

systemctl start postgresql.service

Now switch to the postgres user and enter the PostgreSQL command prompt:

su postgres
psql

Within this prompt, create the redmine user and the production (redmine) and test (redmine_test) databases. Also make the redmine user the owner of these 2 databases (replace the *** password with whatever you want):

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

You can verify the result with list, and if it’s OK exit with quit.

Now test if you can connect via socket:

psql --host=localhost --username=redmine -W

If this gives you an authentication failure (it probably will), open /var/lib/pgsql/data/pg_hba.conf and change ident auth to md5 for both IPv4 and IPv6:

# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
#host    all             all             ::1/128                 ident
host    all             all             ::1/128                 md5

Save it, then restart PostgreSQL:

systemctl restart postgresql.service

Once it works, also make the service start automatically upon startup:

systemctl enable postgresql.service

Redmine

Download Redmine and set up the directory structure:

export REDMINE_VERSION=2.6.0
wget http://www.redmine.org/releases/redmine-${REDMINE_VERSION}.tar.gz
tar xf redmine-${REDMINE_VERSION}.tar.gz -C /opt
cd /opt
ln -s redmine-${REDMINE_VERSION} redmine

Create the database configuration file:

touch /opt/redmine/config/database.yml

Then configure it to use our shiny new PostgreSQL instance (replace the dummy passwords):

test:
    adapter: postgresql
    database: redmine_test
    host: localhost
    username: redmine
    password: "***"

production:
    adapter: postgresql
    database: redmine
    host: localhost
    username: redmine
    password: "***"

Certain gems may fail at documentation generation, so let’s just save some disk space and installation time and disable it altogether:

echo 'gem: --no-rdoc --no-ri' > ~/.gemrc

Now install Ruby and and packages required for Gem generation. Also install the bundler gem:

yum install ruby ruby-devel gcc
gem install bundler

Install all the gems required by Redmine:

cd /opt/redmine
export PATH=$PATH:/usr/local/bin
bundle install --verbose --without development test rmagick

There’s a bug in the pg gem which may or may not occur. Go to /usr/local/share/gems/gems/pg-0.17.1 (the version number may differ) and verify that the pg_ext.so file exists both under the ext and lib subdirectories. If it isn’t, simply copy it over.

Once the gems are installed correctly, initialize the Redmine instance:

rake generate_secret_token
RAILS_ENV=production rake db:migrate
RAILS_ENV=production rake redmine:load_default_data

At this point your instance should be ready to use. Now it’s time to test it on port 3000, for which you’ll also need to temporarily open the appropriate port on the firewall:

firewall-cmd --add-port=3000/tcp

Then fire up the test engine:

ruby script/rails server webrick -e production

Now you can reach your new server via HTTP on port 3000 with the usual admin/admin login.

Web server

Webrick is nice for testing purposes but for production you need something more robust. In our case it’s going to be Nginx. First of all, enable port 80 (the default HTTP port) to be accessible through the firewall:

firewall-cmd --add-service http --permanent
systemctl restart firewalld.service

Now create a service account for Nginx:

useradd --home-dir /opt/nginx --shell /sbin/nologin --user-group --system nginx

Make the Redmine user and group the owner of your instance. This is rather crucial and it applies to future versions as well, refer to the Phusion Passenger users guide for details.

chown -R nginx.nginx redmine-${REDMINE_VERSION}

Now you need to build Nginx with Ruby support. For this, install the required packages first:

yum install gcc-c++ libcurl-devel openssl-devel zlib-devel

Install the Passenger gem:

gem install passenger

Then build Nginx with Ruby support:

passenger-install-nginx-module

The questions should be self-explanatory:

Which languages are you interested in? Ruby
Automatically download and install Nginx? 1. Yes: download, compile and install Nginx for me. (recommended)
Where do you want to install Nginx to? [/opt/nginx]

After it’s finished, you can start Nginx:

/opt/nginx/sbin/nginx

If the Nginx sample page loads in your browser, it should be good. Now you can stop Nginx:

/opt/nginx/sbin/nginx -s stop

Now create a systemd unit for Nginx. Create the /etc/systemd/system/nginx.service file with the following content:

[Unit]
Description=The Nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/opt/nginx/sbin/nginx -t
ExecStart=/opt/nginx/sbin/nginx
ExecReload=/opt/nginx/sbin/nginx -s reload
ExecStop=/opt/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Now make systemd aware of the changes and enable automatic starting of Nginx:

systemctl daemon-reload
systemctl enable nginx.service

Rename /opt/nginx/etc/nginx.conf to nginx.conf.orig, create a new, empty nginx.conf and paste the following into it, but make sure to update the Passenger version number in passenger_root accordingly:

user nginx nginx;
worker_processes 1;

error_log logs/error.log notice;

pid /run/nginx.pid;

events {
        worker_connections 1024;
}

http {
        passenger_root /usr/local/share/gems/gems/passenger-4.0.53;
        passenger_ruby /usr/bin/ruby;
        passenger_load_shell_envvars off;
        passenger_friendly_error_pages on;
        passenger_user nginx;
        passenger_group nginx;
        passenger_default_user nginx;
        passenger_default_group nginx;

        include mime.types;
        default_type application/octet-stream;
        keepalive_timeout 65;
        sendfile on;
        gzip on;

        server {
                listen 80;
                server_name redmine.ad.foo.bar;
                root /opt/redmine/public;
                access_log logs/access.redmine.log;
                passenger_enabled on;
        }
}

Save it, then start Nginx:

systemctl start nginx.service

Congratulations, your Redmine instance should be up and running.