1
3

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.6 RubyonRails6 mysql8でconohaVPSに公開するまで

Last updated at Posted at 2019-08-22

Railsのリポジトリがある前提です
バージョン

centos
7.6
mysql
8.0.17

$ ruby -v
2.6.3
$ rails -v 
6.0.0.rc1

$ node -v
v12.8.0

大まかな手順

1. conohaにVPS登録
2. vpsサーバの各種設定
3. Rubyインストール
4. mysqlインストール・設定
5. nginxインストール・設定
6. CapistranoとUnicornのインストール・設定
7.
8.

1. conohaに登録

↓ こちらから登録すると1000円分のクーポンがもらえるらしいです
https://www.conoha.jp/referral/?token=IWGrST5H2QhYV.qMLTsPTHRLvaa1fDkrP7CpxS7_2efeNKRbFC8-O6O

私はCentos7.6でメモリ2GB1750円のvpsプランを選択しました。

=>⚠️ # はroot権限という意味です

2. サーバーの設定

ログイン
$ ssh root@123.43.567.89

# yum update

localeを変更する
# localectl set-locale LANG=ja_JP.utf8
# localectl
# cat /etc/locale.conf
# source /etc/locale.conf #反映


作業ユーザー登録
# useradd username
# passwd username
# usermod -G wheel username
# visudo

↓ファイルが立ち上がる
## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

上の行の先頭のコメントを外して保存

一旦、サーバーから抜けて作成したユーザーでログインできるか確認

$ ssh hogehuga@123.45.678.000
ログイン成功!!

鍵認証の設定

Mac側で鍵のペアを生成(秘密鍵と公開鍵)
VPS側で公開鍵をMac側で秘密鍵を使ってマッチさせる仕組み
鍵を生成前にまずはVPS側で公開鍵の保管場所を作成する

$ mkdir ~/.ssh     # ディレクトリ作成
$ chmod 700 ~/.ssh #パーミッション設定

MAC側(localhost)で作業

$ ssh-keygen -y rsa -v # 鍵が作成される(id_rsaとid_rsa.pub)
$ chmod 600 ~/.ssh/id_rsa.pub # パーミッション付与

公開鍵をVPSに転送

$ scp ~/.ssh/id_rsa.pub hogehuga@123.45.678.000:~/.ssh/authorized_keys

vpsに入って確認する

$ ls -la .ssh
=> authorized_keysが入っていれば良い

セキュリティを高めるsshの設定

# vim /etc/ssh/sshd_config
で以下のように変更

PubkeyAuthentication yes
Port変更
Port 55555
rootユーザーでのログインを禁止。
PermitRootLogin no
パスワードログインを禁止。yesからnoへ変更
PasswordAuthentication no
公開鍵の場所を設定
AuthorizedKeysFile      .ssh/authorized_keys

sshdを再起動。編集を反映させる

# service sshd restart

iptablesをインストール

# yum install iptables-services
# vim /etc/sysconfig/iptables

下を削除
# -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
下を追加
-A INPUT -m state --state NEW -m tcp -p tcp --dport 55555 -j ACCEPT

iptablesの設定を反映させる再起動

# service iptables restart

configファイルも作っておく

# vi ~/.ssh/config

Host conoha_deploy_app
  HostName 123.45.67.89 # ip_adress
  User hogehuga
  Port 55555
  IdentityFile  ~/.ssh/id_rsa # deployの時にも使います

ssh-agentを登録しておく
$ eval `ssh-agent`
$ ssh-add ~/.ssh/id_rsa

ローカルから接続できているか試す
$ ssh conoha_deploy_app

3. Ruby インストール

サーバーでの作業が続きます

まずはgitをインストール!

なるべく新しいのが良いと思ったので2.7.4です。
少し手間ですが、以下のコマンドを実行しました。
参考
https://ex1.m-yabe.com/archives/3546

# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
#  cd /usr/local/src
#  wget  https://www.kernel.org/pub/software/scm/git/git-2.7.4.tar.gz
#  tar zxvf git-2.7.4.tar.gz
#  cd git-2.7.4
#  ./configure --prefix=/usr/local/
#  rpm -qa|grep gcc
#  yum -y install gcc
#  ./configure --prefix=/usr/local/
#  make prefix=/usr/local all
#  make prefix=/usr/local install
# git version
=> git version 2.7.4

rbenvインストール

rbenvはrubyのバージョン管理ツールです

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

ruby-buildインストール

ruby-burildはrbenv installを実行するためのrbenvのプラグインです。
rbenvとセットでインストール

$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

依存パッケージのインストール

rubyをインストールするための関連するパッケージです。これがないと、rbenv installの際にコケます。

$  sudo yum -y install bzip2 gcc openssl-devel readline-devel zlib-devel

rbenv読み込み設定

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# rbenvの初期化
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# bashの再読込
$ source ~/.bash_profile
# バージョン確認 バージョンが出ればOK
$ rbenv -v

Rubyインストール

$ rbenv install 2.6.3
$ rbenv global 2.6.3
$ rbenv rehash
# バージョン確認
$ ruby -v
2.6.3

bundlerインストール

$ gem install bundle

node.jsインストール

railsでnode.jsが必要

$ sudo yum install nodejs npm --enablerepo=epel
yarnもインストール
$ sudo npm install -g yarn

4. MySQL8のインストール

sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum install --enablerepo=mysql80-community mysql-community-server
sudo yum clean all
mysqld --version
systemctl enable mysqld.service 自動起動設定
systemctl start mysqld.service   起動
sudo grep 'temporary password' /var/log/mysqld.log => 最初のログインで使用する初期設定用のパスワードが表示されます
mysql -u root -p 
mysql_secure_installation =>passwordを変更する

Mysql 8のmy.cnf設定

デフォルトでも構いません
https://qiita.com/nanorkyo/items/94a80683c6753f61316a

/etc/my.cnf

リモートで
sudo vim /etc/my.cnf


自分はこんな感じです↓

[mysqld]
default-authentication-plugin=mysql_native_password
default-password-lifetime       = 0

datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

[mysqld]
character-set-server            = utf8mb4
collation-server                = utf8mb4_bin
open-files-limit                = 65536
max-connections                 = 10000
table-open-cache                = 2000

[client]
default-character-set           = utf8mb4

リスタートして

sudo systemctl restart mysqld.service

ログインする


Mysqlログイン
mysql -u root -p

> create user 'username'@'123.4.56.78' identified by 'password';

> grant all privileges on *.* to 'hogehuga'@'123.4.56.78' with grant option;
> flush privileges;

$ mysql -u hogehuga -h 123.4.56.78 -p

> create database app_production;
> exit;

5. nginx(webサーバー)の設定

デプロイするアプリの置き場所をVPSに用意する

$ sudo mkdir -p /var/www/アプリケーション名

nginxをインストールするための準備

# cd /etc/yum.repos.d
# touch nginx.repo

ファイルの中身を書き加えましょう。

管理者権限になっていることに注意

# vi nginx.repo

nginx.repoファイルの書き方は以下のような感じ(サンプル)

nginx.repo
[nginx]
name=nginx repo 
baseurl=http://nginx.org/packages/centos/7/$basearch/ 
gpgcheck=0 
enabled=1 

nginxをインストール

インストールされるリポジトリ情報を確認
# yum info nginx

インストール
# yum install nginx

設定ファイルをバックアップ

# sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/local.conf
# mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bk
/etc/nginx/conf.d/local.conf

# 各種ログのディレクトリ設定
  error_log  /var/www/app_name/current/log/nginx.error.log;
  access_log /var/www/app_name/current/log/nginx.access.log;
# 処理を受け取る最大許容量
  client_max_body_size 2G;

upstream unicorn {
 server unix:/var/www/deploy_app/shared/tmp/sockets/unicorn.sock; ### 変更箇所 ちょー大事、後ほど登場するユニコーンと紐づく
}


server {
    listen       80; # ポート番号
    server_name  123.654.87.9;
# 次のリクエストが来るまでの待ち時間(秒
    keepalive_timeout 5;


    location / {
        root   /var/www/app_name/current/public;
    }
    #キャッシュのディレクトリ
    try_files $uri/index.html $uri.html $uri @app;
    location @unicorn {
      # HTTP headers
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://unicorn;
    }
    error_page   500 502 503 504  /500.html;
    location = /500.html {
        root   /var/www/app_name/current/public;
    }
}

設定ファイルを編集

$ sudo vi /etc/sysconfig/iptables

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

を追記

# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-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 12345 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

みたいな感じになってます

再起動。

$ sudo service iptables restart

開放されてるか確認

$ sudo iptables -nL
こんな感じで表示されます
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80

サーバー再起動の際にもNginxが自動的に起動するよう設定

chkconfig nginx on

Nginxの設定が完了

6. CapistranoとUnicornの設定

Gemfileにインストール作業で使用する物を記述


ruby '2.6.3'
gem 'mysql2'
・・・・その他中略・・・
group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  # 以下追記
  gem 'capistrano'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
  gem 'capistrano-nvm', require: false
  gem 'capistrano-yarn'
  gem 'capistrano3/unicorn'
end

group :production, :staging do
 # 以下追記
 gem 'unicorn'
end


$ bundle install

Capistranoを設定していく

ファイルを生成するコマンド

$ cap install

capistranoの設定ファイルを編集

# capistranoの基本動作を設定
require "capistrano/setup"   
require "capistrano/deploy"  
require "capistrano/scm/git" 
install_plugin Capistrano::SCM::Git


require "capistrano/rails" 
require "capistrano/rails/assets"
require "capistrano/rails/migrations" 
# rbenvの設定
require "capistrano/rbenv" #ok
require "capistrano/bundler"
require "pry" # 全然必要ないけどデバッグで便利でした...
require 'capistrano/yarn'
require 'capistrano3/unicorn'


Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

リモートのサーバー情報書いていく

config/deploy/production.rb
set :stage, :production
set :branch, 'master' ## 必要があれば変更

server '21.43.65.7', user: 'hoge', roles: %w{app db web}, port: 12345

set :ssh_options, {
  port: 12345, #### 変更
  keys: [File.expand_path('~/.ssh/id_rsa')], # リモートサーバー用秘密鍵があるところを指定
  forward_agent: true,
  auth_methods: %w(publickey)

アプリケーション名や
gitのリポジトリなど書いていきます

config/deploy.rb

# config valid for current version and patch releases of Capistrano
lock "~> 3.11.0"

set :application, "deploy_app"
set :repo_url, "git@github.com:user_name/deploy_app.git" デプロイするgitリポジトリURL

set :deploy_to, '/var/www/deploy_app' # デプロイ先

set :rbenv_type, :user  # rbenvをシステムにインストールした or ユーザーローカルにインストールした
set :rbenv_ruby, '2.6.3' # サーバで利用するrubyのバージョンを指定
set :rbenv_path, '/home/username/.rbenv'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"

# リリースフォルダをいくつまで保持するか?
set :keep_releases, 5
set :deploy_via, :remote_cache

set :log_level, :debug # capistranoの出力ログの制御
set :pty, true # sudoを使用するのに必要

set :yarn_flags, "--ignore-engines --prefer-offline --production --no-progress"
set :yarn_roles, :all
set :yarn_env_variables, {}

# Shared に入るものを指定
set :linked_files, %w{config/database.yml config/secrets.yml} # シンボリックリンクを貼るファイル
set :linked_dirs,  %w{log tmp/pids tmp/sockets tmp/cache vender/bundle } # sharedにシンボリックリンクを張るディレクトリ指定

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do


 desc 'Restart application'
  # アプリ再起動を行うタスク
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      execute :mkdir, '-p', release_path.join('tmp')
      execute :touch, release_path.join('tmp/restart.txt')
    end
  end
  # linked_files で使用するファイルをアップロードするタスク
  # deployが行われる前にコマンドにて実行する
  desc 'upload important files'
  task :upload do
    on roles(:app) do |host|
      execute :mkdir, '-p', "#{shared_path}/config"
      upload!('config/database.yml',"#{shared_path}/config/database.yml")
      upload!('config/secrets.yml',"#{shared_path}/config/secrets.yml")
    end
  end

  # webサーバー再起動時にキャッシュを削除する
  after :restart, :clear_cache do
   on roles(:web), in: :groups, limit: 3, wait: 10 do
    #Here we can do anything such as:
    within release_path do
      execute :rm, '-rf', release_path.join('tmp/cache')
    end
   end
  end
  # Flow の before, after のタイミングで上記タスクを実行
  before :started,   'deploy:upload'
  after  :finishing, 'deploy:cleanup'

  #unicorn 再起動タスク
  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart' # lib/capustrano/tasks/unicorn.rake 内処理を呼び出す
  end
end


認証で使うsecrets.ymlを生成します
ローカルで以下のコマンドを実施

$ rails secret | pbcopy

ファイルに貼り付ける

config/secrets.yml
production:
  secret_key_base: #####ここに貼り付けてください

リモートサーバにて

必要なディレクトリを作成しておく

$ sudo mkdir -p /var/www/deploy_app/shared/config
$ sudo  chown -R 作業ユーザー名 www

Uniconの設定をします

ローカルで

vim lib/capistrano/tasks/unicorn.cap

コピペでいいです

namespace :unicorn do
  task :environment do
    set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid" # config/unicorn/production.rbないのpidと同じ
    set :unicorn_config, "#{current_path}/config/unicorn/production.rb"
  end

  def start_unicorn
    # フォルダが存在した場合のみ実行する
    within current_path do
    execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
    end
  end
  # unicorn停止
  def stop_unicorn
    execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
  end
  # unicorn再起動
  def reload_unicorn
    execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})" 
  end
  # unicorn 強制終了
  def force_stop_unicorn
    execute :kill, "$(< #{fetch(:unicorn_pid)})"
  end
  # unicorn をスタートさせる
  desc "Start unicorn server"
  task :start => :environment do
    on roles(:app) do
      start_unicorn
    end
  end
  # unicorn停止させる
  desc "Stop unicorn server gracefully"
  task :stop => :environment do
    on roles(:app) do
      stop_unicorn
    end
  end
  # 
  desc "Restart unicorn server gracefully"
  task :restart => :environment do # TODO
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        reload_unicorn
      else
        start_unicorn
      end
    end
  end
  # unicornを強制終了させるTask
  desc "Stop unicorn server immediately"
  task :force_stop => :environment do # TODO
    on roles(:app) do
      force_stop_unicorn
    end
  end
end

unicornの設定ファイルを書いていく
ここがうまく紐づかないとリリース後にrailsが動かなかったりします
気をつけてください

config/unicorn/production.rb

# -*- coding: utf-8 -*-
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 30

# ホットデプロイをするか?
preload_app true # 更新時ダウンタイム無し
current_path = '/var/www/deploy_app/shared'
app_path = '/var/www/deploy_app/current'
working_directory "#{app_path}"

# nginxと連携するための設定
# リクエストを受け取る ポート番号を指定
listen "/var/www/deploy_app/shared/tmp/sockets/unicorn.sock" # nginxと同じ

# PIDの管理ディレクトリ
pid "#{current_path}/tmp/pids/unicorn.pid"

stdout_path "#{app_path}/log/unicorn.log"
stderr_path "#{app_path}/log/unicorn.log"


# ログの出力パス
stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])

puts "カレントパス#{ current_path }"
puts ""

# フォーク前に行うことを定義
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

database.ymlの設定

config.database.yml
default: &default
  adapter:  mysql2
  encoding:  utf8mb4
  charset:   utf8mb4
  collation: utf8mb4_unicode_ci
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: 
  host: localhost
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: deploy_app_development

test:
  <<: *default
  database: deploy_app_test

production:
  <<: *default
  adapter: mysql2
  database: deploy_app_production
  username: username
  password: PassWord
  host: 12.34.765.89

7 リモートとgithubの連携

ローカルとサーバーの鍵認証は先にしておりますが、
リモートサーバーとgithubを連携するための
鍵認証の設定です

リモートサーバーで作業すること

$ cd ~/.ssh
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hogehuga/.ssh/id_rsa): Enter 
Enter passphrase (empty for no passphrase): Enter
Enter same passphrase again: Eneter

$ cat id_rsa.pub
# 出力をコピーして、以下のgithubのコンソールリンクより公開鍵を登録
-> https://github.com/settings/keys


# 設定ファイルを作成
$ sudo vi ~/.ssh/config
# 以下を記述
Host github
  Hostname github.com
  User git
  IdentityFile ~/.ssh/id_rsa 

ssh-agentの設定(これやらないとpermission error出ます)
$ eval `ssh-agent` 
$ ssh-add ~/.ssh/id_rsa

$ ssh -vT github で確認 # vはデバッグオプションで便利 
# 以下のような文章が出力されればOK
Hi Hogehuga! You've successfully authenticated, but GitHub does not provide shell access.

gitにプッシュする

$ git add .
$ git commit -m "deploy"
$ git git push origin master

長かったですが、デプロイしてみましょう
ローカルから

$ bundle exec cap production deploy:upload # database.yml、secrets.ymlをアップロードする
$ bundle exec cap production deploy:check # deploy可能かのチェック
$ bundle exec cap production deploy

すんなりいくとは思いませんが、
エラーが起きた場合にはnginxのログやunicornのログなどを頼りにしつつ、問題を切り分けてコツコツ進んでいくのが良いと思います。

ファイルの権限/設定のパスの整合性/各種システムの起動し忘れ/などなどです

雑なメモ

nginx基本コマンド
起動
$ sudo systemctl start nginx
停止
$ sudo systemctl stop nginx
再起動
$ sudo systemctl restart nginx
再起動しても設定ファイルが反映されない場合など
$ sudo nginx -s reload
状態の確認
$ sudo systemctl status nginx


Mysqlコマンド
ログイン
mysql -u username -h 123.45.67.89 -p

・起動
sudo service mysqld start
・停止
sudo service mysqld stop
・再起動
sudo service mysqld restart


Iptablesコマンド

systemctl start iptables
systemctl enable iptables
systemctl status iptables

sshdコマンド
systemctl restart sshd
systemctl status sshd




Unicornコマンド



1
3
0

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
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?