VagrantとVirtualBoxでCentOSにnginxとpumaのRails環境を構築する

VagrantとVirtualBoxを使ってrailsの開発環境を構築しました。データベースはPostgreSQLを選択しています。普段はDockerを推していますが、今回は久しぶりにVagrantでのrailsで、しかもnginxとpumaのunix-socket接続に大分手間取りました。ansibleを使った構成管理をしようかとも思ったんですが、Dockerを勉強するのと同じくらい大変そうに感じたので、構成管理ツールは引き続きDockerに絞って行っていこうと思います。

### バージョン情報
- [Mac OS](https://ninolog.com/about-my-mac/) 10.11.6（El Capitan）
- Vagrant 2.1.1 [ダウンロード](https://www.vagrantup.com/intro/index.html)
    - plugins
        - vagrant-vbguest (0.15.2)
- Virtualbox 5.2.12 [ダウンロード](https://www.virtualbox.org/wiki/Downloads)
- CentOS 7
  - rbenv 1.1.1-37-g1c772d5
    - ruby 2.5.1p57
  - nginx version: nginx/1.15.0
  - psql (PostgreSQL) 11beta1
- rails 5.2.0

#### その他情報
- github:[2no553/rails\-vagrant](https://github.com/2no553/rails-vagrant)
- blog:[VagrantとVirtualBoxでCentOSにnginxとpumaのRails環境を構築する – Ninolog](https://ninolog.com/set-rails-virtualbox-vagrant-with-puma-nginx/)

### vagrant設定
vagrant設定をしていきます。[ config.vm.synced_folder ]の[ type: ]は適切なものを指定しないと、共有マウントがうまくいかない場合がありました。

```
#VagrantとVirtualboxのインストール（バージョン情報の各[ ダウンロード ]リンクからもインストールできます）
$ brew cask install vagrant virtualbox
$ brew cask list

#centos/7のboxを使用して初期化
$ vagrant init centos/7

#プラグインインストール
$ vagrant plugin install vagrant-vbguest

#Vagrantfile修正
$ vi Vagrantfile  

- # config.vm.network "forwarded_port", guest: 80, host: 8080
- # config.vm.network "private_network", ip: "192.168.33.10"
- # config.vm.synced_folder "../data", "/vagrant_data"
+ config.vm.network "forwarded_port", guest: 3000, host: 3000
+ config.vm.network "private_network", ip: "192.168.33.10"
+ config.vm.synced_folder ".", "/vagrant", type: "virtualbox"

#vagrant起動
$ vagrant up
```

### centos設定
centos設定をしていきます。[ SELINUX無効化 ]を忘れると、後にpumaが起動しない原因になるので注意してください。[ centos7 ]では、日本語ロケールがなくて日本語の表示文字化けする場合がありますので、[ glibc-common ]を再インストールすれば解消されます。

```
#ssh接続
$ vagrant ssh

#パッケージアップデート
$ sudo yum update -y

#SELINUX無効化(Disabled)
$ sudo sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
$ sudo reboot
$ vagrant reload
$ vagrant ssh
$ getenforce

#タイムゾーンを[ Asia/Tokyo ]に変更
$ sudo timedatectl set-timezone Asia/Tokyo
$ timedatectl status

#日本語ロケール追加
$ sudo yum reinstall -y glibc-common
$ localectl list-locales

#日本語ロケール・キーマップ設定
$ sudo localectl set-locale LANG=ja_JP.utf8
$ sudo localectl set-keymap jp106
$ localectl status

#日本語フォント インストール（必要に応じて）
$ sudo yum install ibus-kkc vlgothic-*
```

### railsインストール
railsインストールをしていきます。gitを利用したインストール方法になります。[ rbenv install ]はかなり時間がかかりますので気長にいきましょう。

```
#パッケケージインストール
$ sudo yum install git gcc-c++ openssl-devel readline-devel zlib-devel -y

#rbenvインストール
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ cd ~/.rbenv && src/configure && make -C src

#path設定
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ rbenv --version

#ruby-buildインストール
$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
$ cd "$(rbenv root)"/plugins/ruby-build && git pull

#rubyインストール
$ rbenv install -l
$ rbenv install 2.5.1
$ rbenv global 2.5.1
$ rbenv rehash
$ ruby -v
$ rbenv versions
$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash

#bundlerインストール
$ gem install bundler

#railsインストール
$ gem install rails
$ rails -v
```

### nginxインストール
nginxインストールをしていきます。自動起動設定後は[ Vagrantfile ]の[ config.vm.network "private_network" ]で指定したipでスタートページが表示できます。

```
#リポジトリ追加
$ sudo vi /etc/yum.repos.d/nginx.repo
+ [nginx]
+ name=nginx repo
+ baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
+ gpgcheck=0
+ enabled=1

#インストール
$ sudo yum info nginx
$ sudo yum install nginx -y
$ nginx -v

#自動起動設定
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
$ sudo systemctl status nginx

#スタートページ表示
http://192.168.33.10/
```

### postgresqlインストール
postgresqlインストールをしていきます。Baseリポジトリでは[ exclude=postgresql* ]をして無効化してあります。

> checking for pg_config... no
> No pg_config... trying anyway. If building fails,
> please try again with
>  --with-pg-config=/path/to/pg_config
> checking for libpq-fe.h... no
> Can't find the 'libpq-fe.h header

pg gemインストールをした際に、上記のエラーが表示されたら、[ pg_config ]を指定して再度gemインストールを行ってください。

```
#リポジトリ追加
$ sudo vi /etc/yum.repos.d/CentOS-Base.repo
  [base]
  name=CentOS-$releasever - Base
  mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
  #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
  gpgcheck=1
  gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
+ exclude=postgresql*

#postgresqlインストール
$ sudo yum localinstall https://download.postgresql.org/pub/repos/yum/testing/11/redhat/rhel-7-x86_64/pgdg-centos11-11-1.noarch.rpm -y
$ sudo yum info postgresql-server
$ sudo yum install postgresql-server -y
$ sudo yum install postgresql-devel -y
$ psql --version

#postgresql初期化
$ sudo /usr/pgsql-11/bin/postgresql-11-setup initdb

#自動起動設定
$ sudo systemctl start postgresql-11
$ sudo systemctl enable postgresql-11
$ sudo systemctl status postgresql-11

#パスワード変更
$ sudo -u postgres psql -U postgres
postgres=# \q
$ sudo passwd postgres

#vagrantユーザー作成
$ su - postgres
-bash-4.2$ createuser vagrant -s
-bash-4.2$ exit

#pg gemインストール
$ ls -l /usr/pgsql-11/bin/pg*
$ gem install pg -- --with-pg-config=/usr/pgsql-11/bin/pg_config
$ cd /vagrant
$ rails new app-name --force --database=postgresql
```

### rails起動
rails起動をしていきます。

> rake aborted!
> Bundler::GemRequireError: There was an error while trying to load the gem 'uglifier'.
> Gem Load Error is: Could not find a JavaScript runtime. See ?
> https://github.com/rails/execjs for a list of available runtimes.

db作成した際に、上記のエラーが表示されたら[ Gemfile ]の[ mini_racer ]を有効化して再度[ bundle install ]して下さい。

```
$ cd app-name
$ bundle install
$ bundle exec spring binstub --all

#gem有効化
$ vi Gemfile
- # gem 'mini_racer', platforms: :ruby
+ gem 'mini_racer', platforms: :ruby

$ bundle install

#db作成
$ rake db:create

#rails起動
$ rails s

#スタートページ表示
http://192.168.33.10:3000/
```

### migrationテスト
migrationテストをしていきます。

```
$ rails generate model Article title:string text:text
$ rake db:migrate:status
```

### puma-nginxをunix-socket接続
puma-nginxをunix-socket接続していきます。ここでうまくunix-socket接続ができず、大分手間取ってしまいました。

#### puma設定
puma設定をしていきます。実際に使ったことがないため何とも言いがたいのですが、[参考サイト](https://gist.github.com/duleorlovic/762c4ffdf43c8eb31aa7)を見た時に実行権限の都合上vagrantディレクトリの外にシェアディレクトリを作成したほうが良いとあったのでそうしています。シェアディレクトリは自動では生成されないようなので手動で作成します。

> bundler: failed to load command: puma (/home/vagrant/.rbenv/versions/2.5.1/bin/puma)
> Errno::EACCES: Permission denied - connect(2) for /puma_shared/sockets/puma.sock

```
$ ls -la
drwxr-xr-x    3 root    root      21  6月 28 02:19 puma_shared
$ sudo chown -R $USER:$USER puma_shared
$ ls -la
drwxr-xr-x    3 vagrant vagrant   21  6月 28 02:19 puma_shared
```

pumaを起動した際、上記のエラーが出た時は、シェアディレクトリの権限を[ ls -la ]コマンドなので確認して下さい。もし権限がrootになっていたらvagrantに変更して、再度[ bundle exec puma ]を実行して下さい。

```
#シェアディレクトリ作成
$ mkdir -p puma_shared/sockets

#puma設定
$ vi config/puma.rb
+ shared_dir = "/puma_shared"
+ # Set up socket location
+ bind "unix://#{shared_dir}/sockets/puma.sock"

$ sudo mv puma_shared /
$ cd /vagrant/app-name

#puma起動
$ bundle exec puma
Ctrl-C
```

#### nginx設定
nginx設定をしていきます。[ server unix: ]は[ puma.rb ]の[ bind "unix://#{shared_dir}/sockets/puma.sock" ]と同じpathを設定して下さい。[ server_name ]は[ Vagrantfile ]の[ config.vm.network "private_network" ]で指定したipを設定して下さい。

```
#nginx設定
$ vi app-name.conf
+ upstream app-name {
+     server unix:///puma_shared/sockets/puma.sock;
+ }
+ server {
+     listen       80;
+     server_name  192.168.33.10;
+     location / {
+         proxy_pass http://app-name;
+     }
+ }

$ sudo mv app-name.conf /etc/nginx/conf.d/
$ cd /etc/nginx/conf.d/

#構文テスト
$ sudo nginx -t

#再起動
$ sudo systemctl restart nginx
```

#### puma-nginxをunix-socket接続起動
puma-nginxをunix-socket接続起動をしていきます。うまく接続されていればnginxのスタートページを表示した[ http://192.168.33.10/ ]でrailsのスタートページが表示されるようになっています。

```
$ cd /vagrant/app-name

#puma起動
$ bundle exec puma

#スタートページ表示
http://192.168.33.10/
```

今回はあくまでpuma-nginxをunix-socket接続起動できている状態を確認することを最優先にして[ puma.rb ]や[ app-name.conf（nginxの設定のため作成したファイル） ]は最低限の内容にしています。下記の参考サイトなど見て、必要に応じて調整していってもらえればと思います。

##### 参考サイト
- [puma/config\.rb at e0f544d0ec5769c05e439ba251b5685cb546fed5 · puma/puma](https://github.com/puma/puma/blob/e0f544d0ec5769c05e439ba251b5685cb546fed5/examples/config.rb)
- [puma/nginx\.md at master · puma/puma](https://github.com/puma/puma/blob/master/docs/nginx.md)
- [an example of puma and ngxin with ruby on rails config\.md](https://gist.github.com/duleorlovic/762c4ffdf43c8eb31aa7)
- [Rails \+ Puma \+ Nginx on CentOS 7 の 環境構築メモ \- 適当おじさんの適当ブログ](http://www.subarunari.com/entry/2018/04/04/Rails_%2B_Puma_%2B_Nginx_on_CentOS_7_%E3%81%AE_%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E3%83%A1%E3%83%A2)
- [RackサーバーのPumaについて調べてみる \- ゆーじのろぐ](http://arakaji.hatenablog.com/entry/2015/08/03/200502)
- [rails5\+puma\+nginxで本番環境を構築してみる – 不動産屋のエンジニア](https://www.gakusmemo.com/?p=608)