hiroki-saoyun’s blog

40歳でも夢くらい持つよね!!プログラミング勉強中!

S3を使ってアップロード①

セキュリティ対策

セキュリティ対策① 二段階認証

Authyを使用します。

Authyは二段階認証のためのアプリです。

最初にAuthyをインストールします。

iOS

https://itunes.apple.com/jp/app/authy/id494168017?mt=8&uo=4&at=10lMo4

Android

https://play.google.com/store/apps/details?id=com.authy.authy

初期設定をします。

電話番号とメールアドレスを登録します。

ここで登録した番号にSMSで確認コードがくるので、スマホの電話番号を登録します。

codeは+81 (Japan)

最初の0を抜いた自分のスマホの電話番号です。

登録後に"GET ACCOUNT VERIFICATION VIA"のメッセージが表示されるので、確認コード送付方法としてSMSを選択します。

届いた確認コードをAuthyに入力したら、初期設定が完了です。

続いてAWSでの二段階認証設定を行います。

ヘッダー部分のアカウント名をクリックして、「マイセキュリティ資格情報」→「Continue to Security Credentials」→「多要素認証(MFA)」→「「MFAの有効化」をクリックします。

モーダル画面の中から「仮想MFAデバイス」が選択されているのを確認して、続行をクリックします。

次の画面で「QRコードの表示」をクリックします。

スマホでAuthyを開きます。そしてAuthyにAWSアカウントを追加していきます。

「Accounts」を選択して「+」ボタンをタップします。

先ほどのQRコードを読み取ります。

設定画面を終了すると、二段階認証用のパスワードが表示されるようになります。

このパスワードをAWSで入力します。

MFAコードってところにパスワードを入力します。(二箇所あるよ)

1つ目のパスワードを上の欄に、そのパスワードの次に表示されたパスワードを下の欄に入力します。

最後に「MFA」の割り当てをクリックして設定は完了です。

自動デプロイ設定

Capistranoを利用した自動デプロイ

Capistranoとは

自動デプロイツールの一種です。 Capistranoを利用すれば、サーバにログインする事なく、

ローカルのターミナルからデプロイを完了することができます。

Capistranoの導入

Gemをインストールします。

Gemfile

group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

ターミナル(ローカル)

bundle install

bundle exec cap install
# ファイルが生成されます。

Capfileを編集

Capfileは、capistrano全体の設定ファイルです。

Capfile

require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

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

require により引数としておかれた文字列が指すディレクトリが読み込まれます。

デプロイについての設定ファイルの編集

config/deploy/production.rb

server '用意したElastic IP', user: 'ec2-user', roles: %w{app db web}

config/deploy.rb

deploy.rbの記述をすべて削除し、以下のコードを貼り付けます。

# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<Capistranoのバージョン>'

# Capistranoのログの表示に利用する
set :application, '<自身のアプリケーション名>'

# どのリポジトリからアプリをpullするかを指定する
set :repo_url,  'git@github.com:<Githubのユーザー名>/<レポジトリ名>.git'

# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '<このアプリで使用しているrubyのバージョン>' #カリキュラム通りに進めた場合、2.5.1か2.3.1です

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス(例:~/.ssh/key_pem.pem)>'] 

# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end

unicorn.rbの記述を編集

config/unicorn.rb

app_path = File.expand_path('../../', __FILE__)

worker_processes 1

working_directory app_path
pid "#{app_path}/tmp/pids/unicorn.pid"
listen "#{app_path}/tmp/sockets/unicorn.sock"
stderr_path "#{app_path}/log/unicorn.stderr.log"
stdout_path "#{app_path}/log/unicorn.stdout.log"

config/unicorn.rb

# ../が一つ増えている
app_path = File.expand_path('../../../', __FILE__)

worker_processes 1
# currentを指定
working_directory "#{app_path}/current"

# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"

Nginxの設定ファイルの記述を編集

ターミナル(EC2)

$ sudo vim /etc/nginx/conf.d/rails.conf

rails.conf

upstream app_server {
  server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入>;

# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

  root /var/www/<アプリケーション名>/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

上のコードをいったん削除します。

rails.conf

upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入>;

# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

  # currentの中を参照するよう変更
  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更
    root   /var/www/<アプリケーション名>/current/public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

上記のように変更します。

ターミナル(EC2)

[ec2-user@ip-Elastic IP ~]$ sudo service nginx reload
[ec2-user@ip-Elastic IP ~]$ sudo service nginx restart

Nginxの設定を変更したら、再読込・再起動をします。

MySQLの起動

[ec2-user@ip-Elastic IP ~]$ sudo service mysqld restart

unicornのプロセスをkill

[ec2-user@ip-Elastic IP  リポジトリ名]$ ps aux | grep unicorn
ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

プロセスをkillします。

ターミナル(EC2)

[ec2-user@ip-Elastic IP  リポジトリ名]$ kill 確認したunicorn rails masterのPID

ローカルでの修正をmasterにpushします。

自動デプロイを実行

ターミナル(ローカル)

$ bundle exec cap production deploy
# アプリケーションのディレクトリで実行です。

エラーが表示されずに完了したら自動デプロイは完了です。

個人アプリ・ビュー作成

とりあえず必要なビューは作成することができたので、その時調べた事とかを書いていきます。

textarea タグを使ってテキスト入力欄作成

最終課題の時に使って、今回も実装したいと考えていたので使用しました。

textarea タグとは

複数行の入力が可能な入力欄を作成するためのタグです。

f:id:hiroki-saoyun:20200601205644p:plain

こんなやつです。

今は表示だけしたかったので、

HAML

%textarea.new-body__content-recipe{cols: "60", rows: "6", placeholder: "料理の作り方 (必須 1,000文字以内)"}

こんな感じにしています。

本題

このタグを実装するにあたり、一番書いておきたかったことを書いておきます。

それはエリアのサイズの固定です。

SCSS

.new-body__content-recipe {
   border: 1px solid #ccc;
   border-radius: 4px;
   outline: none;
   display: block;
   width: 100%;
   margin-top: 15px;
   padding: 13px 16px;
   resize: vertical;
        }

前にやったのにまったく覚えていなかったので、絶対書いとかねばと。。

resize: vertical;

これで横方向の拡大を禁止しています。

他にも縦とか拡大・縮小を禁止することもできるみたいです。

縦
resize: horizontal;
拡大・縮小
resize: none;

本番環境でRailsを起動させるときに起きたエラーについて

本番環境でRailsを起動させようとした時に、

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

というエラーが出たので、解決した方法を書いて起きます。

解決した方法

ターミナル(EC2)

$ cd  /var/www/アプリ名

$ sudo shutdown -r now

EC2サーバをストップさせて、ログインし直しました。

エラー内容

/tmp/mysql.sock’というソケットでMySQLに接続できなかった。

みたいなエラーだと思っています。

試したこと

MySQLが欲しがってるパスをRails側に持たせてあげると

解決するみたいな記事を見つけたので、

それに関係すると思われることを片っ端から試しました。

最後に

調べ方に問題はあるとは思うのですが、

検索するたびにそんな内容の記事が出てきていたので、

それで解決できるんだ!!と決めつけていました。。

 

AWSのEC2を使ってサーバーを作成⑧

ポートを解放

立ち上げたばかりのEC2インスタンスSSHでアクセスすることはできますが、HTTPなどではつながらないようになっています。

なので、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるようにポートを開放する必要があります。

AWS マネジメントコンソール →EC2 →「インスタンス」→対象のインスタンスを選択します。

次に「セキュリティグループ」のリンクをクリックします。

「インバウンド」→「編集」→「ルールの追加」、タイプを「カスタムTCPルール」、プロトコルを「TCP」、ポート範囲を「3000」、送信元を「カスタム」「0.0.0.0/0」に設定します。

Railsを起動

config/database.yml(ローカル)

production:
  <<: *default
  database: アプリ名_production
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

GitHubにプッシュします。

ターミナル(EC2)

[ec2-user@ip-自分のElastic IP リポジトリ名] $ git pull origin master

ターミナル(EC2)

$ rails db:create RAILS_ENV=production
$ rails db:migrate RAILS_ENV=production

ターミナル(EC2)

$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

Railsを起動します。

アセットファイルをコンパイル

ターミナル(EC2)

$ rails assets:precompile RAILS_ENV=production

Unicornのプロセスを確認

ターミナル(EC2)

$ ps aux | grep unicorn

UnicornのプロセスをKill

ターミナル(EC2)

$ kill <確認したunicorn rails masterのPID>

再びunicornを起動

ターミナル(EC2)

$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

ブラウザで確認

http://Elastic IP:3000/でアクセスします。

これで問題なく表示されたら大丈夫です。

AWSのEC2を使ってサーバーを作成⑦

環境変数の設定

環境変数は、Railsからは ENV['環境変数名'] という記述でその値を利用することができます。

ターミナル(EC2)

$ cd  /var/www/アプリ名
$ rake secret

長い英数の羅列が表示されます。

あとで利用するのでコピーしておきます。

ターミナル(EC2)

$ cd
$ sudo vim /etc/environment

iと打ち込んで入力モードに切り替えます。

/etc/environment

DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
#先ほど設定したパスワードです。
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

書き込みができたら 「esc」→ :wqと入力して内容を保存します。

そして、もう一度本番環境へログインします。

次に環境変数が適用されているか確認します。

ターミナル(EC2)

$ env | grep SECRET_KEY_BASE
$ env | grep DATABASE_PASSWORD

AWSのEC2を使ってサーバーを作成⑥

Githubからコードをクローン

Unicornの設定を済ませたコードをEC2インスタンスにクローンします。

ターミナル(EC2)

#mkdirコマンドで新たにディレクトリを作成します
$ sudo mkdir /var/www/
#作成したwwwディレクトリの権限をec2-userに変更します
$ sudo chown ec2-user /var/www/

Githubから「リポジトリURL」を取得

「clone or download」をクリックして、URLをコピーします。

コードをクローン

ターミナル(EC2)

$ cd /var/www/
$ git clone https://github.com/ユーザー名/リポジトリ名.git

Swap領域を用意

ターミナル(EC2)

$ cd
$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
$ sudo chmod 600 /swapfile1
$ sudo mkswap /swapfile1
$ sudo swapon /swapfile1
$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

順番に実行していきます。

gemをインストール

ターミナル(EC2)

$ cd /var/www/
$ cd  /var/www/アプリ名
$ ruby -v

ターミナル(ローカル)

$ bundler -v
#バージョンの確認です

ターミナル(EC2)

$ gem install bundler -v 2.0.2
#確認したバージョンを導入です
$ bundle install