Centos7にNginx + UnicornでRedmine3.3構築方法

# [概要]
CentOS7にNginx + UnicornでRedmine3.3を構築する。


# [事前準備]
下記が構築済みであることが前提です。
[CentOS7の初期セットアップ手順](http://qiita.com/sabakan7/items/779fa69bf9e15b9e6fee)

# [作業内容]
## 必要パッケージインストール
```bash
$ sudo yum install openssl-devel
$ sudo yum install readline-devel
$ sudo yum install curl-devel
$ sudo yum install libyaml-devel
$ sudo yum install ImageMagick
$ sudo yum install ImageMagick-devel
$ sudo yum install wget
$ sudo yum install git
$ sudo yum install bzip2
$ sudo yum install gcc
```

## MySQLインストール
### MySQLのリポジトリ追加
```bash
$ sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
```

### 最新版のMySQLインストール
```bash
$ sudo yum install mysql mysql-server mysql-devel
```

### my.cnfの編集
```bash
sudo vi /etc/my.cnf
```

元からある my.cnf を全て消して下記を設定する

```/etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

character-set-server = utf8

[mysql]
default-character-set = utf8
```

### MySQL起動
```bash
$ sudo systemctl start mysqld.service
```

### MySQL自動起動設定
```bash
$ sudo systemctl enable mysqld.service
```

### MySQLの起動確認
`running` になってるのを確認

```bash
$ sudo systemctl status mysqld.service
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2016-08-14 22:22:38 JST; 43s ago
 Main PID: 45334 (mysqld)
   CGroup: /system.slice/mysqld.service
           └─45334 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

 8月 14 22:22:31 redmine.ghfdjk.me systemd[1]: Starting MySQL Server...
 8月 14 22:22:38 redmine.ghfdjk.me systemd[1]: Started MySQL Server.
```

### MySQLの初期パスワード確認
初期パスワードが、設定されいるのでそれを確認

```bash
$ sudo cat /var/log/mysqld.log | grep password
2016-08-14T13:22:34.726150Z 1 [Note] A temporary password is generated for root@localhost: <..9k>ocRD8r
```

### MySQLの初期設定
```bash
$ sudo mysql_secure_installation

Securing the MySQL server deployment.

### /var/log/mysqld.log に記載されていた初期パスワードを入力
Enter password for user root: ### <..9k>ocRD8r を入力

The existing password for the user account root has expired. Please set a new password.

New password: ### 新しいパスワードを入力

Re-enter new password:　### 新しいパスワードをもう一度入力

### パスワードのポリシーを強化するプラグインをインストール
The 'validate_password' plugin is installed on the server.
The subsequent steps will run with the existing configuration
of the plugin.
Using existing password for root.

### 強化されたポリシーに則りパスワードを再設定
Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : y

New password: ### 新しいパスワードを入力

Re-enter new password: ### 新しいパスワードをもう一度入力

### anonymous ユーザを削除
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

### リモートからの root ログインを禁止
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.

### test データベースを削除する
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

### 権限設定を読み込む
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!
```

### /root/.my.cnf作成
```bash
$ sudo vi /root/.my.cnf
```

下記を参考に作成する
※ `{password}` は適宜修正してくだい。

```bash
[client]
user = root
password = {password}
```

## Redmine用のデータベース作成とユーザ作成
### redmineデータベース作成
```bash
$ sudo mysql -u root -p
mysql> CREATE DATABASE redmine charset="utf8";
```

### redmineユーザ作成
※ `{password}` は適宜変更してください

```bash
mysql> GRANT ALL PRIVILEGES ON redmine.* TO redmine@localhost IDENTIFIED BY '{pasword}';
mysql> exit
```

## rbenv + ruby-buildのセットアップ
```bash
$ cd /opt
$ sudo git clone https://github.com/sstephenson/rbenv.git
$ sudo mkdir /opt/rbenv/plugins
$ cd /opt/rbenv/plugins
$ sudo git clone https://github.com/sstephenson/ruby-build.git
```

### profile.dにファイルを作成
```bash
$ sudo vi /etc/profile.d/rbenv.sh
```

下記を記述する

```/etc/profile.d/rbenv.sh
export RBENV_ROOT="/opt/rbenv"
export PATH="${RBENV_ROOT}/bin:${PATH}"
eval "$(rbenv init --no-rehash -)"
```

### /opt/rbenv の権限を変更
```bash
$ sudo chgrp -R staff /opt/rbenv
$ sudo chmod -R 775 /opt/rbenv
```

### rubyインストール
```bash
### 環境変数を読み込み
$ source /etc/profile.d/rbenv.sh

### ruby 2.3.1 をインストール
$ rbenv install 2.3.1

### ruby 2.3.1 を全体に反映
$ rbenv global 2.3.1
```

## Redmineインストール
```bash
$ cd /opt
$ sudo wget http://www.redmine.org/releases/redmine-3.3.0.tar.gz
```

### Redmineを解凍
```bash
$ sudo tar zxf redmine-3.3.0.tar.gz
```

### Redmineのシンボリックリンク作成
```bash
$ sudo ln -s redmine-3.3.0 redmine
```

### RedmineのDB設定
まずは、設定ファイルをバックアップ

```bash
$ sudo cp redmine/config/database.yml.example redmine/config/database.yml
```

```bash
$ sudo vi redmine/config/database.yml
```

`password` をmysql用DBのパスワードを設定する

```/opt/redmine/config/database.yml
production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: {password}
  encoding: utf8
```

* 設定値について
 - `database.yml`には`production`以外に`development`、`test`の設定がありますが、基本は`production`のみ使用するのでパスワード設定は`production`だけに設定すれば良いです。
 - `adapter`はMySQLの場合はmysql2を指定します。
 - `database`はRedmineで使用するデータベース名指定します。
 - `username`はMySQLのデータベースに接続するMySQLのユーザー名を指定します。
 - `password`は`username`で指定したMySQLのユーザーのパスワードを指定します。
 - `encoding`はMySQLで使用する文字エンコーディングを指定します。通常utf8となる。

### Redmineメール設定
まずは、設定ファイルをバックアップ

```bash
$ sudo cp /opt/redmine/config/configuration.yml.example /opt/redmine/config/configuration.yml
```

### メール設定ファイル編集
```bash
$ sudo vi /opt/redmine/config/configuration.yml
```

`production:`の箇所に設定する

```/opt/redmine/config/configuration.yml
# specific configuration options for production environment
# that overrides the default ones
production:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: "localhost"
      port: 25
```

### 権限変更
```bash
$ sudo chgrp -R staff /opt/redmine*
```

### システム共通のRubyモジュールインストール
```bash
$ cd /opt/redmine
$ gem install bundler --no-rdoc --no-ri
```

### Redmineで必要なRubyモジュールインストール
```bash
$ cd /opt/redmine
$ bundle install --path vendor/bundler --without development test
```

### セッションデータ暗号化
改ざん防止のため、セッションデータを格納するクッキーを暗号化する鍵をランダムに生成

```bash
$ bundle exec rake generate_secret_token
/opt/redmine-3.3.0/vendor/bundler/ruby/2.3.0/gems/htmlentities-4.3.1/lib/htmlentities/mappings/expanded.rb:465: warning: key "inodot" is duplicated and overwritten on line 466
### 上記のようにでればOK
```

### データベースのスキーマ構築
```bash
$ bundle exec rake db:migrate RAILS_ENV=production
```

### Railsアプリケーションサーバ(Unicorn)のインストール
```bash
$ sudo vi /opt/redmine/Gemfile.local
```

下記を記述
```/opt/redmine/Gemfile.local
gem "unicorn"
```

### Unicornのインストール
```bash
$ cd /opt/redmine
$ bundle update
```

### Systemd用のUnicornサービス定義ファイルの作成
Redmine（Unicorn）は、起動時にデータベースに接続できないとエラー終了してしまいます。
そこで、`[Unit]`セクションに`After`で、`mysqld.service`が実行されてから`redmine-unicorn.service`が起動されるよう順序を指定します。

```
$ sudo vi /usr/lib/systemd/system/redmine-unicorn.service
```

```/usr/lib/systemd/system/redmine-unicorn.service
[Unit]
Description=Redmine Unicorn Server
After=mysqld.service

[Service]
WorkingDirectory=/opt/redmine
Environment=RAILS_ENV=production
SyslogIdentifier=redmine-unicorn
PIDFile=/opt/redmine/tmp/pids/unicorn.pid

ExecStart=/opt/rbenv/shims/bundle exec "unicorn_rails -c config/unicorn.rb -E production"
ExecStop=/usr/bin/kill -QUIT $MAINPID
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
```

## Unicorn設定
```bash
$ sudo vim /opt/redmine/config/unicorn.rb
```

```/opt/redmine/config/unicorn.rb
worker_processes 2

app_path = "/opt/redmine"

listen  File.expand_path('tmp/unicorn_redmine.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
```

### redmine-unicorn起動
```bash
$ sudo systemctl start redmine-unicorn.service
```

### redmine-unicornのプロセス確認
```bash
### active になっているのを確認
$ sudo systemctl status redmine-unicorn.service
● redmine-unicorn.service - Redmine Unicorn Server
   Loaded: loaded (/usr/lib/systemd/system/redmine-unicorn.service; disabled; vendor preset: disabled)
   Active: active (running) since 木 2016-09-22 22:31:34 JST; 19s ago
 Main PID: 35806 (ruby)
   CGroup: /system.slice/redmine-unicorn.service
           ├─35806 unicorn_rails master -c config/unicorn.rb -E production
           ├─35836 unicorn_rails worker[0] -c config/unicorn.rb -E production
           └─35838 unicorn_rails worker[1] -c config/unicorn.rb -E production

 9月 22 22:31:34 redmine.ghfdjk.me systemd[1]: Started Redmine Unicorn Server.
 9月 22 22:31:34 redmine.ghfdjk.me systemd[1]: Starting Redmine Unicorn Server...
```

### redmine-unicornの自動起動設定
```bash
$ sudo systemctl enable redmine-unicorn.service
```

## Nginxインストール
### Nginxのリポジトリ追加
```bash
$ sudo vi /etc/yum.repos.d/nginx.repo
```

```/etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
```

### Nginxのパッケージ追加
```bash
$ sudo yum install nginx
```

### Nginx自動起動設定
```bash
$ sudo systemctl enable nginx.service
```

### Redmineの設定ファイルを作成
```
$ cd /etc/nginx/conf.d
```

### 元の設定ファイルをバックアップ
```bash
$ sudo mv default.conf default.conf.orig
```

```bash
$ sudo vi /etc/nginx/conf.d/redmine.conf
```

```bash
upstream unicorn-redmine {
    server unix:/opt/redmine/tmp/unicorn_redmine.sock;
}

server {
    listen 80;
    server_name {ドメイン名};

    root /opt/redmine/public;
    client_max_body_size 1G;

    location / {
        try_files $uri/index.html $uri.html $uri @app;
    }

    location @app {
        proxy_redirect off;
        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;
        proxy_connect_timeout 60;
        proxy_read_timeout 60;
        proxy_send_timeout 600;
        proxy_pass http://unicorn-redmine;
    }

    error_page 500 502 503 504 /500.html;
}
```

### 設定フィアルのsyntax確認
```bash
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

### Nginx起動
```bash
$ sudo systemctl start nginx
```

## [事後確認・作業]