最小限でRailsをAWSにデプロイする。Ubuntu,Unicorn,Nginx,PostgreSQL

## この記事の対象となる人

- Railsはなんとかいじることができるようになった
- 本番へのデプロイ方法が皆目見当つかない
- Capistranoは使わなくてもよい
- Nginxが何かよくわからない
- Unicornが何だか全くわからない
- PostgreSQLを触って２日くらい
- インフラ怖い
- いったん独自ドメインじゃなくてIP直打ちでもよいから本番にデプロイしてみたい
- 素人の書いた記事を優しい気持ちで見守れる


## 前提というか事前準備


- ローカルでRailsのプロジェクトをつくってあってpushしてある
- AWSでインスタンス（Ubuntu）はあってsshできる 


ローカル開発環境で

```
rails new {project} -d postgresql
```

ぐらいまでして、Gemfileのunicornをコメントアウトして`git push`してある。

なので、本番環境で、以下ができる状態。

```
git clone git@github.com:mochizukikotaro/{project}.git
```

## 本題

掲題の構成でAWSへのデプロイを試みた際の、メモです！

### AWS

セキュリティグループに80は追加しておく。僕はこの設定をせずにコケまくって20分くらい彷徨った。

![スクリーンショット 2015-09-12 22.14.05.png](https://qiita-image-store.s3.amazonaws.com/0/45822/2aa12860-75f4-776c-6d34-f9447698868b.png)

### /var/www

AWSにSSHはできる、なんとかRailsを動かせるような設定はおこなった。git cloneしたい。けど、どこにcloneするのがよいのかわからない。見よう見まねで「/var/www」あたりが無難と見た。ちなみに、/var/wwwディレクトリなんて存在してなかったりするので作る。

```bash
ssh -i {hoge}.pem ubuntu@{IPアドレス}
sudo mkdir /var/www
sudo chown ubuntu /var/www    #なんで所有者変えるかはよく分かってない
cd /var/www
git clone git@github.com:mochizukikotaro/{project}.git
cd {project}
bundle update
bundle install
```

### PostgreSQLのユーザとパス

- ユーザ: {pg_user}
- パス: {pg_password}

```bash
sudo apt-get install -y postgresql libpq-dev
sudo -u postgres createuser -s {pg_user}
sudo -u postgres psql
postgres=# \password {pg_user}
=> 2回パスワードを入力する
=> {pg_password}
postgres=# \q
```

参考：[【荒すぎるメモ】PostgreSQLをVagrant,Ubuntu,Railsでつかってみる](http://qiita.com/mochizukikotaro/items/7d169640417ecf804f95)


### DATABASE_PASSWORD と SECRET_KEY_BASE の設定で困る。

```ruby:config/database.yml
production:
  <<: *default
  database: {project}_production
  username: {project}
  password: <%= ENV['{PROJECT}_DATABASE_PASSWORD'] %>
```

```ruby:config/secrets.yml
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
```

上記のようになっていて、これは環境変数に仕込めばよいらしい。が、それも幾通りかの方法があるらしく、とても困る。ここは強引に、.bashrcに環境変数を書いてしおうと思う。

```bash:.bashrc
echo 'export {PROJECT}_DATABASE_PASSWORD={pg_password}' >> ~/.bashrc
echo 'export SECRET_KEY_BASE={とりあえず適当に長めのランダム文字列}' >> ~/.bashrc
source ~/.bashrc
```

正直、こんなことをしてよいのか、とても不安です。全くわかりません。後で勉強して、良い方法を記載したいとおもいます。

### db:migrateしたい

```bash
cd /var/www/{project}
bundle exec rake db:create RAILS_ENV=production
bundle exec rake db:migrate RAILS_ENV=production

#ちなみにbin/rake db:migrateはできなくて１時間くらい彷徨いました。これも勉強して、記載したい。
```

これでなんとか本番用データベースができた。{project}_production.


### Unicorn

```bash
touch /var/www/{project}/config/unicorn.rb
```

```rb:config/unicorn.rb
@app_path = '/var/www/{project}'
working_directory @app_path

worker_processes 2
preload_app true
timeout 30
listen "/tmp/unicorn.sock", :backlog => 64
pid "/var/www/{project}/shared/tmp/pids/unicorn.pid"

stderr_path "#{@app_path}/log/unicorn.stderr.log"
stdout_path "#{@app_path}/log/unicorn.stdout.log"

before_fork do |server, worker|
  ENV['BUNDLE_GEMFILE'] = File.expand_path('Gemfile', ENV['RAILS_ROOT'])
end

before_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

after_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
  end
end
```

```bash
sudo mkdir -p /var/www/{project}/shared/tmp/pids
sudo chmod 777 /var/www/{project}/shared/tmp/pids
cd /var/www/{project}
bundle exec unicorn_rails -c config/unicorn.rb -p 8080 -D -E production    #起動
ps aux | grep unicorn    #動いているかの確認
kill -9 {pid}    #プロセスを切る
```

### Nginx

しまった、nginxのインストール方法忘れた。。

```
sudo apt-get install -y nginx
```

とかだと最新が入らないような気がするが、、気にしない。

```
touch /etc/nginx/conf.d/{project}.conf
```

```rb:{project}.conf
upstream unicorn_server {
    server unix:/tmp/unicorn.sock
    fail_timeout=0;
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name {IPアドレス};

    keepalive_timeout 5;

    # Location of our static files
    root /var/www/{project}/public;

    location ~ ^/assets/ {
        # 誤り) root /var/www/{project}/shared/public; 
        root /var/www/{project}/public; #修正後
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/{project}/public;
    }
}
```

```bash
sudo /etc/init.d/nginx start    #起動
```

## アクセス

あとは{IPアドレス}にアクセスをすれば、、僕はいけた。

それと、cssを本番でも効かせるために

```bash
cd /var/www/{project}
bundle exec rake assets:precompile RAILS_ENV=production
```

はしておく必要がある。その後のUnicornの再起動もしておいた方が良さそう。ちなみに、当初僕は上記の通りnginxの設定でassetsのパスを間違って書いていて、2時間くらい彷徨いました。/var/www/{project}/public/assetsにコンパイルされた奴はいるのですね。

ありがとうございました。