はじめてのCentOS7でRubyOnRails×PostgreSQL環境をつくる

日々インフラ屋さんの自分もコーディング能力が必要になってきたなと思っていたので、
Rubyの勉強がてらちょっとしたWEBサービスを作ろうかなと思い立ちました。
ついでなので、身の周りの評判の悪さから毛嫌いしていたRedhat7.x系で作ろうと思います。

# まずは開発環境を準備
我が家には非力なマシンしかないので、流行りの安上がりなIaaSサービスを使うことに。
月額500円でミニマムな環境＋LB＋帯域2GBps使えるIDFCに決定。
参考：[【クラウドサーバーサービス(IaaS)比較まとめ】](http://matome.naver.jp/odai/2141128309524837601)

IDCFクラウド申し込みの際、
Chromeブラウザだと決定ボタンが押せない等あり、IEブラウザで決定ボタンだけ押すなどやりました。
推奨ブラウザchrome入ってるのに。申し込み終了後の管理画面では不具合ないのですが。
初期登録・設定自体は特に詰まることなくサクサク完了。
参考：[新しいIDCFクラウドを使ってみた](http://tech.raksul.com/2014/10/15/idcf_cloud/)

**マシンスペック**
* CPU: 1core
* メモリ: 1GB
* ディスク: 15GB
* OS: CentOS 7.1

# 環境をセットアップする
今回CentOS7に導入するパッケージは下記となります。

* PostgreSQL
* ruby
* rails
* railsからpostgreSQLを使うための何か

## CentOSを設定する
### 【ネットワーク】
ネットワーク設定はIDCFクラウドによって、自動的に設定されているので実施することはありません。
iptables・・・ではなくFirewalldも、IDCFクラウドのFW設定に頼って未設定としました。

CentOS7から`ifconfig`や`netstat`が廃止されたと聞いていましたが、
IDCFで配布されているCentOS7.1にはパッケージが最初から入っており、すべて使えました。

CentOS7からは、ネットワークの設定はNetworkManager経由で実施する必要があり、`nmcli`か`nmtui`を使う必要があります。
また、`ethx`(イーサx)の愛称？で知られるデバイス名も、長ったらしい`enxxxxxx`系に置き換わり、設定しにくくなった感覚です。
デバイス名も覚えてられないので、手動でやるならnmtuiのが直感的でイイですね。

慣れない上記の変更点ですが、どうやらGrubオプションから戻せたりするみたいです。(非推奨とのことですが)
参考：[CentOS7でネットワークインターフェース名をethXに戻す方法](http://e-trees.jp/index.php/dev-blog/20140723blog01/)
参考：[CentOS 7 ネットワーク設定](http://server.etutsplus.com/centos-7-network-configuration/)

### 【時刻設定】
IDCFさんが自動で設定してくれていました。
なお、CentOS7から`ntpd`から`chronyd`に置き換わっており、そちらで設定されてました。
`ntpd`パッケージも入っていませんでした。

置き換わったことを知らずに「ntpd入ってないじゃーん」ってノリで入れたら、
時刻同期で競合発生しておかしくなりそうだなと思ったら、
unitの依存関係でしっかりConflictsになっていて、ntpdがafterに入ってました。
両方入っていた場合はntpd->chronydの順番に起動されるので、
Conflict条件でchronydが後勝ちでntpdを殺して上がることになりそうですね。
今回はとりあえずそのままchronydで。

```shell-session
# cat /usr/lib/systemd/system/chronyd.service
[Unit]
Description=NTP client/server
After=ntpdate.service sntp.service ntpd.service
Conflicts=ntpd.service
・・・
```

## PostgreSQLを導入・設定する
バージョンは安定版の最新である`9.4`を採用しました。

### インストール編
インストール作業については、特に言及することもない

```shell-session
# wget http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-2.noarch.rpm
# rpm -ivh pgdg-centos94-9.4-2.noarch.rpm
# yum list postgresql94*
# yum install postgresql94.x86_64 postgresql94-devel.x86_64 postgresql94-libs.x86_64 postgresql94-server.x86_64
```

導入後にsystemdにちゃんと登録されているか確認

```shell-session
# systemctl list-unit-files | grep postgres
postgresql-9.4.service                      disabled
```

さすがにRPM導入だと自動的にサービス登録されるみたいですが、makeで入れる場合は自分でサービス登録が必須ですね。
この場合は、`/usr/lib/systemd/system/`配下にunit定義を追加するのではなく、
`/etc/systemd/system/`の下にunit定義を追加するのが正しいみたいです。
参考：[「Systemd」を理解する ーシステム起動編ー](http://equj65.net/tech/systemd-boot/)

### 設定編
#### 【DB作成】
psqlユーザでinitdbしようと思ったらパスが通ってなかったのでフルパスで実施する必要あり。
咄嗟にパスが見つからず、検索してこんなパスだったっけ？と思いつつ実行。
databaseの置き場をオプションで変えてみました。

```shell-session
# mkdir -p /database/data
# chwon -R postgres:postgres /database/data
# su - postgres
$ /usr/pgsql-9.4/bin/initdb --encoding=UTF8 --no-locale --pgdata=/database/data
```
#### 【自動起動設定】
chkconfigがなくなったので、systemctlコマンドで設定。

```shell-session
# systemctl enabled postgresql-9.4
Job for postgresql-9.4.service failed. See 'systemctl status postgresql-9.4.service' and 'journalctl -xn' for details.
```

すごい余談ですが、initのランレベルについて考慮はされていて、下記にtarget unitが用意されてました。
unitは慣れると依存関係が直感的でわかりやすくていいですね。

```shell-session
# ls -l /usr/lib/systemd/system/runlevel*.target
lrwxrwxrwx. 1 root root 15  9月 16 15:55 /usr/lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx. 1 root root 13  9月 16 15:55 /usr/lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx. 1 root root 17  9月 16 15:55 /usr/lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root 17  9月 16 15:55 /usr/lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root 17  9月 16 15:55 /usr/lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx. 1 root root 16  9月 16 15:55 /usr/lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx. 1 root root 13  9月 16 15:55 /usr/lib/systemd/system/runlevel6.target -> reboot.target

# cat /usr/lib/systemd/system/runlevel1.target
[Unit]
Description=Rescue Mode
Documentation=man:systemd.special(7)
Requires=sysinit.target rescue.service
After=sysinit.target rescue.service
AllowIsolate=yes

[Install]
Alias=kbrequest.target
```

#### 【PGDATA環境変数を再設定】
特に言及することなし

```shell-session
# su - postgres
# vi .bash_profile
  #PGDATA=/var/lib/pgsql/9.4/data  ←コメントアウト
  PGDATA=/database/data
```

#### いざ起動
エラーが発生。

```shell-session
# systemctl start postgresql-9.4
Job for postgresql-9.4.service failed. See 'systemctl status postgresql-9.4.service' and 'journalctl -xn' for details.
```

ここでsyslogに置き換わろうとしているjournalctlの便利さを実感しました。
PostgreSQL関連のログだけをオプションでgrepでき、保存形式がbinaryだから速度も早いらしい。
ログを見ると環境変数で変えたはずの`PGDATA`の値がまだ`/var/lib/pgsql/9.4/data`になってますね。

```shell-session
# journalctl -u postgresql-9.4
12月 06 19:36:25 TEST.cs1373idcfcloud.internal systemd[1]: Starting PostgreSQL 9.4 database server...
12月 06 19:36:25 TEST.cs1373idcfcloud.internal postgresql94-check-db-dir[25038]: "/var/lib/pgsql/9.4/data/" is missing or empty.
12月 06 19:36:25 TEST.cs1373idcfcloud.internal postgresql94-check-db-dir[25038]: Use "/usr/pgsql-9.4/bin/postgresql94-setup initdb" to initialize the database
12月 06 19:36:25 TEST.cs1373idcfcloud.internal postgresql94-check-db-dir[25038]: See %{_pkgdocdir}/README.rpm-dist for more information.
12月 06 19:36:25 TEST.cs1373idcfcloud.internal systemd[1]: postgresql-9.4.service: control process exited, code=exited status=1
12月 06 19:36:25 TEST.cs1373idcfcloud.internal systemd[1]: Failed to start PostgreSQL 9.4 database server.
12月 06 19:36:25 TEST.cs1373idcfcloud.internal systemd[1]: Unit postgresql-9.4.service entered failed state.
```

initスクリプトはなくなったので、設定しているとすればunit設定だと覗いてみたら直に書いてありました。
unit設定を書き換えてみます。

```shell-session
# cp -p /usr/lib/systemd/system/postgresql-9.4.service /etc/systemd/system/postgresql-9.4.service
# vi /etc/systemd/system/postgresql-9.4.service
・・・
#Environment=PGDATA=/var/lib/pgsql/9.4/data/  ←
Environment=PGDATA=/database/data/
・・・
```

書き換えて実行してみるも、同じエラー発生。
調べてみると、unitファイルを更新した場合は再読み込み的なことが必要になるとのこと。
下記実行して、問題なく稼働しました。

```shell-session
# systemctl --system daemon-reload
# systemctl start postgresql-9.4
```

## 最新RubyとRailsを導入する
デフォルトで`ruby-2.0.0.598-25.el7_1.x86_64`が入っていました。
このままでもイイかなと思いましたが、せっかくなので最新版を`rbenv`を使って導入。

ググった結果そのままなので特に言及するところなし。
nokogiriは入れるのに毎回つっかかりますね。

```shell-session
# git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
# echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# type rbenv
# git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
# exec $SHELL -l
# rbenv install 2.2.3
# rbenv rehash
# rbenv global 2.2.3
# yum install gcc-c++
# gem install nokogiri -- --use-system-libraries
# gem install rails
```

## RailsからPostgreSQLを使う
ちょっとハマりました。
`pg`というgemを入れるだけだったのですが、入れる際にpostgreSQLのファイルを指定する必要がありました。
また、gemが入っても最新版だとRails実行時にエラーがでてしまい、バージョンを下げて入れました。

```
# gem install pg
        ERROR: Failed to build gem native extension.

    /root/.rbenv/versions/2.2.3/bin/ruby -r ./siteconf20151207-14677-1chd1c0.rb extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config

# gem install pg -- --with-pg-config=/usr/pgsql-9.4/bin/pg_config
# rails s
/Users//Projects/The /vendor/bundle/gems/pg-0.14.1/lib/pg.rb:4:in require': cannot load such file -- pg_ext (LoadError)
・・・・
# gem uninstall pg
# gem install pg -v 0.17.1-- --with-pg-config=/usr/pgsql-9.4/bin/pg_config
```

参考：[PG pg_ext load error in rails](http://stackoverflow.com/questions/26617779/pg-pg-ext-load-error-in-rails) ※英語です

---
以上です。

結局Railsを触る手前で時間を費やしてしまいましたが、CentOS7の勉強にはなりました。
Systemdは結構良いなと思いましたが、NetworkManagerはメリットを感じるところまで至りませんでした。
色々と調べた際に参考になったサイトを紹介します。

# 参考にさせて頂いたページ
[CentOS6とCentOS7の比較表](http://qiita.com/sion_cojp/items/115e1671fcbc8f214aee)
[「Systemd」を理解する ーシステム起動編ー](http://equj65.net/tech/systemd-boot/)
[なぜsystemdなのか？](http://postd.cc/why-systemd/)
[systemdを本番運用してわかったこと](http://alpha.mixi.co.jp/entry/2013/12063/)
[RHEL7/CentOS7のjournaldについてのもろもろ](http://enakai00.hatenablog.com/entry/20141130/1417310904)
[CentOS 7 ネットワーク設定](http://server.etutsplus.com/centos-7-network-configuration/)

---