職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

EC2にRedmine(Apache|Passenger|HTTPS)

人に頼まれてRedmineをAWSのEC2上に構築することになった。この記事はその作業記録である。

要件

  • ランニングコストは最低限に抑えたい:業務時間中しか使わないし
  • オレオレ証明書で良いから、平文のHTTPは一切禁止、HTTPSのみでの運用にしたい
  • OSはAmazon Linuxがいい
  • ネットワーク的にはいろんな場所からアクセスする

らしい。

報酬

肉。心は踊るが財布は踊らない。

インフラの用意

ドメイン

既にRoute53で運用しているドメインが存在していたので、それのサブドメインを使った。
Aレコードを、後述のElasticIPのものに設定する。

EC2仮想マシン

運用はt2.microを使うのだが、メモリが1GBしかないときは後述のPassengerのビルド時に「メモリ足らねえぞゴルァ、swapの設定しやがれ」と怒られていろいろ面倒臭かった記憶があったので、そんなのは金で解決する。構築中はt2.smallインスタンスを使い、構築が終わったらt2.microに切り替える。
「業務時間中しか使わない」ということであったが、予算の都合でELB使えないし複雑なことはしたくない(報酬が少ない!)ので、EC2インスタンス起動する度にPublicIPアドレスをRoute53に登録するような構成は取らず、ElasticIPを使う。

やったこと

  • ElasticIP 1個取得
  • t2.small インスタンス
    • Amazon Linux
    • Security Groupは、sshを制限付きで許可、HTTPSをどこからでも許可、という感じのを用意。
    • IAM Role は、例えばバックアップをS3に置いたりってことが考えられるけど今はそこまで設計するの面倒くさいので、一応空っぽのものを付けとく。起動した後にRole設定することは非常に面倒臭いけど、既存のRoleに権限追加するのは簡単なので。
    • ストレージはデフォルトの8GBで構築。こういう小さい容量だとGP-SSDよりはMagneticの方が良い気がしてるのでMagneticで構築。(容量少ないときのGP-SSDのベンチ、誰か取ってないかなー?)
  • root ユーザになる: $ sudo su -
  • # yum update
  • /etc/sysconfig/network をいじってホスト名を設定
  • 気になるならOS再起動

MySQLの用意

MySQL 5.6 は、Amazon Linuxがデフォルトで提供しているリポジトリの中では最新版。世の中は5.7の話題で持ちきりだけど、ここは5.6を使う。(5.7は落とし穴も一杯あるし…)

# yum install mysql56-server

そして起動。

# service mysqld start

初回起動時はいろいろ設定するらしく、ログがたくさんでる。その中に「特権ユーザのパスワードを設定しろよ!」というメッセージが居るので見逃さずに設定する。

# /usr/libexec/mysql56/mysqladmin -u root password 'new-password'

Apacheの用意

# yum install httpd24 mod24_ssl
オレオレ証明書

という戦略を取る。完全に予算の都合である。

# cd /etc/httpd
# mkdir ssl
# cd ssl
# openssl genrsa 2048 > server.key
# openssl req -new -key server.key > server.csr
※ここで、署名要求に記載する事項の入力を対話型で求められる。CN(Common Name)は、事前に用意しておいたドメインを指すようにする。
# openssl x509 -days 36500 -req -signkey server.key < server.csr > server.crt
# chmod 400 server.key

最後の秘密鍵の権限設定は、気軽な鯖だったらやんなくても良いかという気がするが、手が勝手に打ち込む。

証明書の用意ができたら、Apacheにそれを食わせる。
秘密鍵の絶対パスは /etc/httpd/ssl/server.key になっていて、証明書の絶対パスは /etc/httpd/ssl/server.crt になっているはずなので、これらの情報を /etc/httpd/conf.d/ssl.conf に書き込む。このファイル内のどこに書いたら良いのかってのはこのファイルの中身を見ればわかるはずだ。

ここまでできれば、 # service httpd start でApacheを起動してHTTPSの動作確認ができるはずだ。

OS起動設定

OSが起動したときに、MySQLとApacheが起動するようにしておく。

# chkconfig --level 345 mysqld on
# chkconfig --level 345 httpd on

Redmineの用意

さて、ここからが本番である。基本的には公式のマニュアル http://www.redmine.org/projects/redmine/wiki/RedmineInstall に沿うことになる。
個人的にrubyを取り扱うときにいつも悩むのが、gemをどのユーザのところにインストールさせるのかというところ。今回はRedmineの専用鯖になるのでrootユーザに仕込もうかとも考えたが、マサカリが大量に飛んでくる可能性もある訳で、やはり redmine という名の専用のユーザを用意する。

以下、# はroot権限、$はredmine権限でのコマンド実行である。

ユーザの用意
# useradd redmine

以後の操作は基本的に redmine ユーザで実施する。 # su - redmine で成りきれる。

バージョンの選定と入手:公式マニュアルのStep1に相当

個人的なポリシーとして「構築時の最新の stable リリースのものを使う」ことにしている。この記事の執筆時点では Redmine 3.1.1 がそれに該当する。この記事の執筆時点でのAmazonLinuxデフォルトのRubyのバージョンは動作できる Ruby のバージョンは2.0.0であるが、これは Redmine 3.1.1が動作可能なバージョンであるようだ。このまま3.1.1使う。ダウンロードページ http://www.redmine.org/projects/redmine/wiki/Download から必要なアーカイブのリンクをコピって、wgetとかでダウンロード!

$ cd ~
$ wget http://www.redmine.org/releases/redmine-3.1.1.tar.gz
$ md5sum redmine-3.1.1.tar.gz
(一応確認しとく)
$ tar -zxf redmine-3.1.1.tar.gz

この結果、redmineユーザの ~/redmine-3.1.1 にディレクトリができてるので、そこに入っておく。

DBの用意:公式マニュアルのStep2に相当

面倒臭いから、MySQLのrootユーザで接続させる。だからユーザは作らない。

$ mysql -h localhost -u root -p

で接続して、

CREATE DATABASE redmine CHARACTER SET utf8;

でDB作成。終わったら quit

DB接続設定:公式マニュアルのStep3に相当

config/database.yml.example を config/database.yml にコピって使えと公式マニュアルが言っておられるので、素直にそれに従う。設定内容もマニュアルに従う。ここまで作ってきたDBの環境のことを思い出しながら。

必要なgemのインストール:公式マニュアルのStep4に相当

どうやら、これらのコマンドを実行するときの作業ディレクトリは大事であるようだ。Gemfileが見えている場所でってのが大事なんだろう、きっと。

$ gem install bundler
$ bundle install --without development test

この2個目の bundle コマンドを動かすと「◯◯がありません」みたいなエラーが出て止まる。Redmineインストールの難関その1である。
エラーメッセージに従って必要なものをインストールする。ここで何が必要なのか?を調べるのが、Redmine(というかruby)のツラいところだと思ってる。まあruby初心者の戯言ではあるが。

# yum install ruby-devel rubygem20-io-console gcc zlib zlib-devel patch mysql56-devel ImageMagick ImageMagick-devel

このyumのあと、また redmine ユーザに戻って、ディレクトリを間違えずに bundle install すれば良い。

パスワード生成:公式マニュアルのStep5に相当

Redmineのバージョンによって流すべきコマンドが異なる。1.4.x と 2.x には案内があるが、3.x の案内は無い。ここでは 2.x のガイドに従う。

$ bundle exec rake generate_secret_token
テーブル構築:公式マニュアルのStep6に相当

これで一発。前述のDB接続設定をミスってると死ぬ。

$ RAILS_ENV=production bundle exec rake db:migrate
初期値投入:公式マニュアルのStep7に相当

テーブル構築が成功してたらうまく行く。

$ RAILS_ENV=production bundle exec rake redmine:load_default_data

どの言語?って聞かれるので、英語がよければそのままreturn, 日本語が良ければ ja 指定だ。

ファイル権限設定:公式マニュアルのStep8に相当

ここで語ることは何もない。公式マニュアル通り。

chmod 777 files
chmod 777 log
chmod 777 tmp
chmod 777 tmp/pdf
chmod 777 public/plugin_assets

で終わりと行きたいところであるが、ここまでの手順に沿うと redmine ユーザのホームディレクトリ内に置いてあるredmineのファイル群にApacheのプロセスが辿り着けない。もういっちょ chmod 755 ~ を流す必要が有る。
※本当なら /var/ の下だったり /usr/local/ の下だったりに置くのが理想的なんだろう。でも専用鯖なので大目に見る。

Webrickでの動作確認:公式マニュアルのStep9に相当

SecurityGroupでHTTPのポート開けるの面倒臭いし、パス。初期パスワードをインターネット上に平文で流すのも嫌だし。


Passengerの用意

まずはgemのインストール。

$ gem install passenger

これはすんなり行く。
次に、Apacheモジュールのインストール。

$ passenger-install-apache2-module

で、また足りないものをインストールする必要に迫られる。

# yum install gcc-c++ libcurl-devel httpd24-devel apr-devel apr-util-devel

再度モジュールのインストールを試みると、ビルドが始まる。メモリ足らないマシン使ってるとここで怒られる。
数分待つと、Apacheの設定ファイル書き換えろよっていうメッセージが出てくるので、それに従う。これがちょっと面倒で、もう一つのセッションでsshつなぐ必要がある。接続できたらroot権限で /etc/httpd/conf.d/ に redmine.conf とか言って書き込む。別セッションの方はこれで任務完了であるが、接続を残しておくのも良い。

DocumentRoot の設定

もしもRedmineのインストールディレクトリが /home/redmine/redmine-3.1.1/ であるならば、設定すべきDocumentRootは /home/redmine/redmine-3.1.1/public になる。
これはApacheの設定ファイル /etc/httpd/conf/httpd.conf に直接書き込む。一緒にディレクトリの設定もしてしまう。

DocumentRoot "/home/redmine/redmine-3.1.1/public"
<Directory "/home/redmine/redmine-3.1.1/public">
        AllowOverride None
        Require all granted
</Directory>

ここまでできたら、 # service httpd restart すればRedmineを使えるようになっているはずだ。初期パスワードなどは公式のマニュアルに書いているので、あとは好きにしたら良いだろう。

定期的バックアップは、また暇なときにやる(たぶん記事にはしない)。設定したIAM Roleがきっと役に立つはずだ。

インスタンスタイプ

もともとt2.smallを使ってた理由はPassengerのApacheモジュールのビルドにメモリが必要だったから、である。稼動確認できたらもうt2.smallである必要はなくて、t2.microに切り替えて良い。