はじめに
今回、WebサーバーにNginxを、アプリケーションサーバーにunicorn(+ Ruby on Rails + Redmine)を、データベースサーバーにMariaDBをそれぞれ採用して、CentOS7のインストールイメージminimalを使って構築したいと思います。 なお、アプリケーションサーバーの部分についてはWebサーバーやデータベースサーバーと同様に、systemctlコマンドで起動や停止ができるようにします。
ホストの準備
本環境をセットアップするホストを準備します。AWS EC2インスタンスを使用する場合と、オンプレミス環境で一から構築する場合を想定します。
OSインストールとホスト起動
AWS EC2向け
CentOS公式サイト ダウンロードページからISOファイルのファイル名を参照して最新の日付(YYMM)を確認します。 AWS マネジメントコンソールにサインインしてEC2ダッシュボード画面を表示します。インスタンス作成時に、AWS Marketplaceから「CentOS HVM」で検索すれば、最新のCentOS7を利用できます。
オンプレミス向け
CentOS公式サイト ダウンロードページからISOファイルをダウンロードします。OSインストーラーを起動してインストールします。
設定バックアップ用ディレクトリ作成
# mkdir -p /root/originalfiles
SELinux無効化
# setenforce 0
# cp /etc/sysconfig/selinux /root/originalfiles/etc__sysconfig__selinux
# vi /etc/sysconfig/selinux
# diff /root/originalfiles/etc__sysconfig__selinux /etc/sysconfig/selinux
7c7
< SELINUX=enforcing
---
> SELINUX=disabled
SSHサーバー追加
オンプレミス環境でminimalイメージからセットアップした場合、SSHサーバーがインストールされていませんので、TTY端末で下記コマンドを実行してインストールします。
# yum install openssh-server
# systemctl start sshd
# systemctl enable sshd
以降、手元のPCのSSH端末を使用してリモートで操作できるようになります。
postfixインストール
Redmineはチケットのステータスが変更されたときなど、メールで通知する機能があります。メールを送信できるようにするため、Postfixをインストールします。
パッケージインストール
# yum install postfix
設定調整
このホストからはメールを発送するだけですので、送り元となるサーバーのFQDNを指定するだけにします。
# cp /etc/postfix/main.cf /root/originalfiles/etc__postfix__main.cf
# vi /etc/postfix/main.cf
# diff /root/originalfiles/etc__postfix__main.cf /etc/postfix/main.cf
75c75
< #myhostname = host.domain.tld
---
> myhostname = redmine.example.com
98c98
< #myorigin = $myhostname
---
> myorigin = $myhostname
サーバー起動
# systemctl restart postfix
# systemctl enable postfix
メールテスト送信
実際にどのようにメールが発送されるか確認します。このホストのroot宛のメールはすべて普段使っているメールアドレス宛に転送するようにします。このコマンドを実行すると、送り主はroot@redmine.example.comとなっているはずです。以降、このホストのユーザー(Linuxユーザー)から発送されるメールの差出人は「@redmine.example.com」となります。
# echo 'myaddress@example.com' >> /root/.forward
# yum install mailx
# echo 'transport test from new redmine server' \
| mail -s 'transport test' root
MariaDB5.5インストール
Redmineのユーザーデータを格納するデータベースサーバーをインストールします。
パッケージインストール
# yum install mariadb-server
設定調整
# cp /etc/my.cnf.d/server.cnf /root/originalfiles/etc__my.cnf.d__server.cnf
# vi /etc/my.cnf.d/server.cnf
# diff /root/originalfiles/etc__my.cnf.d__server.cnf /etc/my.cnf.d/server.cnf
9a10
> character-set-server = utf8
# cp /etc/my.cnf.d/client.cnf /root/originalfiles/etc__my.cnf.d__client.cnf
# vi /etc/my.cnf.d/client.cnf
# diff /root/originalfiles/etc__my.cnf.d__client.cnf /etc/my.cnf.d/client.cnf
7a8
> default-character-set = utf8
サーバー起動
# systemctl start mariadb
# systemctl status mariadb
# systemctl enable mariadb
Redmineアプリケーションサーバー構築
インストールドキュメントによると、Redmine3.4.3 (2017.10.21時点で最新の安定版)にはruby2.4、Rails4.2を使えばよさそうです。 Redmine、Ruby on Rails環境、unicornをすべて、アプリケーション実行用ユーザーapp-userで実行するようにします。
アプリケーションユーザー追加
# useradd app-user
ruby2.4インストール
ruby2.4はapp-userのユーザーローカル環境にセットアップして、OSの共通領域をクリーンに保つようにします。
ビルド環境インストール
# yum groupinstall "Development Tools"
# yum install openssl-devel readline-devel zlib-devel curl-devel libyaml-devel mariadb-devel ImageMagick ImageMagick-devel
rbenvセットアップ
# su - app-user
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ cd ~/.rbenv
$ src/configure && make -C src
$ vi ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH="$PATH:$HOME/bin"
PATH="$PATH:$HOME/.rbenv/bin" ← この行を追記
export PATH
$ ~/.rbenv/bin/rbenv init
$ vi ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH="$PATH:$HOME/bin"
PATH="$PATH:$HOME/.rbenv/bin"
export PATH
eval "$(rbenv init -)" ← この行を追記
app-user環境をリロードするため、一度ログアウトしてログインしなおします。type rbenvを実行すると、rbenv() の内容が表示されるようになります。
$ logout
# su - app-user
$ type rbenv
rbenv is a function
rbenv ()
{
local command;
command="$1";
if [ "$#" -gt 0 ]; then
shift;
fi;
case "$command" in
rehash | shell)
eval "$(rbenv "sh-$command" "$@")"
;;
*)
command rbenv "$command" "$@"
;;
esac
}
ruby-buildプラグインインストール
Railsインストールのため、ruby-buildをインストールします。
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
Rubyインストール
利用できるRubyのバージョン一覧を確認します。
$ rbenv install -l
2.4.x のうち最新のものを指定してインストールします。
$ rbenv install 2.4.2
app-userがデフォルトで利用するrubyのバージョンを明示的に指定します。
$ rbenv global 2.4.2
$ ruby -v
Rails4.2インストール
railsのバージョン一覧を確認します。
$ gem list '^rails
rails 4.2.x のうち最新バージョンをインストールします。
$ gem install rails --version "~>4.2.0"
インストールされたrailsのバージョンを確認します。
$ rails --version
Redmine3.4インストール
データベースアカウント作成
$ mysql -u root
> CREATE DATABASE redmine CHARACTER SET utf8;
> CREATE USER 'redmine'@'localhost';
> GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';
> QUIT;
パッケージインストール
$ mkdir ~/src
$ cd ~/src
$ curl -LO http://www.redmine.org/releases/redmine-3.4.2.tar.gz
$ tar fx redmine-3.4.2.tar.gz
$ logout
# cp -r /home/app-user/src/redmine-3.4.2 /var/lib/redmine
# chown -R app-user:app-user /var/lib/redmine
設定調整
Redmineがデータベースサーバーに接続できるようにします。
# su - app-user
$ cp /var/lib/redmine/config/database.yml.example /var/lib/redmine/config/database.yml
$ vi /var/lib/redmine/config/database.yml
$ diff /var/lib/redmine/config/database.yml.example /var/lib/redmine/config/database.yml
config/database.yml
9c9
< username: root
---
> username: redmine
Redmineがメールを発送する方法を指定します。今回はPostfixに対してsendmailコマンドで送るように設定します。
先の手順で、mailコマンドを使ってroot宛にメールの発送テストをしましたが、mailコマンドもsendmailコマンドを使用してメールを発送します。
$ cp /var/lib/redmine/config/configuration.yml.example /var/lib/redmine/config/configuration.yml
$ vi /var/lib/redmine/config/configuration.yml
$ diff /var/lib/redmine/config/configuration.yml.example /var/lib/redmine/config/configuration.yml
config/configuration.yml
15a16
> delivery_method: :sendmail
RedmineのWebUIでアップロードされたファイルの保存先ディレクトリを作成します。
ファイルの保存先を変更するには、config/configuration.ymlの「attachments_storage_path」に目的のパスを指定します。
$ logout
# mkdir -p /var/redmine/files
# chown app-user:app-user /var/redmine/files
# su - app-user
gemインストール
Redmineが使用するgemをインストールします。
$ cd /var/lib/redmine
$ bundle install --without development test rmagick
$ bundle exec rake generate_secret_token
データベース更新
$ cd /var/lib/redmine
$ bundle exec rake db:migrate RAILS_ENV=production
クリーンアップ
$ bundle exec rake tmp:cache:clear tmp:sessions:clear RAILS_ENV=production
Unicornインストール
Gemfile.local 作成
$ cd /var/lib/redmine
$ cat << EOF > Gemfile.local
gem "unicorn"
EOF
依存パッケージインストール
$ bundle install --without development test
アプリケーションサーバー動作確認と初期設定
$ bundle exec unicorn_rails -l 3000 -E production
http://host-address:3000/ などでアクセスして、RedmineのWebUIが表示できることを確認します。(終了するには「Ctrl + C」を入力します) ここで、管理者アカウントのパスワードを変更しておきます。管理者アカウントのIDと初期パスワードはともに「admin」です。
デーモンプロセス化
systemctlコマンドでアプリケーションサーバーを起動・停止できるようにします。今回、アプリケーションサーバーは3000番ポートでリッスンすることとします。
アプリケーション設定
$ vi /var/lib/redmine/config/unicorn.rb
/var/lib/redmine/config/unicorn.rb
worker_processes 2
app_path = "/var/lib/redmine"
listen 3000
#listen File.expand_path('tmp/unicorn.sock', app_path)
pid File.expand_path('tmp/unicorn.pid', app_path)
stderr_path File.expand_path('log/unicorn.stderr.log', app_path)
stdout_path File.expand_path('log/unicorn.stdout.log', app_path)
preload_app true
timeout 30
if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end
before_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
end
end
end
after_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
SECRET_KEY_BASE 取得
SECRET_KEY_BASEの値は、次のコマンドを実行して取得できます。
$ cd /var/lib/redmine
$ bundle exec rake secret
ここで 0~9、a~f 128文字からなる文字列を得られます。
systemctlコマンド用スクリプト作成
systemctlコマンドで指定するサービス名でファイルを作成します。サービス起動順序の依存関係として、MariaDBが起動してからアプリケーションサーバーを起動するよう指定します。
$ logout
# vi /etc/systemd/system/unicorn-redmine.service
/etc/systemd/system/unicorn-redmine.service
[Unit]
Description=redmine
Wants=mariadb.service
After=mariadb.service
[Service]
User=app-user
WorkingDirectory=/var/lib/redmine
Environment=RAILS_ENV=production
Environment=RAILS_SERVE_STATIC_FILES=1
Environment=SECRET_KEY_BASE=<[0-9a-f]{128}な文字列>
SyslogIdentifier=unicorn-redmine
PIDFile=/var/lib/redmine/tmp/unicorn.pid
ExecStart=/home/app-user/.rbenv/shims/bundle exec "unicorn_rails -D -c /var/lib/redmine/config/unicorn.rb -E production"
[Install]
WantedBy=multi-user.target
アプリケーションサーバー起動
# systemctl start unicorn-redmine
# systemctl status unicorn-redmine
# systemctl enable unicorn-redmine
もしここでサービスの起動が失敗する場合は、/var/lib/redmine/log/unicorn.stderr.log
を確認してください。 私の環境で起こった事なのですが、「アプリケーションサーバー動作確認と初期設定」で手動では起動できるけれど、systemctl start unicorn-redmine
を実行すると失敗する、という現象が発生しました。原因は /var/lib/redmine/tmp/unicorn.sock
がソケットファイルではなく通常ファイルになってしまっていたことでした。/var/lib/redmine/tmp/unicorn.sock
を削除して、再度 systemctl start unicorn-redmine
を実行すれば、無事起動するようになりました。エラーメッセージは下記のとおりです。
F, [2017-10-22T14:02:23.476984 #1554] FATAL -- : error adding listener addr=/var/lib/redmine/tmp/unicorn.sock
/home/app-user/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/unicorn-5.3.0/lib/unicorn/socket_helper.rb:131:in `bind_listen': socket=/var/lib/redmine/tmp/unicorn.sock specified but it is not a socket! (ArgumentError)
nginxインストール
Redmineがアプリケーションサーバーとして起動しました。これのフロントエンドとしてNginxをインストールして、連携させます。
リポジトリ追加
# yum install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
パッケージインストール
# yum install nginx
アプリケーションサーバーとの連携
# mv /etc/nginx/conf.d/default.conf /root/originalfiles/etc__nginx__conf.d__default.conf
# vi /etc/nginx/conf.d/redmine.conf
upstream redmine {
server localhost:3000;
}
server {
listen 80;
server_name redmine.example.com;
root /var/lib/redmine/public;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
location / {
if (-f $request_filename) {
break;
}
proxy_pass http://redmine;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
# systemctl restart nginx
# systemctl status nginx
# systemctl enable nginx