Ruby
Redmine

ServerMan@VPSにRedmineをインストールする

More than 5 years have passed since last update.

なぜRedmineか?

有償ウェブサービスを開発する前提で、実装する機能やチームで情報を共有するためにはプロジェクト管理ツールが便利だ。
ツールはいくつかあるんだけれど、Ruby製で進化が早くbacklogsプラグインでアジャイルの手法にも対応ができTiDDも実行できるという点でお気に入りのRedmineを使うことにした。

Redmineのインストール手順

この内容を読むひとへ、多分時が経ったらこの手順では動かないこともあると思うので、あくまで参考として使ってください。

サーバーの環境

VPS:ServerMan@VPS Entry
メモリー:512M〜1.2G
OS:debian 64bit

OSのアップグレード

前提 ServerMan@VPS Entry debian 64bitのシンプルセットの初期構成

# apt-get update -y
# apt-get upgrade

localeの設定

dpkg-reconfigure locales

en_US.UTF-8... done
ja_JP.UTF-8... done

参考
http://landisk.kororo.jp/diary/08_locale.php

作業用のアカウントを作成して、ROOTログインを禁止する。

$ ssh root@XXX.XXX.XXX.XXX -p XXXX
# groupadd admin
# useradd -d /home/user -G admin user
# passwd user

設定に失敗して、ログインできなくなるとOSを初期化することになるので、別プロセスでuserアカウントでログインする。
本来ならsudo権限だけを持たせてsu -を禁止にするのがセキュリティ上は望ましいのだけれど後回しでrootで作業することにする。

$ ssh user@XXX.XXX.XXX.XXX
$ su -
# vi /etc/ssh/sshd_config
#PermitRootLogin yes
PermitRootLogin no

設定を有効にするために、sshdを再起動する

# /etc/init.d/ssh restart

参考
http://blog.cloudrider.net/2010/12/serversmanvps-debian.html

gitのインストール

Redmineはソースからダウンロードすればよいが、あとあとgitのリポジトリからcloneすることになるので最初にインストールしておく。

# apt-get install -y git

ruby1.9.3のインストール

普通にソースからコンパイルもできるけど、パッケージ作っておくと便利な時が多いのでdebパッケージを作る。
まず、debianの標準のruby1.8.7とrubygemsとruby1.9.3-p385をコンパイルするためのパッケージをインストールする。

# apt-get install ruby rubygems 
# gem1.8 install fpm --no-ri --no-rdoc 
# apt-get install -y build-essential openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev ncurses-dev libyaml-dev

それから現時点での最新のrubyをダウンロードして、コンパイルするための準備作業をする。

# cd /tmp
# wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p385.tar.gz
# tar -zxvf ruby-1.9.3-p385.tar.gz
# cd ruby-1.9.3-p
# rm -rf /tmp/ruby193
# time (./configure --prefix=/usr && make && make install DESTDIR=/tmp/ruby193)

fpmでdebパッケージを作るらしいのだが、fpmってなんだっけ?
まあ、それを調べるのが目的ではないので参考URLにしたがって気にせず実行する。

# /var/lib/gems/1.8/bin/fpm -s dir -t deb -n ruby193 -v 1.9.3-p385 --description "Self-packaged Ruby 1.9.3 patch 385" -C /tmp/ruby193 \
  -p ruby193-VERSION_ARCH.deb -d "libstdc++6 (>= 4.4.3)" \
  -d "libc6 (>= 2.6)" -d "libffi5 (>= 3.0.4)" -d "libgdbm3 (>= 1.8.3)" \
  -d "libncurses5 (>= 5.7)" -d "libreadline6 (>= 6.1)" \
  -d "libssl0.9.8 (>= 0.9.8)" -d "zlib1g (>= 1:1.2.2)" \
  -d "libyaml-0-2 (>= 0.1.3)" \
  usr/bin usr/lib usr/share/man usr/include

debian標準のruby1.8.7を削除し、出来上がったパッケージをインストールする。
ちゃんと動いたので問題なし。

# apt-get remove ruby rubygems
# dpkg -i ruby193-p125_i386.deb
# ruby -ropenssl -rzlib -rreadline -ryaml -e "puts :success" 

参考
https://gist.github.com/2318876

apache2のアンインストール

注意点としてServerMan@VPSはDTIが提供してるサービスがいくつかApache2上でうごいてるので、それを活かしたい人にはapache2-passengerがオススメだ。
けれど、僕にとって現時点では魅力的なツールではないので使わない事にする。
それよりnginxでRailsのアプリケーションを劇速動作させることにフォーカスする。
追記:運用してたらserversmanが25%もリソースをつかっていて突然Redmineがメモリ不足で落ちたので起動とサービス自体を停止した。

# apt-get uninstall -y apache2*
# update-rc.d -f serversman remove

Redmineのインストール

さていよいよ本題、redmineの最新版をダウンロードして任意のディレクトリで動かす。
個人的にはサービスで起動するので/srv下にしている。
動かすユーザーはApache2のwww-dataを流用する。
ホームディレクトリとかいまいちな感があるけど気にしない。

ImageMagickとMysqlのインストール

ところで、rubygemsには結構クセがあってインストール中にコンパイルをかけることがあるので、前もってそのコンパイルに必要な依存パッケージをいれとくのがオススメだ。
代表的なのはRmacigkでImageMagickがインストールされている必要がある。
あとはMysqlとnokogiriもlibxslt-dev libxml2-devが必要だ。
そうしないとモグラたたきみたいに何度もbundle install --without development testをやることになって寒い思いをする。

apt-get install -y imagemagick mysql-server libmysqlclient16 libmysqlclient-dev mysql-client mysql-common libxslt-dev libxml2-dev

Mysqlのインストールのとき、debianだと確かパスワード設定しろって途中でおこられた気がする。Mysqlのバージョンはデフォのやつでいいと思う。
結構5.1系は安定してるし、5.5系から○○ってとこに買収されてるし、調べてないけどあまり変わらなかったはず。
ImageMagickも同様にデフォ、過去にソースからコンパイルするととんでもなく苦痛をしいられた記憶がトラウマになってまして。
ライブラリ系はそんなにバージョンにシビアになることないと思うのでデフォ。
セットアップが過日のことで忘れてしまった。

Redmine用のDB作成

localhostで動かす前提でMysqlにredmine用のDBと接続するユーザーを作成する。
ちなみに別のサーバーから設定する場合はlocalhostを接続サーバーのIPにすると接続できるはず。
FWやOSのiptablesとかも関わってくるので気をつけるべし。
実を言うと実務とかでいつも悩むのはどんな名前にするかとかなんだけど割り切ってDB名とユーザー名はredmineにする。
権限まで設定する。
権限も細かく設定はできるんだけど、整理するのがとても面倒なのでprivilegesで管理者権限をつける。
確認した方がいいけど、ここでは省く事にする。

# mysql -uroot -p
Enter password:
mysql> create database redmine character set utf8;
mysql> create user 'redmine'@'localhost' identified by 'redmine';
mysql> grant all privileges on redmine.* to 'redmine'@'localhost';

Redmineのインストール

Redmineとbacklogsプラグインのバージョン

・Redmine v2.2.2
・backlogs v0.9.35

それでは、メインディッシュであるRedmineの最新版のソースをダウンロードし、backlogsプラグインをリポジトリからcloneする。

# cd /srv
# wget https://github.com/redmine/redmine/archive/2.2.2.tar.gz
# tar zxf 2.2.2.tar.gz
# mv redmine-2.2.2 redmine
# cd /srv/redmine/plugins
# git clone https://github.com/backlogs/redmine_backlogs.git
# chown -R www-data. /srv/redmine

Redmineの設定ファイルを環境にあわせて編集する

# cp /srv/redmine/config/database.yml.example /srv/redmine/config/database.yml
# cp /srv/redmine/config/configuration.yml.example configuration.yml

まずは、database.ymlでこれからずっと自分の開発する行動をRedmineで記録していくのでproduction環境で動かす。
これみんなやりたがらないんだけど、全部自分のノウハウになるんだよね。ノウハウはポジションを確立するうえでとっても大事なのにね。
継続は力なりならぬ計測は力なりなのだ。
vi /srv/redmine/config/database.yml

/srv/redmine/config/database.yml
production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: redmine

次は、configuration.ymlを編集。
リポジトリはgit以外使わないのでそれ以外はコメントアウトした。
ここはよしなに
メールの設定はpostfixのインストールから必要なので動かした後にセットアップする。
いずれ、その記事もアップする予定。
vi /srv/redmine/config/database.yml

#  scm_subversion_command:
#  scm_mercurial_command:
  scm_git_command:
#  scm_cvs_command:
#  scm_bazaar_command:
#  scm_darcs_command:

たしか、Redmineとbacklogsでrakeのバージョンに食い違いがあってエラってたと思う。
とりあえずbacklogsのgem 'rake', '~>0.9'をコメントアウトした。

#gem 'rake', '~>0.9'

その後に、bundle install --without development testでgemをインストールする。
結構ここで依存関係とかではまるんだけど、ヒストリーがなくなったので皆さんチャレンジしてください。
覚えている限りではまったところを書いときます。

# cd /srv/redmine
# bundle install --without development test
# rake db:migrate  RAILS_ENV=production
# rake redmine:plugins:migrate RAILS_ENV=production
# rake redmine:backlogs:install RAILS_ENV=production

Redmineの起動をWebrickで動かして確認する。

# pwd
/srv/redmine
# rails s

ブラウザでIPアドレスでアクセスしてみる。

http://XXX.XXX.XXX.XXX:3000

OK!!エクセレント!
じゃ次わっと、ウェブサーバーね。

Nginxのインストールとセットアップ

僕は新し物好きで怠惰なので、他の人ががんばってくれたことに感謝しNginxもできる限り最新版のパッケージをインストールするようにする。
ぶっちゃけ結構ソースからインストールするとはまることがあるので極力パッケージをインストールして楽したいという横着心なのだが。

vi /etc/apt/sources.listでdotdebのリポジトリを追加する。

ここで独自ドメインが必要になるのであらかじめ取っていたほうがよいかな。
ま、IPで運用するひとはディスってください。

/etc/apt/sources.list
deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all

dotdebのgpgキーをダウンロードして、apt-keyに追加する。
この辺りは結構時とともに変わっていくかな。

# wget http://www.dotdeb.org/dotdeb.gpg
# cat dotdeb.gpg | apt-key add -
# rm dotdeb.gpg 

dotdebのリポジトリから現時点で最新安定版のNginxをインストールする。

# aptitude update
# aptitude show nginx
# aptitude install nginx-full
# aptitude

Nginxの設定の前にunicornをインストールしとく。

# gem install unicorn

vi /srv/redmine/config/unicorn.rbでredmineをunicornで動かす下準備をする。

/srv/redmine/config/unicorn.rb
worker_processes 1
working_directory "/srv/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 "/srv/redmine/tmp/sockets/unicorn.sock", :backlog => 64 #directory structure needs to be created.  
pid "/srv/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 "/sev/redmine/log/unicorn.stderr.log"
stdout_path "/srv/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

Nginxのデフォルト設定のシンボリックリンクを削除する。

# cd /etc/nginx/sites-available/
# ls
# rm ../sites-enabled/default

RedmineのNginxの設定ファイルをvi redmineで作る。
ここのポイントはログとserver_nameかな。
よしなに設定してください。
あとはデフォであんま問題ないと思う。

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

server { 

    listen   80; ## listen for ipv4 

    server_name redmine.yourdomain.com; 

    access_log  /var/log/nginx/redmine.access.log; 
    error_log  /var/log/nginx/redmine.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; 
      } 
    } 
}

NginxでRedmineを動作させるために/etc/nginx/sites-available/へシンボリックリンクを貼って、設定ファイルをチェックする。

# ln -s /etc/nginx/sites-available/redmine /etc/nginx/sites-enabled/redmine
# /etc/init.d/nginx configtest

OK!!問題なさそうだね。

そういや起動スクリプトを作ってないな。
gitlabの起動スクリプトを参考にしてredmine用の起動スクリプトをつくる。
vi /etc/init.d/redmine

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

# Redmine
# Maintainer: Your Name
# App Version: 2.2.2

### BEGIN INIT INFO
# Provides:          redmine
# Required-Start:    $local_fs $remote_fs $network $syslog 
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Redmine Project management
# Description:       Redmine Project management
### END INIT INFO


APP_ROOT="/srv/redmine"
DAEMON_OPTS="-c $APP_ROOT/config/unicorn.rb -E production -D"
PID_PATH="$APP_ROOT/tmp/pids"
UNICORN_PID="$PID_PATH/unicorn.pid"
NAME="unicorn"
DESC="Redmine service"

check_pid(){
  if [ -f $UNICORN_PID ]; then
    PID=`cat $UNICORN_PID`
    STATUS=`ps aux | grep $PID | grep -v grep | wc -l`
  else
    STATUS=0
    PID=0
  fi
}

start() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    # Program is running, exit with error code 1.
    echo "Error! $DESC $NAME is currently running!"
    exit 1
  else
    if [ `whoami` = root ]; then
      sudo -u www-data -H bash -l -c "nohup unicorn_rails $DAEMON_OPTS  > /dev/null  2>&1 &"
      sudo -u www-data -H bash -l -c "mkdir -p $PID_PATH  > /dev/null  2>&1 &"
      echo "$DESC started"
    fi
  fi
}

stop() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    ## Program is running, stop it.
    kill -QUIT `cat $UNICORN_PID`
    sudo -u www-data -H bash -l -c "mkdir -p $PID_PATH  > /dev/null  2>&1 &"
    rm "$UNICORN_PID" >> /dev/null
    echo "$DESC stopped"
  else
    ## Program is not running, exit with error.
    echo "Error! $DESC not started!"
    exit 1
  fi
}

restart() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    echo "Restarting $DESC..."
    kill -USR2 `cat $UNICORN_PID`
    sudo -u www-data -H bash -l -c "mkdir -p $PID_PATH > /dev/null  2>&1 &"
    if [ `whoami` = root ]; then
      sudo -u www-data -H bash -l -c "mkdir -p $PID_PATH > /dev/null  2>&1 &"
    fi
    echo "$DESC restarted."
  else
    echo "Error, $NAME not running!"
    exit 1
  fi
}

status() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    echo "$DESC / Unicorn with PID $PID is running."
  else
    echo "$DESC is not running."
    exit 1
  fi
}

## Check to see if we are running as root first.
## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root"
    exit 1
fi

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  reload|force-reload)
        echo -n "Reloading $NAME configuration: "
        kill -HUP `cat $PID`
        echo "done."
        ;;
  status)
        status
        ;;
  *)
        echo "Usage: sudo service redmine {start|stop|restart|reload}" >&2
        exit 1
        ;;
esac

exit 0

rc.dに登録して、redmineのプロセスを起動する。
プロセスはちゃんと動いてるようだ。
これでOSをリブートしても自動で起動してくれる。

# chmod 755 /etc/init.d/redmine
# update-rc.d redmine defaults 21
# /etc/init.d/redmine start
# ps -ef | grep redmine
www-data 14165     1  0 Feb14 ?        00:00:07 unicorn_rails master -c /srv/redmine/config/unicorn.rb -E production -D  

それでは、最後にNginxで起動します。

# /etc/init.d/nginx start

ブラウザで独自ドメインでアクセスしてみる。

http://youredomain.com

オー!!エクセレント!!
長い戦いだったぜ〜

おまけ

運用ではログローテーションは必須なので設定しとく。
vi /etc/logrotate.d/redmine

/etc/logrotate.d/redmine
/srv/redmine/log/*.log {
        daily
        missingok
        rotate 20
        compress
        delaycompress
        notifempty
        copytruncate
        create 0640 www-data www-data
        dateext
}

参考
http://slunked.com/redmine-on-debian-6-with-unicorn-and-nginx/all/1

次回予告

ServerMan@VPSにgitlabをインストールする