はじめに
CentOS7での記事の後、CentOS8も試したので、書き留めておきます。
Vultrの一番安い10GB SSDプランだとCentOS8ではディスクが足りなくなるので25G以上をお勧めします。以下の手順はRubyだけ古いバージョンですが、これはローカルのアプリが ruby 2.5.3 で動いているためです。2.7でも手順は同じでOKと思います。(未検証)
激安VPSのVultrで紹介者からのリンク経由でアカウント登録すると$100のクレジットをもらえるので、CentOS7, 8, MySQL 5.7, 8などの組み合わせをいろいろ試しました。このキャンペーンはいつ終わるか分からないので、興味のある方は以下のリンクからアカウント登録してください。あなたはクレジットをもらえるし、私にも多少のクレジットが入るらしいので、Win-Winです。
このリンクで$100もらえます
私もリファラー経由でアカウントを作ったので$100もらえました。これで最初にあれやこれや試すのは無料でできます。
0. OS基本設定
前回のCentOS7での記事の1〜6までを行って、ユーザー作成やSwap領域の設定などをやっておきます。
1. MySQL 8 をインストール
$ sudo su
Unistall MariaDB
# yum -y remove mariadb-libs
# rm -rf /var/lib/mysql/
Install MySQL 8
# yum -y install @mysql
# systemctl start mysqld
# systemctl enable --now mysqld
# systemctl status mysqld
# mysql_secure_installation
Securing the MySQL server deployment.
Connecting to MySQL using a blank password.
VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?
Press y|Y for Yes, any other key for No: y
There are three levels of password validation policy:
LOW Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2
Please set the password for root here.
New password:
Re-enter new password:
Estimated strength of the password: 100
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
- Dropping test database...
Success.
- Removing privileges on test database...
Success.
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.
All done!
2. Ruby V2.5.3 をインストール
# yum groupinstall "Development Tools"
# yum -y install libyaml-devel
# yum install -y openssl-devel readline-devel zlib-devel
# 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.5.3 <=これが時間がかかる。
# rbenv global 2.5.3
# rbenv rehash
3. bundler 2.1.2 をインストール
自分の開発環境のBundlerが2.1.2なのでそれに合わせたが、バージョンは開発環境に合わせる。
# gem install bundler -v 2.1.2
4. node.js をインストール
# yum install -y nodejs
# node --version
v10.19.0
5. yarn をインストール
# npm install -g yarn
6. Nginx stable最新版をインストール
(1)yum-utils をインストール
# yum install yum-utils
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
(2) インストール
# cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
# yum --disablerepo=AppStream install -y nginx
Basic認証を使いたいのでhttpd-toolsもインストール
# yum install httpd-tools
(3) 動作確認
nginx起動
$ sudo nginx
nginx自動起動設定
# systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
動作状態確認
# systemctl status nginx
● nginx.service - nginx - high performance web server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Sun 2020-03-15 17:14:15 UTC; 5s ago
Docs: http://nginx.org/en/docs/
Process: 3413 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
Main PID: 3414 (nginx)
Tasks: 2 (limit: 5066)
Memory: 2.0M
CGroup: /system.slice/nginx.service
├─3414 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
└─3415 nginx: worker process
Mar 15 17:14:14 vultrguest systemd[1]: Starting nginx - high performance web server...
Mar 15 17:14:15 vultrguest systemd[1]: nginx.service: Can't open PID file /var/run/nginx.pid (yet?) after start: No such file or directory
Mar 15 17:14:15 vultrguest systemd[1]: Started nginx - high performance web server.
(4) ブラウザでアクセス
7. snapshot
ここまででクリーンインストールが終わったので、他の作業前にスナップショットを取得しておく。
8. Rails 6 をインストール
(1) Rails6のための事前準備
# yum install mysql-devel
# gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'
# gem install msgpack
(2) Rails 6 をインストール
# gem install rails -v 6.0.2.1
...
Done installing documentation for concurrent-ruby, i18n, thread_safe, tzinfo, zeitwerk, activesupport, rack, rack-test, mini_portile2, nokogiri, crass, loofah, rails-html-sanitizer, rails-dom-testing, builder, erubi, actionview, actionpack, activemodel, activerecord, globalid, activejob, mini_mime, mail, actionmailer, nio4r, websocket-extensions, websocket-driver, actioncable, mimemagic, marcel, activestorage, actionmailbox, actiontext, thor, method_source, railties, sprockets, sprockets-rails, rails after 87 seconds
40 gems installed
9. Test rails app
動作検証用に適当なアプリを作る。Capistranoでローカル環境からデプロイする場合はこの動作検証はスキップして構わない。
(1) directory preparation
$ sudo su
[root@vultrguest var]# mkdir /var/www
[root@vultrguest var]# mkdir /var/www/myapp
[root@vultrguest var]# chown -R deploy.deploy /var/www
(2) Gemfile preparation
$ bundle init
Writing new Gemfile to /var/www/myapp/Gemfile
$ vi Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem "rails" <= remove "#" here
(3) rails new
$ bundle install --path vendor/bundle
$ bundle exec rails new . -B -d mysql --skip-test
$ bundle install --path vendor/bundle
$ rails webpacker:install
...
Webpacker successfully installed 🎉 🍰
$ rails s
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.3 (ruby 2.5.3-p105), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop
(4) telnetで確認
前提条件 :Port 3000が開いている事
$ yum list installed | grep telnet
もしtelnetがインストールされていなければインストール
$ sudo yum -y install telnet telnet-server
$ telnet 127.0.0.1 3000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
GET / HTTP/1.1 <=Enterを2回押す事。
HTTP/1.1 403 Forbidden
Content-Type: text/html; charset=UTF-8
Content-Length: 3102
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Action Controller: Exception caught</title>
<style>
body {
background-color: #FAFAFA;
....
</body>
</html>
Connection closed by foreign host.
これでPumaが動いていることは確認できました。外部からブラウザでアクセスするにはnginxとの連携の設定が必要です。
(5) Snapshot
一旦、ここまででスナップショットを取っておきます。
10. Capistrano3でデプロイ
今度はローカルの開発環境で作ったアプリをCapistrano3でデプロイしてみます。
前提条件
- GitHubにSSH公開鍵でローカルからPushできていること。
(1) Vultr VPSにアプリのデプロイ先ディレクトリを準備
$ sudo su
# mkdir /var/www
# mkdir /var/www/myapp
# mkdir /var/www/myapp/shared
# mkdir /var/www/myapp/shared/config
# adduser www
# chown -R www:www /var/www
# chown -R deploy /var/www/myapp
# gpasswd -a deploy www
# gpasswd -a nginx www
(2) デプロイ対象外指定したファイルをコピー
$ scp -i ~/.ssh/vultr config/master.key deploy@SERVER_IP_ADDR:/var/www/myapp/shared/config/
$ scp -i ~/.ssh/vultr config/database.yml deploy@SERVER_IP_ADDR:/var/www/myapp/shared/config/
(3) Capistrano関連Config
# Use Capistrano for deployment
group :development do
gem 'capistrano'
gem 'ed25519'
gem 'bcrypt_pbkdf'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano3-puma'
end
Capfile, config/deploy.rbを生成
$ bundle exec cap install STAGES=production
Capfile, config/deploy.rbを設定
# Load DSL and set up stages
require "capistrano/setup"
# Include default deployment tasks
require "capistrano/deploy"
# Load the SCM plugin appropriate to your project:
#
# require "capistrano/scm/hg"
# install_plugin Capistrano::SCM::Hg
# or
# require "capistrano/scm/svn"
# install_plugin Capistrano::SCM::Svn
# or
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
# Include tasks from other gems included in your Gemfile
# require "capistrano/rvm"
require "capistrano/rbenv"
# require "capistrano/chruby"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
# require "capistrano/passenger"
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Nginx
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"
server 'Your Vultr IP ADDR', port: 22, roles: [:app, :web, :db], primary: true
set :application, 'myapp'
set :repo_url, 'git@github.YOU/myapp.git'
set :user, 'deploy'
set :ssh_options, {
forward_agent: true,
user: fetch(:user),
keys: %w(~/.ssh/vultr)
}
# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, "/var/www/my_app_name"
set :deploy_to, "/var/www/myapp"
# Default value for :format is :airbrussh.
# set :format, :airbrussh
# You can configure the Airbrussh format using :format_options.
# These are the defaults.
# set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto
# Default value for :pty is false
# set :pty, true
# Default value for :linked_files is []
# append :linked_files, "config/database.yml"
# Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
append :linked_dirs, '.bundle'
append :linked_files, "config/master.key"
append :linked_files, "config/database.yml"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets"
# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
# Default value for local_user is ENV['USER']
# set :local_user, -> { `git config user.name`.chomp }
# Default value for keep_releases is 5
# set :keep_releases, 5
# Uncomment the following to require manually verifying the host key before first deploy.
# set :ssh_options, verify_host_key: :secure
# rbenv
set :rbenv_type, :system
set :rbenv_ruby, File.read('.ruby-version').strip
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :bundle_jobs, 2 <=安いプランなので2。Defaultは4。
# debug log level
set :log_level, :debug <=設定作業中はデバッグモードにした。
(4) nginx-puma連携の事前デプロイ
VPS事前準備
# mkdir /etc/nginx/sites-available
# mkdir /etc/nginx/sites-enabled
# chgrp www sites-available
# chgrp www sites-enabled
capistrano-pumaプラグインで設定ファイル自動生成
これらコマンドで、サーバ上の /etc/nginx/sites-available
と shared/puma.rb
に設定ファイルが作られる。
$ bundle exec cap production puma:nginx_config
00:00 puma:nginx_config
Uploading /tmp/nginx_myapp_production 100.0%
01 sudo mv /tmp/nginx_myapp_production /etc/nginx/sites-available/myapp_production
✔ 01 deploy@Vultr_IP_ADDR 0.200s
02 sudo ln -fs /etc/nginx/sites-available/myapp_production /etc/nginx/sites-enabled/myapp_production
✔ 02 deploy@Vultr_IP_ADDR 0.223s
$ bundle exec cap production puma:config
00:00 puma:config
Uploading /var/www/myapp/shared/puma.rb 100.0%
デプロイ実行
デプロイを実行して、pumaが起動されるところまで正常終了することを確認する。
$ bundle exec cap production deploy
Tips 1:
GitHubをVultrサーバーから読み込めない場合、ローカル開発環境からGitHubにssh接続する時に使っているSSH鍵を以下のコマンドで追加すると直る。GitHubリポジトリを再作成した場合にエラーになったら試すと良い。
ssh-add ~/.ssh/id_rsa
Tips 2:
OpenSSLのエラーが出た場合、 config/master.key
で作成された config/credentials.yml.enc
がデプロイされているか確認する。 ~/.bash_profile
に export RAILS_MASTER_KEY="abc0123456789xyz..."
があるとRAILS_MASTER_KEYが優先されるので、キーが合わずにこのエラーになる。
DEBUG [3b3d9306] rake aborted!
ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage
...
Caused by:
OpenSSL::Cipher::CipherError:
(5) nginx-puma連携の設定
nginxとpumaがソケットで連携する設定を行う。
#user nginx;
user deploy; <=重要。NginxとPumaは同じユーザーでプロセスを起動する。
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*; <=RailsアプリのConfigをここでインクルードしている。
}
upstream puma_myapp {
server unix:/var/www/myapp/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name あなたのVultrサーバーのIPアドレス;
root /var/www/myapp/current/public;
try_files $uri/index.html $uri @puma_myapp_production;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 @503;
location @puma_myapp_production {
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-Proto http;
proxy_pass http://puma_myapp_production;
# limit_req zone=one;
access_log /var/www/myapp/shared/log/nginx.access.log;
error_log /var/www/myapp/shared/log/nginx.error.log;
# Basic認証
auth_basic "Restricted"; <=テスト用のサーバーなのでBasic認証を付けた
auth_basic_user_file /etc/nginx/sites-available/.htpasswd; <=テスト用のサーバーなのでBasic認証を付けた
}
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location = /50x.html {
root html;
}
location = /404.html {
root html;
}
location @503 {
error_page 405 = /system/maintenance.html;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html break;
}
rewrite ^(.*)$ /503.html break;
}
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
return 405;
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
}
nginx設定のチェックと読み込み
nginxについては解説記事がたくさんあるのであまり細かくは書きません。
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
起動
$ sudo nginx
停止
$ sudo nginx -s stop
設定の再読み込み
$ sudo nginx -s reload
Basic認証
$ sudo htpasswd -c /etc/nginx/sites-available/.htpasswd username
New password: password
Re-type new password: password
Adding password for user username
pumaの操作
起動
$ bundle exec cap production puma:start
停止
$ bundle exec cap production puma:stop
状態確認
$ bundle exec cap production puma:status
ブラウザで確認
参考記事
How to Install MySQL 8.0 on CentOS 8 / RHEL 8
CentOSに最新版のGitをインストール・アップデートする方法
CentOS 8にNginx stable最新版をインストール(公式repository)
新規Railsプロジェクトの作成手順まとめ
capistranoでいきなりgithubに繋がらなくなった時の話