UbuntuのRedmineをApacheで動かす (HTTPSとCORSに対応)

Redmine

はじめに

以前の投稿でUbutntuにRedmine 4.2/5.0をインストールする手順について紹介しました。その続きとして、WebサーバーにApacheを使い、自己署名証明書 (いわゆるオレオレ証明書) を使ってHTTPS化したので、その手順を紹介します。CORS対応についても説明しています。

前記事から続く …

UbuntuにRedmine 5.0/Ruby 3.1をインストールする
UbuntuにRedmine 4.2/5.0をインストールする

RedSync – Redmineをタスク管理の定番ツールTrelloと連携

RedmineとTrelloの連携 - 作業支援と進捗管理を融合 (デモあり)
Trelloを使った日々の作業の中で、Redmineからアサインされたタスクを実行し、そのステータスや進捗をRedmineに報告することができます。個人とチームの作業を支援し、同時にプロマネによる効果的な進捗管理を実現できます。

環境

ソフトウェアのバージョンは次の通りです。

  • OS: Ubuntu 20.04 LTS
  • Redmine: 4.2, 5.0
  • Apache 2.4
  • Passenger 5.0

セットアップの手順

前記事でPumaを使って稼働確認を行ったところから継続します。

  • Apacheのインストール
  • ApacheのHTTPS化
  • Passengerのインストール
  • Passengerの構成
  • CORSの構成

特に指定しない場合は、作業はホームディレクトリ (/home/redmine) で行うものとします。

サービスの停止

以前の投稿で、Redmineの起動をサービス化している場合は、サービスを停止します。

sudo systemctl stop redmine
sudo systemctl disable redmine

Apacheのインストール

参考資料: Install and Configure Apache

まずレポジトリを最新化します。

sudo apt update

Apacheをインストールします。

sudo apt install apache2

ブラウザで、http://<サーバーアドレス> にアクセスすると、デフォルトのページが表示されます。

ApacheのHTTPS化

参考資料:
1) How to enable HTTPS protocol with Apache 2 on Ubuntu 20.04
2) How to create a Self-Signed SSL Certificate on Ubuntu 18.04

自己署名証明書の作成

秘密鍵 (private.key) と署名リクエスト (request.csr) を作成します。秘密鍵は暗号化せずに作成しています。暗号化していると、Apacheを起動するサービス中でPass Phraseの入力を求められ、エラーとなるためです。

cd ~
openssl genrsa -out private.key 2048
openssl req -new -key private.key -out request.csr

作成中、次のような質問が表示されます。

Common Name (e.g. server FQDN or YOUR name) []:

参考資料1)によれば、ここにはFQDNまたはIPアドレスを指定せよ、となっています。筆者はIPアドレスを指定しました。(YOUR nameとなっているので、何でも良さそうではあるのですが …)

証明書 (certificate.crt) を生成します。

openssl x509 -in request.csr -out certificate.crt -req -signkey private.key -days 365

正しく実行されると、Signature ok と表示されます。

プライベートキーのアクセス権限を制限しておきます。

chmod 400 private.key

プライベートキーを暗号化していないことで、セキュリティレベルが下がることが気になります。ただApacheのFAQにもこの方法が書かれています。

How can I get rid of the pass-phrase dialog at Apache startup time?

ここまでで次の3つのファイルが作成されます。

  • request.csr
  • certificate.crt
  • private.key

このうちcertificat.crt, private.keyの2つのファイルを、次のようにフォルダを作成して保管します。

sudo mkdir /etc/certificate
sudo cp certificate.crt /etc/certificate
sudo cp private.key /etc/certificate

Apache SSLパラメータの定義

Apacheの構成ファイルに読み込むSSLパラメータを定義します。

sudo vim /etc/apache2/conf-available/ssl-params.conf

次の内容をコピーします。(筆者は不勉強のため解説不能 …)

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
    
    SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    
    SSLHonorCipherOrder On
    
    
    Header always set X-Frame-Options DENY
    
    Header always set X-Content-Type-Options nosniff
    
    # Requires Apache >= 2.4
    
    SSLCompression off
    
    SSLUseStapling on
    
    SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
    
    
    # Requires Apache >= 2.4.11
    
    SSLSessionTickets Off

署名証明書をSSLに組み込む

HTTPSのリクエストを受けるサイト定義に、証明書を組み込みます。

定義ファイルを開きます。

sudo vim /etc/apache2/sites-available/default-ssl.conf

定義フィル内で次の記述を探します。

                    SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem  
                    SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

これを先に作成した証明書で置き換えます。

                    SSLCertificateFile      /etc/certificate/certificate.crt
                    SSLCertificateKeyFile /etc/certificate/private.key

参考資料1)では、ServerNameを追加するようになっています。筆者は後述するredmine.confの中で定義しました。

また参考資料1)では、ファイヤウォール (UFW) の設定が行われていますが、筆者は自宅内LANの環境なのでスキップしました。(sudo ufw statusで確認したところinactiveでした)

構成の適用

必要なモジュールを組み込むみます。

sudo a2enmod ssl
sudo a2enmod headers

SSLパラメータ定義を組み込みます。

sudo a2enconf ssl-params

HTTPSアクセスを受け付けるサイトの定義を組み込みます。

sudo a2ensite default-ssl

構成をテストします。

sudo apache2ctl configtest

次のメッセージが出ればOKです。ServerNameについては後で解消します。

AH00558: apache2: Could not reliably determine the server’s fully qualified domain name, using 127.0.1.1. Set the ‘ServerName’ directive globally to suppress this message
Syntax OK

Apacheサーバーを再起動します。

sudo systemctl restart apache2

ブラウザで、https://<server address> にアクセスします。

自己署名証明書のためブラウザから警告画面が表示されますが、指示に従ってアクセスを許可します。

デフォルトのページが表示されます。

セキュリティ警告の回避方法について

インターネット上に公開されるサーバーであれば、正式な証明書を組み込むべきでしょう (Let’s Encryptのような無料のサービスもありますし)。

イントラネットの場合は、イントラネット内にプラベート認証局を立てて、その認証局で署名した証明書を使うことで警告を回避できます (筆者もこの方法を使っています)。

参考: Ubuntu 20.04で認証局(CA)をセットアップおよび設定する方法

別の方法として、もしドメインを所有しDNSの設定ができるのであれば、イントラであってもLet’s Encryptを利用できます。筆者も条件は満たすのですが、DNSの設定と反映に時間がかかるため、この方式はとっていません。 (テスト環境なので直ぐに結果を見たいのです …)

Apacheの構成ファイルについて

Apacheの構成ファイルは構造化され複数のファイルに分かれています。

メインの構成ファイルとして、

/etc/apache2/apache2.conf

があり、ここに次のディレクトリ群に入っている個別の構成ファイルを読み込むようになっています。

/etc/apache2/(conf|mods|sites)-available
/etc/apache2/(conf|mods|sites)-enabled

個別の構成ファイルの入るディレクトリは、availableとenabledのペアとなっています。availableにファイルの実体を配置し、その中で実際に使うものをenabledにリンクしてあります。Apacheは起動時に、enabledからファイルを読み込んで、メインの構成ファイルに組み込みます。enabledにリンクするには、次のコマンドを使います。

a2ensite
a2enconf
a2enmod

Passengerのインストール

Phusion Passengerは、アプリケーションサーバーで、ここではRubyで書かれたアプリケーションの実行環境として使われます。Apacheの他、NGINXとの組み合わせもポピュラーなようです。

参考資料:
1) Installing Passenger on Ubuntu 20.04 LTS (with APT)
2) Introduction to configuring Passenger
3) Configuration reference for Passenger + Apache

インストールの準備をします。(Passengerレポジトリの取得準備のようですが詳細未確認)

sudo apt-get install -y dirmngr gnupg
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates

レポジトリを更新します。

sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger focal main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update

Passenger本体とApache用のモジュールをインストールします。

sudo apt-get install -y libapache2-mod-passenger

Apacheサーバーを再起動します。

sudo systemctl restart apache2

インストール結果を検査します。

sudo /usr/bin/passenger-config validate-install

この結果、次のメッセージが表示されます。

 * Checking whether this Passenger install is in PATH... ✓
 * Checking whether there are no other Passenger installations... ✓
 * Checking whether Apache is installed... ✗

   Unable to validate your Apache installation: more software required

   This program requires the apxs2 tool in order to be able to validate your
   Apache installation. This tool is currently not installed. You can solve this
   as follows:

   Please install it with apt-get install apache2-threaded-dev

   When done, please re-run this program.


Detected 1 error(s), 0 warning(s).

この指示に従ってapache2-threaded-devをインストールしようとすると、E: Unable to locate package apache2-threaded-devとのメッセージがでます。ネット上には、代わりにapache2-devをインストールすれば良いとの情報もあるが真偽は不明です。(確かにエラーは無くなりますが …) 筆者はそのまま放置としました。

Passengerのプロセスが起動していることを確認します。

sudo /usr/sbin/passenger-memory-stats

Passengerのインストール方法には、RubyのGemとしてインストールする方法もあります。ネット上の記事ではこちらの方法を取っているものが多いようです。

Installing Passenger from RubyGem (with RVM)

Passengerの構成

PassengerでRedmineを呼び出すように構成ファイルを作成します。

sudo vim /etc/apache2/conf-available/redmine.conf

次の内容をコピーします。ServerNameは、自己署名証明書を作成した時に指定したもので置き換えます。(違っていても稼働するので、特に意味は無いのかも …)

ServerName 192.168.xx.xx
<IfModule mod_passenger.c>
    DocumentRoot /opt/redmine/public
    PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
    PassengerDefaultRuby /home/redmine/.rbenv/shims/ruby
</IfModule>

<Directory /opt/redmine/public>
    Allow from all
    Options -MultiViews
    Require all granted
</Directory>

PassengerRootの確認方法を失念しました。PassengerDefaultRubyについては、which rubyで確認しました。

「備忘録: UbuntuにRedmine 4.2/5.0をインストールする (CORS対応)」の古い記事では、ホーム (/home/redmine) にRedmineをインストールしていました。その記事から来られた方は、上記の定義で、/opt/redmine -> /home/redmine/redmine と読み替えてください。本記事では、Redmineのインストール先を/opt/redmineに変更しています。

HTTPSサイトの定義から、DocumentRootをコメントアウトします。(redmine.confと二重定義になるで)

sudo vim /etc/apache2/sites-available/default-ssl.conf
# DocumentRoot /var/www/html

設定を組み込みます。

sudo a2enconf redmine

Apacheサーバーを再起動します。

sudo systemctl restart apache2

ブラウザで、https://<サーバーアドレス> にアクセスすると、Redmineのページが表示されます。

CORSの構成

Cross-Origin Resource Sharing (CORS) は、ブラウザ内からRedmineのRest APIを呼び出す場合に必要になります。筆者の場合は、TrelloのPower-Up (プラグイン) を開発しており、CORS対応が必要となっています。通常のRedmineの使用では必要ありません。

CORSをサポートする方法には2つあります。

  • rack-corsの組み込み
  • ApacheによるHeaderとStatus Codeの書き換え

rack-corsの組み込み

前記事「備忘録: UbuntuにRedmine 4.2/5.0をインストールする (CORS対応) 」でも使用した方法です。PassengerはRack対応ということで、rack-corsとの組み合わせでCORS対応を実現できます。

参考資料: Rack CORS Middleware

Gemfile.localに追加でインストールしたいGemを登録します。

cd /opt/redmine
sudo vim Gemfile.local

次の1行を書き込みます。

gem 'rack-cors'

Gemをインストールします。

bundle install

Apacheサーバーを再起動します。

sudo systemctl restart apache2

ApacheによるHeaderとStatus Codeの書き換え

より一般的 (?) な方法として、ApacheにHeaderとStatus Codeを書き換えさせることができます。

CORSのための設定ファイルを作成します。

sudo vim /etc/apache2/conf-available/cors.conf

次の内容をコピーします。

<Location />
  <IfModule mod_headers.c>
    Header always set Access-Control-Allow-Origin "*"
    Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT, PATCH"
    Header always set Access-Control-Max-Age "7200"
    Header always set Access-Control-Allow-Headers "Content-Type, x-redmine-api-key"
  </IfModule>

  <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ $1 [R=200,L]
  </IfModule>
</Location>

最初のヘッダー書き換えは、Access-Control-Allow-Originなど、CORSで要求されるヘッダー情報をレスポンスに追加します。

2番目はOPTIONSに対するステータスコードを書き換えます。OPTIONSはCORSに付随してブラウザからサーバーに発行されるリクエストで、CORSをサポートするかどうか事前に問い合わせます。RedmineはOPTIONSに対しては404を返すので、それを200に書き換えて返しています。

設定を組み込み、Apacheサーバーを再起動します。

sudo a2enconf cors
sudo a2enmod rewrite
sudo systemctl restart apache2

変更履歴

日時内容
2022/06/25自己署名証明書の作成時に、秘密鍵を最初から暗号化せずに生成するように変更
2022/06/21自己署名証明書の作成ステップを修正
> chmod 400 server.key -> chmod 400 private.key
> 上記chmodを別ラインに分割 (直前のコマンドでPass Phraseの入力が正しく行われないため)
redmine.confの記述を修正
> /home/redmine/redmine -> /opt/redmine
rack-corsの設定について補足
2022/06/20秘密鍵を復号化するように変更
セキュリティ警告の回避方法について記載
2022/06/10CORSに関する記述にrack-corsを追加
2022/06/07初版リリース

コメント

タイトルとURLをコピーしました