前提
とある事情でCentOS6.8上でRailsアプリを動かすことになったので、その時のメモです。
セキュリティについてはあまり考慮していません。具体的にはSE LinuxはOffにし、Apache httpdも全てに対してアクセス許可をしています。
各種バージョン
- OSはCentOS 6.8 64bit版
- Apache httpdは
yum install httpd
で入れたバージョンである2.2です。 - Rubyは2.3.3
- Railsは4.2.8
手順
OSの環境構築
railsapp
グループを作成します。
$ sudo groupadd railsapp
既存のユーザをrailsapp
グループに属すようにします。例えば、dev1
ユーザをrailsapp
グループに属すようにするには次のようにします。
$ sudo usermod -aG railsapp dev1
EPELのリポジトリをインストールします。
$ sudo yum -y install epel-release
Rubyのインストールに必要な各種ライブラリをインストールします。この情報は、rbenvのpluginであるruby-buildのページに記載があります。
$ sudo yum install -y gcc bzip2 openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel sqlite-devel git
Nodejsのインストールを行います。単にtherubyracerをインストールしたくないためです。これについては、NodejsのWebサイトに記載があります。
$ sudo su -
# curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
# yum -y install nodejs
Apacheのインストールを行います。
$ sudo yum install -y httpd
SE LinuxをOffにします。まずは設定ファイルである/etc/selinux/config
を開きます。
$ sudo vim /etc/selinux/config
SELINUX=enforcingとなっている行をSELINUX=disabledに変更します。
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
その後、システムを再起動します。
$ sudo reboot
Rubyのインストール
Rubyのインストールはrbenvを使います。特定のユーザではなく、システム全体で使えるようにします。
$ cd /usr/local
$ sudo git clone https://github.com/rbenv/rbenv.git rbenv
$ sudo chgrp -R railsapp rbenv
$ sudo chmod -R g+rwxXs rbenv
環境変数の設定を行います。/etc/profile
の末尾に次の記述を追加します。
export RBENV_ROOT=/usr/local/rbenv
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
書き終わったら、再読込して有効化します。
source /etc/profile
次にruby-buildをインストールします。
$ mkdir /usr/local/rbenv/plugins
$ cd /usr/local/rbenv/plugins
$ sudo git clone https://github.com/rbenv/ruby-build.git
$ sudo chgrp -R railsapp ruby-build
$ sudo chmod -R g+rwxs ruby-build
また、rbenv-default-gemsを入れます。これを入れるとRubyのインストール時に自動的に設定したgemもインストールされます。
$ cd /usr/local/rbenv/plugins
$ git clone https://github.com/rbenv/rbenv-default-gems.git
次に/usr/local/rbenv/default-gems
というファイルを作り、1行に1つのgemを書きます。
bundler
pry
Rubyをインストールします。
$ rbenv install 2.3.3
インストール後、使うRubyのバージョンをglobal設定としておきます。
$ rbenv global 2.3.3
今回Railsは4.2.8を使うので、対象バージョンのRailsをインストールします。
$ gem install rails -v 4.2.8 --no-doc
Railsアプリの作成
動かすRailsアプリを作ります。サンプルなのでテストファイルは作らずに。Gemfile
を編集したあとでbundle install
するのでrails new
のタイミングではbundle install
はしないようにします。
$ rails _4.2.8_ new rails_sample -B -T --skip-turbolinks
Gemfileを編集します。development環境やtest環境などのgemは記していません。
source 'https://rubygems.org'
gem 'rails', '4.2.8'
gem 'sqlite3'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'jbuilder', '~> 2.0'
gem 'unicorn'
Gemfileを編集後にbundle install
します。
$ bundle install --path vendor/bundle
動作確認のためにrails g scaffold
で適当にアプリを作ります。
$ bundle exec rails g scaffold post title:string body:text
$ bundle exec rake db:migrate RAILS_ENV=production
config/routes.rb
を編集してroot pathを設定します。
Rails.application.routes.draw do
resources :posts
root 'posts#index'
end
JavaScriptやCSSをprecompileします。
$ bundle exec rake assets:precompile
環境変数SECRET_KEY_BASE
に設定する値を生成します。
$ bundle exec rake secret
生成した値は、Apache httpdの実行ユーザの環境変数として設定します(下記のxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxの部分はbundle exec rake secret
で生成された値を入れます)。
export SECRET_KEY_BASE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Unicornの設定
config/uniorn.rb
というファイルを作成します。
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true # 更新時ダウンタイム無し
listen 8080, :tcp_nopush => true
pid "/tmp/unicorn.pid"
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
# ログの出力
stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
これで次のコマンドでUnicornが起動するようになります。
$ bundle exec unicorn_rails -c config/unicorn.rb -E production
rakeコマンドを作り、Unicornの起動や終了ができるようにします。
namespace :unicorn do
desc "Start unicorn for production env."
task(:start) {
config = Rails.root.join('config', 'unicorn.rb')
sh "bundle exec unicorn_rails -c #{config} -E production -D"
}
desc "Stop unicorn"
task(:stop) { unicorn_signal :QUIT }
desc "Restart unicorn with USR2"
task(:restart) { unicorn_signal :USR2 }
desc "Increment number of worker processes"
task(:increment) { unicorn_signal :TTIN }
desc "Decrement number of worker processes"
task(:decrement) { unicorn_signal :TTOU }
desc "Unicorn pstree (depends on pstree command)"
task(:pstree) do
sh "pstree '#{unicorn_pid}'"
end
def unicorn_signal signal
Process.kill signal, unicorn_pid
end
def unicorn_pid
begin
File.read("/tmp/unicorn.pid").to_i
rescue Errno::ENOENT
raise "Unicorn doesn't seem to be running"
end
end
end
これでUnicornはRailsアプリのROOTディレクトリ上で以下のコマンドを実行します。
$ bundle exec rake unicorn:start
で起動することができるようになります。
また、RailsアプリのROOTディレクトリ上で
$ bundle exec rake unicorn:stop
でUnicornの停止ができるようになります。
Apache httpdの設定
Apache httpdの設定ファイルを記述します。管理しやすいように/etc/httpd/conf/httpd.conf
に追記するのではなく、別ファイルに記述します。
アクセス制御はとりあえず全てに対して許可するようにします。
RailsアプリのROOTディレクトリ上は/home/dev1/work/rails_sample
とした場合、次のような設定となります。
<VirtualHost *:80>
DocumentRoot /home/dev1/work/rails_sample/public
<Directory "/home/dev1/work/rails_sample/public">
AllowOverride All
Options -MultiViews
Order deny,allow
Allow from all
</Directory>
ServerName サーバ名
ErrorLog logs/app-error_log
CustomLog logs/app-access_log common
<Proxy *>
Order deny,allow
</Proxy>
ProxyRequests Off
ProxyPass /assets/ !
ProxyPass /fonts/ !
ProxyPass /robots.txt !
ProxyPass /favicon.ico !
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
ProxyPreserveHost on
</VirtualHost>
また、Apache httpdの実行ユーザと実行グループを変更します。
## (前略)
User dev1
Group railsapp
## (後略)
これで後はUnicornの起動とhttpdを起動してブラウザでアクセスすればOKです。
Unicornの起動はRailsアプリのROOTディレクトリ上で以下のコマンドを実行します。
$ bundle exec rake unicorn:start
で、httpdの起動は
$ sudo service httpd start
です。