84
89

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CentOS7, Ruby on Rails 5, PumaでProducrion環境構築@VPS + Capistranoでのデプロイ

Last updated at Posted at 2016-11-03

はじめに

プライベートでサービスを立ち上げるときには、今まではいつもherokuを使っていました。herokuはすべてがサービス化されていてすごい楽なんですけど、反面、コスパが悪くて、ちゃんとプライベートのサービスやるには向かねーなあって思ってました。

そんなわけで重い腰を上げて今回からは自分でVPSを使って環境構築してみることにしました。自分はサーバ設定まわりがとても苦手で、かつ、まとまった情報もあまりネットになく、けっこう苦労したので、普段qiitaとか書かないのですが、せっかくなのでまとめておきます。

CentOS7 + Ruby on Rails 5 + Pumaで動作。Capistranoでのデプロイができるというところまで。

おおまかな流れ

  • Railsを動作させる@ローカルMac
    • プロジェクト作成
    • MySQLユーザ作成
    • git, github初期設定
  • VPS初期設定
    • ユーザ作成
    • firewall設定
    • swap領域作成
  • MySQLインストール
  • Rubyインストール
    • rbenv
    • ruby
    • bundler
  • Nginxインストール
  • Capistranoでデプロイ

Railsを動作させる@ローカルMac

まずはローカルでrailsプロジェクトが動くようにします。最終的にローカルからCapistranoでdeployを行います。RubyやMySQLなどはインストールされているものとします。

プロジェクト作成

$ rails new アプリ名 -d mysql

MySQLユーザの作成

$ mysql -u root
> CREATE USER 'DBユーザ名'@'localhost' IDENTIFIED BY 'パスワード';
> GRANT ALL PRIVILEGES ON DB名.* TO 'DBユーザ名'@'localhost';
> FLUSH PRIVILEGES;
> exit;

DBユーザ名、パスワード、DB名はあとでdatabase.ymlに書く必要があるのでメモっておく。

git, githubの設定

gitを初期し、githubへアップします。

$ cd アプリ名
$ git init

.gitignoreを編集して不要なファイルがgit管理されないようにしましょう。

/.bundle
/vendor/bundler/
/log/*.log
/tmp
/uploads/tmp/
/config/settings.local.yml
/config/settings/*.local.yml
/config/environments/*.local.yml
/config/secrets.yml
/config/database.yml

.pryrc
.DS_Store

コミットしてプッシュします

$ git add .
$ git commit -m "first commit"
$ git remote add origin git@github.com:eiei19/アプリ名とか.git
$ git push -u origin master

database.yml と sercrets.ymlの編集

こんな感じになるはずです。

databese.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  host: 127.0.0.1

development:
  <<: *default
  database: DB名
  username: DBユーザ名
  password: DBパスワード

test:
  <<: *default
  database: dos_test

production:
  <<: *default
  database: DB名(production)
  username: DBユーザ名(production)
  password: DBパスワード(production)
sercrets.yml
development:
  secret_key_base: xxx

test:
  secret_key_base: xxx

production:
  secret_key_base: xxx

Production環境のDBパスワードなどは、あとでVPS側で設定するときに決めます。

railsを動かす

DBの作成と起動

$ bin/rake db:create
$ bin/rails server

http://localhost:3000 にアクセスしてRailsのWelcome画面が表示されればOK。

適当にコントローラーとか作る

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
  end
end
app/views/posts/index.html.erb
<h1>Hello World</h1>
config/routes.rb
Rails.application.routes.draw do
  get '/posts', to: 'posts#index'
end

http://localhost:3000/posts にアクセスしてHello Worldが表示されればOK。commit&pushしておきましょう。

VPS初期設定

今回はvultrというVPSサービスを使ってみました。よくわかってないですが、コンパネから一発でVPSを立ち上げることができて、snapshotとかもとれて、Tokyoリージョンもあります。ミニマムで$5/monthからと値段もお手頃。

SSHの設定

サーバをCentOS7で立ち上げます。まずはssh周りを設定します。

$ root@IPアドレス

--  ここからVPS --

# adduser ei
# passwd ei
# gpasswd -a ei wheel
# mkdir /home/ei/.ssh
# vi /home/ei/.ssh/authorized_keys
> 公開鍵を貼り付ける
# chmod 700 /home/ei/.ssh/authorized_keys
# chown -R ei:ei /home/ei/.ssh/

-- ローカルで違うターミナルを開く --

$ ssh ei@IPアドレス #接続できることを確認する

--  ここからVPS --

$ sudo vi /etc/ssh/sshd_config

> 以下を変更
PermitRootLogin no
PasswordAuthentication no

$ sudo systemctl reload sshd

これでrootログインとパスワードログインができなくなった。

Timezone設定

$ sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
$ date

Firewall設定

次にiptablesによるFirewallの設定をします。

$ sudo yum remove -y firewalld
$ sudo yum install -y iptables-services
$ sudo systemctl start iptables
$ sudo systemctl enable iptables
$ sudo /usr/libexec/iptables/iptables.init save
$ sudo vi /etc/sysconfig/iptables

> こんな感じにする。Web用に80と433をあける。
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [48:7196]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

$ sudo systemctl reload iptables

swap領域の確保

初期設定だとswap領域が確保されていないので、メモリを使いすぎると、使いすぎてるプロセスがキルされます。それだと困るのでswap領域を確保しておきます。

# dd if=/dev/zero of=/swapfile bs=1M count=1024
# mkswap /swapfile
# swapon /swapfile
# vi /etc/fstab 

> 以下追記

/swapfile swap swap defaults 0 0

ここまでできたら自動マウントされるか試すためにサーバを再起動する。topコマンドswap領域が確保されてればOK。

MySQLインストール

つぎはミドルウェアとかを入れていきます。まずはMySQLから。

インストール

# yum -y remove mariadb-libs
# rm -rf /var/lib/mysql/
# yum -y localinstall http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
# yum -y install mysql-community-server mysql-devel
# systemctl enable mysqld.service
# systemctl start mysqld.service
# cat /var/log/mysqld.log | grep "A temporary password"

> 表示されるパスワードを使ってインストールする

# mysql_secure_installation

> 新しいパスワードを決める。質問は全部YESでOK.

# vi /etc/my.cnf

> 以下追記
character-set-server = utf8
default_password_lifetime = 0

ユーザ作成

# mysql -u root -p

> CREATE USER 'DBユーザ名'@'localhost' IDENTIFIED BY 'パスワード';
> GRANT ALL PRIVILEGES ON DB名.* TO 'DBユーザ名'@'localhost';
> FLUSH PRIVILEGES;
> exit;

Rubyインストール

Rubyをインストールします。今回はrbenvを使います。

# yum -y install git gcc-c++ glibc-headers openssl-devel readline libyaml-devel readline-devel zlib zlib-devel bzip2
# cd /usr/local
# git clone git://github.com/sstephenson/rbenv.git rbenv
# git clone git://github.com/sstephenson/ruby-build.git rbenv/plugins/ruby-build

# vi /etc/profile.d/rbenv.sh

> 以下を記述
export RBENV_ROOT="/usr/local/rbenv"
export PATH="${RBENV_ROOT}/bin:${PATH}"
eval "$(rbenv init --no-rehash -)"

# source /etc/profile.d/rbenv.sh
# rbenv install 2.3.0
# rbenv global 2.3.0
# rbenv rehash
# gem install bundler --no-ri --no-rdoc

最後にnodejsをいれておく。railsで必要。
# yum -y install nodejs

Nginxインストール

# vi /etc/yum.repos.d/nginx.repo

> 以下記載
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1

# yum -y update
# yum -y install nginx
# systemctl start nginx
# systemctl enable nginx

Capistranoでデプロイ

デプロイ準備

デプロイ用のディレクトリとユーザを作成します。

# mkdir /var/www
# adduser www
# chown -R www:www /var/www
# chmod -R 770 /var/www/
# adduser deploy
# gpasswd -a deploy www
# gpasswd -a nginx www
# mkdir /home/deploy/.ssh
# vi /home/deploy/.ssh/authorized_keys
> デプロイ用ユーザの公開鍵を貼り付ける。最初のユーザとは変えておく。macでは、ssh-keygen -t rsa でキーペアを作れる。
# chown -R deploy:deploy /home/deploy/.ssh
# chmod -R 700 /home/deploy/.ssh
$ ssh -i ~/.ssh/さっき貼り付けた公開鍵とペアの秘密鍵 deploy@IPアドレス
> ログインできるか確認する

Capistrano設定

あともう一息です。ローカルのRailsプロジェクトに戻ります。gemファイルに追記。

group :development do
  gem 'capistrano',         require: false
  gem 'capistrano-rails',   require: false
  gem 'capistrano-bundler', require: false
  gem 'capistrano3-puma',   require: false
  gem 'capistrano-rbenv',   require: false
end
$ bundle install --path vendor/bundle
$ bundle exec cap install
Capfile.
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rails'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/puma'
deploy.rb
server 'IPアドレス', port: 22, roles: [:app, :web, :db], primary: true
set :repo_url,        'git@github.com:eiei19/アプリ名とか.git'
set :application,     'アプリ名'
set :user,            'deploy'
set :ssh_options,     {
  forward_agent: true,
  user: fetch(:user),
  keys: %w(~/.ssh/deployユーザの秘密鍵)
}
set :puma_threads,    [4, 16]
set :puma_workers,    0
set :pty,             true
set :use_sudo,        false
set :stage,           :production
set :deploy_via,      :remote_cache
set :deploy_to,       "/var/www/#{fetch(:application)}"
set :puma_bind,       "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state,      "#{shared_path}/tmp/pids/puma.state"
set :puma_pid,        "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.access.log"
set :puma_error_log,  "#{release_path}/log/puma.error.log"
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :rbenv_type, :system
set :rbenv_ruby, '2.3.0'
set :linked_dirs, fetch(:linked_dirs, []).push(
  'log',
  'tmp/pids',
  'tmp/cache',
  'tmp/sockets',
  'vendor/bundle',
  'public/system',
  'public/uploads'
)
set :linked_files, fetch(:linked_files, []).push(
  'config/database.yml',
  'config/secrets.yml'
)

namespace :puma do
  desc 'Create Directories for Puma Pids and Socket'
  task :make_dirs do
    on roles(:app) do
      execute "mkdir #{shared_path}/tmp/sockets -p"
      execute "mkdir #{shared_path}/tmp/pids -p"
    end
  end
  before :start, :make_dirs
end

namespace :deploy do
  desc "Make sure local git is in sync with remote."
  task :check_revision do
    on roles(:app) do
      unless `git rev-parse HEAD` == `git rev-parse origin/master`
        puts "WARNING: HEAD is not the same as origin/master"
        puts "Run `git push` to sync changes."
        exit
      end
    end
  end

  desc 'Initial Deploy'
  task :initial do
    on roles(:app) do
      before 'deploy:restart', 'puma:start'
      invoke 'deploy'
    end
  end

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      invoke 'puma:restart'
    end
  end

  before :starting,     :check_revision
  after  :finishing,    :compile_assets
  after  :finishing,    :cleanup
end
$ cap production deploy:initial

database.ymlがないとか言われるはずなので、サーバにdeployユーザでログインして配置します。ホントはここも自動化するべき。

nginx設定

最後にnginxを設定して終了。
/etc/nginx/conf.d/xxxx.conf とか置く。

upstream アプリ名 {
    server unix:/var/www/アプリ名/shared/tmp/sockets/アプリ名-puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name サーバのIPもしくはドメイン;
    root /var/www/アプリ名/current/public;

    location ~ ^/assets/ {
      root /var/www/アプリ名/current/public;
    }

    try_files $uri/index.html $uri @アプリ名;

    location / {
        proxy_pass http://アプリ名;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}
84
89
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
84
89

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?