目次
はじめに
改訂された新しい記事があります!!
以前の投稿でUbutntuにRedmine 5.1をインストールする手順について紹介しました。その続きとして、WebサーバーにApacheを使い、自己署名証明書 (いわゆるオレオレ証明書) を使ってHTTPS化したので、その手順を紹介します。CORS対応についても説明しています。
2023/04/11
Ubuntu 22.04.2 LTS Amd64で、Phusion Passengerのプロセスがスタートしない、というエラーを確認しました。この解決方法 (と思われるもの) について追記しています。Arm64版では発生せず確認が遅れました。このエラーで悩まれた方は申し訳ありません。
前記事
TrelloとRedmineを比較している方、Redmineの展開に悩んでいる方、ぜひご一読を!
環境
ソフトウェアのバージョンは次の通りです。
- OS: Ubuntu Server 22.04 LTS
- Redmine: 5.1
- 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 apache2-dev
ブラウザで、http://<サーバーアドレス> にアクセスすると、デフォルトのページが表示されます。
ApacheのHTTPS化
参考資料:
1) How to enable HTTPS protocol with Apache 2 on Ubuntu 20.04
2) OPENSSL COOKBOOK by Ivan Ristic
(2023/04/08 参考資料を変更しopensslの使い方も更新しました)
本稿では自己署名証明書を使ってHTTPS化していますが、プライベート認証局を構築してHTTPS化する方法もあります。
自己署名証明書の作成
秘密鍵 (private.key) と署名リクエスト (request.csr) を作成します。秘密鍵は暗号化せずに作成しています。暗号化していると、Apacheを起動するサービス中でPass Phraseの入力を求められ、エラーとなるためです。
cd ~
openssl genpkey -out private.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
openssl req -new -key private.key -out request.csr
作成中、次のような質問が表示されるので、適宜指定してください。
Country Name (2 letter code) [AU]: JP
State or Province Name (full name) [Some-State]: Tokyo
Locality Name (e.g. city) []: Chiyoda
Organization Name (eg. company) [Internet Widgits Pty Ltd]: Hoge LLC
Organiztion Unit Name (eg. section) []: Home
Common Name (e.g. server FQDN or YOUR name) []: example.com
必須項目は、Country Name, Organization Name, Common Nameです。
Common Name (CN) は、Webブラウザに入力されたアドレスと比較されます。WebサーバーがFQDN (Fully Qualified Domain Name) を持っている場合は、それを指定します。IPアドレスしか持たない場合は、IPアドレスを指定します。
ブラウザによっては、CNではなく、SAN (Subject Alt Name) を参照するため、本来はSANの指定も必要です。ただそもそも自己署名証明書として例外を承認することで、SANは無視されるので、ここではSANの指定は省略しています。
証明書 (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
次の内容をコピーします。(筆者は不勉強のため解説不能 … 参考資料1) からのコピーです)
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
SSLUseStampling, SSLStamplingCacheをコメントアウトしています。これらは、証明書の失効に関する設定です。外部の認証局によって認証された証明書の場合、その認証局に証明書が失効していないか問い合わせます。そのための設定になります。自己署名証明書の場合は、失効は自ら証明書を削除または置き換えますから、この設定は無用です。(あっても問題無いようですが、Apacheのログにエラーが出ます)
署名証明書を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のような無料のサービスもありますし)。
イントラネットの場合は、イントラネット内にプラベート認証局を立てて、その認証局で署名した証明書を使うことで警告を回避できます (筆者もこの方法を使っています)。
更に簡便に済ますなら、作成したオレオレ証明書 (certificate.crt) を、ルート証明書としてブラウザにインポートすることで、警告を消すことができます。ただしこの方法は、サーバーを追加すると、その度に証明書をブラウザに追加する必要があります。 またブラウザによっては、ルート証明書としてインポートできません。
別の方法として、もしドメインを所有しDNSの設定ができるのであれば、イントラネットであってもLet’s Encryptを利用できます。
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
検査対象を選択するように求められるので、Passenger, Apacheの両方を選択します。
What would you like to validate?
Use <space> to select.
If the menu doesn't display correctly, press '!'
⬢ Passenger itself
‣ ⬢ Apache
この結果、次のメッセージが表示されます。
* Checking whether this Passenger install is in PATH... ✓
* Checking whether there are no other Passenger installations... ✓
* Checking whether Apache is installed... ✓
Everything looks good. :-)
Passengerのプロセスが起動していることを確認します。
sudo /usr/sbin/passenger-memory-stats
次のようにPassengerのプロセスが起動していることを確認します。
----- Passenger processes ------
PID VMSize Private Name
--------------------------------
271481 294.7 MB 2.3 MB Passenger watchdog
271484 849.9 MB 4.1 MB Passenger core
### Processes: 2
### Total private dirty RSS: 6.39 MB
Ubuntu 22.04.2 LTS Amd64で構築したところ、上記でPassengerのプロセスが起動しない状況になりました。Apacheのエラーログ (/var/log/apache2/error.log) を見てみると、次のようなエラーメッセージが記録されていました。
PassengerAgent: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory
[Tue Apr 11 11:51:20.032520 2023] [passenger:error] [pid 820:tid 140061081606016] *** Passenger could not be initialized because of this error: Unable to start the Phusion Passenger(R) watchdog: it seems to have crashed during startup for an unknown reason, with exit code 127
Stackoverflowの記事を参考に以下を試してみました。
wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.17_amd64.deb
sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.17_amd64.deb
筆者の環境ではこれで解決しました。ただし他に副作用がないか十分な確認はできていません。(packageの中身をみると、openssl1.1向けのモジュールを追加するだけで、何かを上書きしたりはしないようです …)
ldconfig で確認すると下記のようにlibcrypto.so.1.1が追加でロードされていました。
libcrypto.so.3 (libc6,x86-64) => /lib/x86_64-linux-gnu/libcrypto.so.3
libcrypto.so.1.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libcrypto.so.1.1
libcrypto.so (libc6,x86-64) => /lib/x86_64-linux-gnu/libcrypto.so
Ubuntu 22.04.2 LTS Arm64 (Apple M2) で構築した場合は、このようなエラーは発生しませんでした。またldconfigで確認したところ、libcrypto.so.1.1はロードされていませんでした。
Phusion Passengerのビルドの違いで、libcrypto.so.1.1を要求するかしないかの違いがあるのかも知れません (筆者には判断不能 …)。
しかしもしAmd64とArm64で違いがあるとすると、今後の確認作業が2倍になるので、どうしたものかと …
Passengerのインストール方法には、RubyのGemとしてインストールする方法もあります。ネット上の記事ではこちらの方法を取っているものが多いようです。
Passengerの構成
PassengerでRedmineを呼び出すように構成ファイルを作成します。
sudo vim /etc/apache2/conf-available/redmine.conf
次の内容をコピーします。ServerNameは、自己署名証明書を作成した時に指定したもので置き換えます。
ServerName example.com
<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の組み込み
前記事で使用した方法です。PassengerはRack対応ということで、rack-corsとの組み合わせでCORS対応を実現できます。
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
変更履歴
日時 | 内容 |
2023/04/11 | 22.04.2 LTS Amd64 でPassengerのプロセスが起動しない問題について記述 |
2023/04/08 | 自己署名証明書の作成コマンドを変更 (OPENSSL COOKBOOKに準拠) Apacheのインストール時に、apache2-devをインストールするように変更 |
2023/03/27 | 自己署名証明書の作成時に指定する Common Name について説明を追加 |
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/10 | CORSに関する記述にrack-corsを追加 |
2022/06/07 | 初版リリース |