Redmine3.4 を Nginx + Unicorn,  Sub-URI で動かす (Ubuntu18.04)

[redmine.tokyo](https://redmine.tokyo/) 勉強会にて、最近は Redmine を Nginx + Unicorn で動かしている例が多いと聞き、自宅サーバーの Redmine を Apache2 + Passenger から Nginx + Unicorn に移行。
Redmine は Sub-URI で運用。Redmine を Nginx + Unicorn で、かつ Sub-URI で構築する設定例が少なく、少し手間取ったため、備忘録を作成。

# 前提条件

* Nginx がインストールされていること
* Redmine が WEBrick で動作すること

本記事は既存の Redmine 環境を Nginx + Unicorn で動かす方法に絞って記載。

# 環境

* Raspberry Pi 3 B+
* Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1030-raspi2 armv7l)
* ruby 2.4.5 (rbenv で構築)
* Redmine 3.4.6
* MySQL 5.7.24
* Nginx 1.14.0 (apt-get でインストール)

rbenv と Redmine は下記ディレクトリにインストール。

<table>
  <tr>
    <td> rbenv </td>
    <td> /opt/rbenv </td></tr>
  </tr>
  <tr>
    <td> Redmine </td>
    <td> /opt/redmine </td></tr>
  </tr>
</table>

Redmine は下記環境で動作させる。

<table>
  <tr>
    <td> URI </td>
    <td> http://[hostname]/redmine/ </td>
  </tr>
  <tr>
    <td> 環境</td>
    <td> production </td></tr>
  </tr>
  <tr>
    <td> ユーザー </td>
    <td> redmine </td></tr>
  </tr>
  <tr>
    <td> グループ </td>
    <td> redmine </td></tr>
  </tr>
</table>


# 

# Unicorn

## インストール

Unicorn を Bundler でインストール。

Redmine の Gemfile.local を作成。

```:/opt/redmine/Gemfile.local
gem "unicorn"
```

bundle install を実行。

```
RAILS_ENV=production bundle install --without development test
```

## 設定

Redmine の config ディレクトリに Unicorn 用の設定ファイルを作成。設定の説明は [こちら](https://qiita.com/syou007/items/555062cc96dd0b08a610) を参照。

Unicorn のワーカープロセスがユーザー redmine、グループ redmine で動作するよう設定している。

```Ruby:/opt/redmine/config/unicorn.rb
rails_root = File.expand_path('../../', __FILE__)

ENV['BUNDLE_GEMFILE'] = rails_root + "/Gemfile"

worker_processes 2

working_directory rails_root

timeout 30

stderr_path File.expand_path('../../log/unicorn_stderr.log', __FILE__)
stdout_path File.expand_path('../../log/unicorn_stdout.log', __FILE__)

# Nginx と組み合わせて使用する場合
listen File.expand_path('/var/run/unicorn/redmine.sock', __FILE__)
# Unicorn 単体で使用する場合
#listen 8080

pid File.expand_path('../../tmp/pids/unicorn.pid', __FILE__)

preload_app true

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

user 'redmine', 'redmine'
```

ソケットファイルはディレクトリ /var/run/unicorn/ に作成する。 Ubuntu 18 では /var/run/ は tmpfs のため、OSを起動した際、ファイルは全て削除される。OSを起動した際ディレクトリ /var/run/unicorn/ が作成されるよう、tmpfiles.d の設定をする。

```/etc/tmpfiles.d/unicorn.conf
#Type   Path                    Mode    UID     GID     Age     Argument
d       /var/run/unicorn        0755    root    root    -
```

## サービス化

Unicorn をサービス化するため、UNIT 定義ファイルを作成。

Redmine は DB に接続できないと失敗するため、[Unit] セクションの After で MySQL サービスの後に起動するよう設定している。

```:/etc/systemd/system/redmine-unicorn.service
[Unit]
Description=Redmine Unicorn Server
After=mysql.service

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

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

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

unicorn_rails コマンドの `-E` オプションの値が環境変数 RAILS_ENV に、`--path` オプションの値が環境変数 RAILS_RELATIVE_URL_ROOT に、それぞれ設定される([参考](https://github.com/phusion/unicorn/blob/master/bin/unicorn_rails))。
環境変数は UNIT 定義ファイルの [Service] セクションでも設定可。

## 確認

ブラウザから Redmine の動作を確認する場合、unicorn.rb の listen の設定を一時的にソケットからポートに変更する。firewall が動作している場合、一時的にポートを開放することを忘れずに。

redmine-unicorn.service が認識されているか確認。

```
systemctl list-unit-files --type=service
``` 

サービスの起動を確認。

```
sudo systemctl start redmine-unicorn.service
``` 

サービスの状態確認。

```
sudo systemctl status redmine-unicorn.service
``` 

サービス停止。

```
sudo systemctl stop redmine-unicorn.service
``` 

OS 起動時にサービスが自動起動されるよう有効化。

```
sudo systemctl enable redmine-unicorn.service
``` 

OS 再起動。再起動後にサービスが起動されていることを確認。

# Redmine

Redmine が Sub-URI で動作するよう config.ru を編集。

```Ruby:/opt/redmine/config.ru
require ::File.expand_path('../config/environment',  __FILE__)

map ActionController::Base.config.relative_url_root || "/" do
  run RedmineApp::Application
end
```

Rails のセオリーに沿った設定を採用。
ActionController::Base.config.relative_url_root は環境変数 RAILS_RELATIVE_URL_ROOT の値が設定される。

# Nginx

Unicorn のサーバー設定に Unicorn の設定を追記。

```Nginx:/etc/nginx/sites-available/default
client_max_body_size 192M;

upstream redmine {
    server unix:/var/run/unicorn/redmine.sock fail_timeout=0;
}

server {

(途中省略)

        location /redmine {
                alias /opt/redmine/public;
                try_files $uri/index.html $uri.html $uri @redmine;
        }

        location @redmine {
                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_pass http://redmine;
        }

}
```

client_max_body_size ディレクティブは POST の最大サイズ。デフォルトの 1MB では小さすぎてファイルのアップロードに支障があるため、適宜設定しておく。

Nginx の設定を確認。

```
sudo nginx -t
```

設定を反映させる。

```
sudo nginx -s reload
```

ブラウザから http://[hostname]/redmine/ にアクセスできるか確認。

# 参考

* [CentOS7にRedmine3.2を入れ、nginx、unicornで動かす。 - Qiita](https://qiita.com/bikun_bikun/items/30951573fc900d78d0c9)
* [CentOS7にRailsとUnicornとNginxをインストールして連携させる（あとMySQLも） - とりとめも](http://marimomemo.hatenablog.jp/entry/2017/03/04/191921)
* [Unicorn設定のまとめ - Qiita](https://qiita.com/syou007/items/555062cc96dd0b08a610)
* [How to Install Redmine on Ubuntu 16.04 with Nginx & Unicorn](https://ericmathison.com/blog/how-to-install-redmine-on-ubuntu-16-04-with-nginx-and-unicorn/)
* [CentOS 6.3にRedmine + Unicorn + nginxな環境を構築する手順 - Qiita](https://qiita.com/s-yamaz@github/items/5b32919ea33caddbca82)
* [RedmineをCentOS 7上で動かすーUnicornとNginx編 - ソフトウェアエンジニアリング - Torutk](http://www.torutk.com/projects/swe/wiki/Redmine%E3%82%92CentOS_7%E4%B8%8A%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%99%E3%83%BCUnicorn%E3%81%A8Nginx%E7%B7%A8)
* [Redmine を Nginx + Unicorn へ移行 - tilfin's note](https://tilfin.hatenablog.com/entry/20130617/1371558070)
* [RailsアプリをSub-URIで動かす - Qiita](https://qiita.com/yteraoka/items/bf47a893c0007489dda7)
* [unicorn/unicorn_rails at master · phusion/unicorn](https://github.com/phusion/unicorn/blob/master/bin/unicorn_rails)
* [HowTo Install Redmine in a sub-URI - Redmine](http://www.redmine.org/projects/redmine/wiki/HowTo_Install_Redmine_in_a_sub-URI) (注：こちらに記載されているUnicorn+Nginxの設定例ではプラグインが動作しない)