業務上、非プログラマも混在したチームで新規プロジェクトの課題管理をする必要に迫られたので、EC2上にRedmineを建てた。
近年では他にも色々と選択肢はあるんじゃないの?という話もあるけども、どうしてもサーバにインストールするタイプのものが必要だったのでRedmineを選択した。それでも他に選択肢はあるだろうけど、選ぶ時間がもったいなかった😇
この記事の本題は、issue tracking system の製品選択の理由や経緯ではなく、「EC2上にRedmineを構築する」ときの作業手順等の記録である。
2015年に似た作業を実施していたが、その時は Amazon Linux 1 / Passenger / Apache という構成だった。
tmotooka.hatenablog.jp
2024年の現在では、取るべき構成や、ハマりポイントなどは大きく変わっているので、改めて記事にした。
想定読者
筆者自身のような人間、つまり以下の条件を全て満たす人が想定読者である。この条件に当てはまらない人にとっては説明不足だったり、「当たり前のことを言ってるだけ」になる可能性が高い。
構成の概要
全てAWS上のものである。
- LB : Application Load Balancer、ここでHTTPS終端する構成。
- EC2 : t4g.micro(構築作業中はt4g.small) で Ubuntu 22.04 を稼働しているマシン1台に、以下のものを詰め込んでいる構成。
RDSを使わない理由
- 前述のRPO要件から、multi-AZである必要が無いから
- 費用を抑えたかったから😅
事前準備
- AWSの基本的な設定(Organizationsの member account を作るとか、switch role のための設定とか、CloudTrailとか、billingの警告とか。詳細は割愛。)
- バックアップ用のS3バケットの作成
- EC2用の IAM Role の作成
- SessionManagerを使うので
AmazonSSMManagedInstanceCore
が必要 - CloudWatchにデータとかを送るので
CloudWatchAgentServerPolicy
が必要 - バックアップ用S3へのwrite権限が必要
- SessionManagerを使うので
- LoadBalancer用のSecurityGroupの作成
- 任意の場所からHTTP接続を受ける(もう不要かな?)
- 任意の場所からHTTPS接続を受ける
- 後述のEC2へのHTTP接続を出す
- EC2用のSecurityGroupの作成
- ACMでHTTPS証明書を作成
- LoadBalancerの作成
EC2の構築
bundle install
ではメモリを沢山食うらしく、t4g.micro だと処理が止まる。small以上である必要がある。構築後はmicroにしても良いけど、Redmineや ruby gems の更新が必要になるくらい長期の運用をするのなら、その時はsmallに戻すことになる。- 数年前に試したときの記憶だと確か、nano サイズだとそもそもMySQLも起動できなかったはず。
- 面倒なので、public subnetに配置して、IPアドレスを取得したw 他の業務のVPCの中に構築するのであれば、きちんとした設計(=private subnetに配置して、外向け通信は NAT instance とかを経由するやつ)にするのも良い。そうでなくても、お金に余裕があるのならそうした方が良い!
- Credit Specification はstandard にした。課金こわい。。
- sshのポートはSessionManager依存にするから開けないし、sshログイン用の鍵の設定もしない(非推奨だけど)
aptでインストールするもの
- nginx
- ruby ※バージョンにこだわりがある人は、ここでは入れずにrbenvとかを使うのだろう。
- ruby-bundler ※これが無いと「bundle」が使えない。rbenvとかで入れたら一緒に入るはずだけど。
- ruby-mysql2 ※これが無い時に何が起きるのかは試してない。
- ruby-dev ※これが無いと「bundle install」で落ちる。たぶん native extension のビルドで落ちる。
- build-essential ※これが無いと、bundle install の native extension のビルドで落ちる。
- libmysqlclient-dev ※これが無いと、bundle install のmysql2のビルドで落ちる(ということは、ruby-mysql2 のインストール物は使われていないかも?)
- mysql-server
- awscli ※バックアップをS3に置いたりしないのなら不要
Redmineのインストール
基本は、公式マニュアルに従う。
RedmineInstall - Redmine
以下の点は補足。
- Redmineのバージョン選択の情報は Download - Redmine を参照。本記事執筆時点での適切バージョンは 5.1.2 だった。
- アプリケーションをどこに置くべきか。諸説あるだろうが、ここでは
/var/www/redmine-5.1.2
とした。雑すぎるが、数ヶ月で廃止する鯖ならこれで十分。 - Step 4 のbundle操作の前に
echo "gem 'puma'" > Gemfile.local
して、pumaをインストールさせるべし。
Pumaのサービス起動
systemd環境下において、Pumaをサービスとして起動する方法は、公式のガイドがあるので、これを参考にして進めた。
github.com
要約すると、こうなる。
- Pumaのサービスの設定ファイルを作れ
- (今回のように UNIX Domain Socket を使う通信の場合)Socketの設定ファイルも作れ
- これらをsystemdに取り込んで有効化しろ
以下は補足。
- 数ヶ月で廃止する鯖とは言えども、Pumaの実行ユーザはrootじゃない方が良いので、「puma」というユーザを作った。
useradd --no-create-home --system puma
※他にも入れた方が良いオプションは色々あるだろうけど… - ソケットのファイルパスは、pumaユーザから書き込む(作る?)必要があるので、公式ガイドにある
/run/puma.sock
というのは不適切である。/run/puma/
というディレクトリを事前に作っておいて、ディレクトリの所有者をpumaユーザにした上で、ソケットのファイルパスを/run/puma/puma.sock
とした。 - サービス設定ファイルの
ExecStart
は、こうした:/usr/bin/bundle exec puma -e production -b unix:///run/puma/puma.sock
- TCPじゃなくてSocketを採用した理由:なんかカッコいいから😆
- 本稿から少し離れた話だが、↓の記事の話は面白かった
NginxからPumaに通信できるようにする
qiita.com
↑の記事の「nginxの設定」のコーナーに従えばすぐにできる。
以下は補足。
- UbuntuのaptでNginxをインストールした場合、80番ポートをlistenする設定が既に sites-enabled の中に(symlink)で存在してるので、新規に設定ファイルを作るのではなくて、これを編集する(または新規に作る+既存ファイルを消す)という方法で設定することになる。
- ここではALBでhttpsを終端化した構成なので、Nginxの立場では平文HTTPの通信を受け付ける構成である。
X-Forwarded-Proto
でpumaに渡す値は、$scheme
としてしまった場合、意図せず平文httpであることをpumaに通知してしまう。今の時代においては固定で「http」を渡すのが良いはずだ。 - Hostヘッダとかをpumaに渡す値を明示しない場合、どうやらNginx設定ファイルにおけるupstreamの名称がHostに設定されるらしく、Railsアプリがリダイレクトを返す時に、壊れたURLがユーザの元に届く😆
その他の設定
- ALB配下のWebサーバなので、お決まりの仕事として ELB経由のnginxでアクセス元IPアドレスをアクセスログの$remote_addrとして書くようにする #nginx - Qiita のように、Nginxのアクセスログの設定をするべきである。
- mysqldumpとかでダンプを作ってS3バケットにアップロードするbashスクリプトを書いて、cronとかで定期実行を仕込む。
- Redmineにアップロードされたファイルのバックアップは、公式のマニュアルを見ればファイルパスがわかるので、それをtarか何かで固めてS3に放り込む。 RedmineBackupRestore - Redmine
さいごに
久し振りにrubyを触って疲れた。(主に bundle install まわりで)