ansibleを使った事ない僕がansibleつかってawsにRails + Nginx + Unicorn 環境をセットアップをしてみた(まさかの手動あり)


## 前提

AWSのインスタンス立ち上げ済み

## ansibleってみる

まずはinstall

```
brew install python
sudo easy_install pip
sudo pip install ansible
```

ansibleのひな形を取得

```
git clone https://github.com/morizyun/vagrant-ansible-rails

cd vagrant-ansible-rails
cp ./ansible/hosts_vagrant ./ansible/hosts_aws
```

./ansible/hosts_aws の内容を書き換える

```ruby:書き換え前
[app]
192.168.33.10 ansible_ssh_user=vagrant ansible_connection=ssh ansible_ssh_private_key_file=~/.ssh/id_rsa
```

```ruby:書き換え後(例)
[app]
(IP) ansible_ssh_user=ec2user ansible_connection=ssh ansible_ssh_private_key_file=(pemファイルのパス)
```

playbookの内容を書き換える

```ruby:書き換え前
---
- hosts: app
  sudo: true
  vars:
    hostname: server-production
    environtment: production
    ruby_version: 2.1.2
    rbenv_root: /home/vagrant/.rbenv
    rbenv_bin: /home/vagrant/.rbenv/libexec/rbenv
  roles:
    - common
    - rvm
    - nginx
    - mysql
    - rails
    #- troubleshooting
```

```ruby:書き換え後(例)
---
- hosts: app
  sudo: true
  vars:
    hostname: server-production
    environtment: production
    ruby_version: 2.1.2
    rbenv_root: /home/ec2-user/.rbenv
    rbenv_bin: /home/ec2-user/.rbenv/libexec/rbenv
  roles:
    - common
    - rvm
    - nginx
    - mysql
    - rails
    #- troubleshooting
```

nginxのパスやsslの設定を書き換える(下記の①、②)。

```ruby:ansible/roles/nginx/files/production/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log;

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" "$gzip_ratio"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip              on;
    gzip_http_version 1.0;
    gzip_types        text/plain
                      text/xml
                      text/css
                      application/xml
                      application/xhtml+xml
                      application/rss+xml
                      application/atom_xml
                      application/javascript
                      application/x-javascript
                      application/x-httpd-php;
    gzip_disable      "MSIE [1-6]\.";
    gzip_disable      "Mozilla/4";
    gzip_comp_level   1;
    gzip_proxied        any;
    gzip_vary           on;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    upstream backend {
        server 127.0.0.1:5001;
    }

    server {
        listen       80;
        server_name  DOMAIN_NAME;
        # root は自分の好きな場所に設定 ①
        root /home/ec2-user/apps/public;

        location ~* \.(ico|css|js|gif|jpg|jpeg|png|otf|svg|woff|eot|ttf)(\?[0-9]+)?$ {
            # only production
            expires 1y;
            break;
        }
    }

# ひとまず https は使わないのでコメントアウトしました。 ②
#   server {
#       listen 443 default ssl;
#       server_name  DOMAIN_NAME;
#       root /home/ec2-user/apps/public;
#
#       ssl on;
#       ssl_certificate /etc/nginx/ssl/cert.pem;
#       ssl_certificate_key /etc/nginx/ssl/server.key;
#
#       include           mime.types;
#       default_type      application/octet-stream;
#       sendfile          on;
#       keepalive_timeout 65;
#
#       location / {
#           client_max_body_size 20M;
#           rewrite ^\/ja(/.*)$ $1 permanent;
#           rewrite ^\/ja$ / permanent;
#           rewrite ^(.+[^/])/$ $1 permanent;
#           proxy_pass http://backend;
#           proxy_set_header X-Real-IP $remote_addr;
#           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#           proxy_set_header Host $http_host;
#           proxy_set_header X-Forwarded-Proto https;
#       }
#
#       satisfy any;
#   }

}
```


ansibleの実行を行う

```
export ANSIBLE_HOSTS=./ansible/hosts_aws
ansible-playbook ./ansible/playbook_production.yml
```


以上でサーバに環境がそろいました。

ここからは手動でunicornを入れていきます。
sshでログイン後、railsのインストールとアプリの作成をします。

```
rvmsudo gem install rails bundler --no-ri --no-rdoc
rails new apps --database=mysql
cd apps
```

Gemfileに下記を追加します

```
gem 'therubyracer', platforms: :ruby
gem 'unicorn'
```

bundle installしてDBを作ります。

```
bundle install
rake db:create
```

Unicornの設定を行います。`vim config/unicorn.rb`

```unicorn.rb
@app_path = '/home/ec2-user/apps'

worker_processes 2
working_directory "#{@app_path}/"

# This loads the application in the master process before forking
# worker processes
# Read more about it here:
# http://unicorn.bogomips.org/Unicorn/Configurator.html
preload_app true

timeout 30

# This is where we specify the socket.
# We will point the upstream Nginx module to this socket later on
listen "/tmp/unicorn.sock", :backlog => 64

pid "/tmp/unicorn.pid"

# Set the path of the log files inside the log folder of the testapp
stderr_path "#{@app_path}/log/unicorn.stderr.log"
stdout_path "#{@app_path}/log/unicorn.stdout.log"

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

  old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
        Process.kill(sig, File.read(old_pid).to_i)
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end

    sleep 1
  end

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

```

nginxのconfを触ります。

```/etc/nginx/conf.d/apps.conf
upstream unicorn_server {
    # This is the socket we configured in unicorn.rb
    server unix:/tmp/unicorn.sock
    fail_timeout=0;
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name _;

    keepalive_timeout 5;

    # Location of our static files
    root /home/ec2-user/apps/public;

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

        # If you don't find the filename in the static files
        # Then request it from the unicorn server
        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /home/ec2-user/apps/public;
    }
}

```

nginxの再起動とunicornの再起動をする

```
sudo /etc/init.d/nginx restart
unicorn_rails -c config/unicorn.rb -E development -D
```

以上で EC2インスタンスのipにアクセするとrailsアプリが動いている事が確認できると思います。

## 雑感
途中unicornあたりは本来であれば自分のRailsアプリごとgit cloneしてきてするなどして、
またnginxに継ぎ足したところなどももともとそう書いておけば完全自動化できそうです。
(今回の目的はあくまで使ってみる事にあったのでやりませんでしたが)

##参考
[Vagrant(CentOS6.5)にRails4.1 + Nginx + Unicorn + MySQL環境でRailsを起動する。](http://qiita.com/teitei_tk/items/74794983d9893c3e7a05#2-4)
[Vagrant/AWS + AnsibleでCentOS/Nginx/MySQL/RVM/Ruby2.1.2環境を構築](http://morizyun.github.io/blog/vagrant-ansible-rails-rvm-nginx-mysql/)
[Ansible の Playbook を使ってみる](http://d.hatena.ne.jp/akishin999/20130815/1376520672)