背景と概要
もともとApacheでRedmineを運用していたのだが, 興味があってNginxに乗り換えてみた.
乗り換えついでに, SSL通信にも対応させた.
Nginxに/var/lib/redmineを読みに行くよう設定すればいいだけだと思っていたのだが,
Passsengerと連携するためには再コンパイルしなくてはならないことが判明した.
理由は次の通り.
Why can't Phusion Passenger extend my existing Nginx?
要するに, Nginxは動的モジュール読み込みに(あまり)対応しておらず,
サードパーティ製ツールと連携させる場合は, コンパイルし直して静的に読み込まなければならないようだ.
モジュールを動的に読み込めるApacheと比べると柔軟性にかけるようにも思えるが,
それゆえに高速な動作が可能なのであろう.
仕様
- CentOS 7.3
- Redmine 3.3.3
- Postgresql 9.2.18
- Ruby 2.3.3
- Rails 4.2.7
- ホスト名
www.hogehoge.com
旧構成 | 新構成 |
---|---|
Apache 2.4.6 | Nginx 1.10.2 |
SSLなし | SSLあり |
Nginxのインストール
passengerが組み込まれたnginxのインストーラを実行する.
# passenger-install-nginx-module --auto
yumでインストールした場合とは異なり,
ベンダー提供のアプリが格納される, /opt以下にインストールされる.
権限の変更
# chown -R nobody:nobody /opt/nginx
# chown -R 755 /opt/nginx
お約束.
nginxサービスの設定
systemdのunitファイルを作成する.
すでにyumなどでインストールしてある場合には, 数行を編集するだけでOK.
元のnginx設定ファイルが置かれていた, /etc/nginxに該当する箇所を, 新しい/opt/nginx
用に書き換える.
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/opt/nginx/logs/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but hasthe wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/opt/nginx/sbin/nginx -t -c /opt/nginx/conf/nginx.conf
ExecStart=/opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
編集内容を反映し, nginx.serviceを起動&自動起動設定.
# systemctl daemon-reload
# systemctl start nginx
# systemctl enable nginx
SSL対応
証明書は,さくらナレッジの記事を参考に, LetsEncryptで発行した.
全てのWebアクセスプロトコルはHTTPS化するというのが21世紀風らしいので,
いっそのこと80番ポートへのアクセスは全て443番にリダイレクトしてしまうことにした.
余談だが, このときちょっと困ったことがあった.
Nginxでリダイレクトに失敗していると思い込んでいた件
設定は以下の通り.
まず, passengerの配置場所を確認する.
# passenger-config --root
私の環境では,
/usr/local/lib/ruby/gems/2.3.0/gems/passenger-5.1.4
と表示された.
httpコンテキストの先頭に次の5行を追記.
http {
user nobody;
pid /opt/nginx/logs/nginx.pid;
passenger_root /usr/local/lib/ruby/gems/2.3.0/gems/passenger-5.1.4;
passenger_ruby /usr/local/bin/ruby;
include /opt/nginx/conf/conf.d/*.conf;
...
}
続けて, serverコンテキストを次のように書き換える.
server {
listen 80;
server_name www.hogehoge.com;
return 301 https://$host$request_uri;
}
SSL通信用に, 443番ポートで待ち受ける設定をする.
server {
listen 443 ssl;
server_name www.hogehoge.com;
root /var/www/html/;
ssl_certificate /path/to/your/cert.pem;
ssl_certificate_key /path/to/your/privkey.pem;
...
}
これで, ブラウザからhttp://www.hogehoge.com/
にアクセスすると,
https://www.hogehoge.com/
へリダイレクトされ, ホストOSの/var/www/html/以下が読まれるようになる.
Redmineとの連携
-
https://www.hogehoge.com/redmine/
でアクセスできるようにする. - /var/lib/redmine 以下にコンテンツが配置してあるとする.
Redmineの関連ファイルの所有者をnginxユーザに変更する.
# chown -R nginx:nginx /var/lib/redmine
SSL通信の設定ファイルに, 次のように追記する.
http {
listen 443 ssl;
...
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Server $host;
+ proxy_set_header X-Forwarded-Host $host;
server {
listen 443 ssl;
server_name www.hogehoge.com;
root /var/www/html/;
ssl_certificate /path/to/your/cert.pem;
ssl_certificate_key /path/to/your/privkey.pem;
...
+ location ~ ^/redmine {
+ passenger_base_uri /redmine;
+ passenger_app_root /var/lib/redmine;
+ passenger_enabled on;
+ rails_env production;
+ access_log /var/log/redmine_access.log;
+ error_log /var/log/redmine_error.log;
}
...
}
...
}
ブラウザからhttps://www.hogehoge.com/redmine/
にアクセスし,
以下のように表示されればOK.
以上です.
今度は, HTTPSの裏でDockerコンテナを動かして,
セキュアなWebHookを作ってみたいなぁ.