ChefでCentOS 6.7 + nginxを設置する。- 外部クックブック


## 関連記事

* [Chefを使ってより効率的にサーバを管理しよう。まずは用語から](http://qiita.com/park-jh/items/9e2e358d2e82a7736cf7)
* [Berkshelfを使って外部クックブックをノードに適用する。](http://qiita.com/park-jh/items/751464a4cc6d8abcd6fd)
* [クックブックを作成してノードに適用する。- その１](http://qiita.com/park-jh/items/8d641809850b5930d39c)
* [クックブックを作成してノードに適用する。- その２](http://qiita.com/park-jh/items/88237342cfd202e6893f)
* [ChefでCentOS 6.7 + rbenv + ruby 2.3.0の環境を構築する。](http://qiita.com/park-jh/items/f249a18793899f2eb4bf)
* [ChefでCentOS 6.7 + Vim 7.4 + luaを設置する。](http://qiita.com/park-jh/items/371d179d5e71618a1f14)
* [ChefでVimプラグインマネージャーNeoBundleを設置する。](http://qiita.com/park-jh/items/ec09e40f9b4aaf9fedfd)
* [Chefのレシピをデバッグしてみよう。](http://qiita.com/park-jh/items/96a076e167327a6a5a39)
* ChefでCentOS 6.7 + nginxを設置する。- 外部クックブック
* [ChefでCentOS 6.7 + nginxを設置する。- カスタムクックブック](http://qiita.com/park-jh/items/43451cea21ee1724c24b)
* [ChefでCentOS 6.7 + nodejs + npmを設置する。](http://qiita.com/park-jh/items/96089e7e1c97b0fe3a6c)
* [ChefでVimプラグインマネージャーvim-plugを設置する。](http://qiita.com/park-jh/items/ba27ad412ce9926fd94d)
* [ohaiのカスタムプラグインを作ってみよう。](http://qiita.com/park-jh/items/34be55abb7c63b36cddb)
* [Chef SoloからChef Zeroへ](http://qiita.com/park-jh/items/44c249c9de768c53b423)
* [Chefでnginx + php(php-fpm) + mariadb + wordpressを設置する。](http://qiita.com/park-jh/items/7515e47dddc38257a454)

## nginxをtarballでインストール

* apacheとは違ってnginxのmoduleはコンパイルするとき指定しないとダメだ。
* そういうわけでyumで設置するよりtarballで設置することを推奨する。

### クックブックの生成

* 外部クックブックを使うかカスタムクックブックを使うかはケースバイケースだと思う。
* しかし、他の人が作ったクックブックがどんなふうになっているのか覗くのも確かに勉強になる。
* まずはChef社のSupermarketから公開されている外部クックブックを調べることを推奨する。
* それで十分だという判断であれば新しいクックブックを作成する必要はないだろう。
* それが不十分であればそのとき作成しても遅くはない。
* https://supermarket.chef.io/cookbooks/nginx
* Berkshelfにnginxというクックブックを取得するために追加する。

```sh
% vi Berkshelf

... snip ...

cookbook 'nginx'
```

* クックブックを保持する。

```sh
% bin/berks vendor cookbooks
```

### クックブックの構成

```sh
nginx
├── CHANGELOG.md
├── README.md
├── attributes
│   ├── auth_request.rb
│   ├── default.rb
│   ├── devel.rb
│   ├── echo.rb
│   ├── geoip.rb
│   ├── headers_more.rb
│   ├── lua.rb
│   ├── naxsi.rb
│   ├── openssl_source.rb
│   ├── pagespeed.rb
│   ├── passenger.rb
│   ├── rate_limiting.rb
│   ├── repo.rb
│   ├── set_misc.rb
│   ├── socketproxy.rb
│   ├── source.rb
│   ├── status.rb
│   ├── syslog.rb
│   └── upload_progress.rb
├── definitions
│   └── nginx_site.rb
├── files
│   └── default
│       ├── mime.types
│       └── naxsi_core.rules
├── libraries
│   └── matchers.rb
├── metadata.json
├── recipes
│   ├── authorized_ips.rb
│   ├── commons.rb
│   ├── commons_conf.rb
│   ├── commons_dir.rb
│   ├── commons_script.rb
│   ├── default.rb
│   ├── headers_more_module.rb
│   ├── http_auth_request_module.rb
│   ├── http_echo_module.rb
│   ├── http_geoip_module.rb
│   ├── http_gzip_static_module.rb
│   ├── http_mp4_module.rb
│   ├── http_perl_module.rb
│   ├── http_realip_module.rb
│   ├── http_spdy_module.rb
│   ├── http_ssl_module.rb
│   ├── http_stub_status_module.rb
│   ├── ipv6.rb
│   ├── lua.rb
│   ├── naxsi_module.rb
│   ├── ngx_devel_module.rb
│   ├── ngx_lua_module.rb
│   ├── ohai_plugin.rb
│   ├── openssl_source.rb
│   ├── package.rb
│   ├── pagespeed_module.rb
│   ├── passenger.rb
│   ├── repo.rb
│   ├── repo_passenger.rb
│   ├── set_misc.rb
│   ├── socketproxy.rb
│   ├── source.rb
│   ├── syslog_module.rb
│   └── upload_progress_module.rb
└── templates
    ├── debian
    │   └── nginx.init.erb
    ├── default
    │   ├── default-site.erb
    │   ├── modules
    │   ├── nginx-upstart.conf.erb
    │   ├── nginx.conf.erb
    │   ├── nginx.init.erb
    │   ├── nginx.pill.erb
    │   ├── nginx.sysconfig.erb
    │   ├── nxdissite.erb
    │   ├── nxensite.erb
    │   ├── plugins
    │   ├── sv-nginx-log-run.erb
    │   └── sv-nginx-run.erb
    ├── gentoo
    │   └── nginx.init.erb
    ├── suse
    │   └── nginx.init.erb
    └── ubuntu
        └── nginx.init.erb
```

* ファイル名だけでもいろんなことがわかる。
* attributesディレクトリの中にsource.rbが存在する場合大体はtarballで設置ができる。
* attributes/default.rbの中にinstall_methodと言う項目があり、そこからpackageで設置するかsourceで設置するか決めるようになっている。
* 今度はsourceで設置するので肝心のところであるattributes/source.rbを調べてみる。

```ruby
include_attribute 'nginx::default'

default['nginx']['source']['version']                 = node['nginx']['version']
default['nginx']['source']['prefix']                  = "/opt/nginx-#{node['nginx']['source']['version']}"
default['nginx']['source']['conf_path']               = "#{node['nginx']['dir']}/nginx.conf"
default['nginx']['source']['sbin_path']               = "#{node['nginx']['source']['prefix']}/sbin/nginx"
default['nginx']['source']['default_configure_flags'] = %W(
  --prefix=#{node['nginx']['source']['prefix']}
  --conf-path=#{node['nginx']['dir']}/nginx.conf
  --sbin-path=#{node['nginx']['source']['sbin_path']}
)

default['nginx']['configure_flags']    = []
default['nginx']['source']['version']  = node['nginx']['version']
default['nginx']['source']['url']      = "http://nginx.org/download/nginx-#{node['nginx']['source']['version']}.tar.gz"
default['nginx']['source']['checksum'] = 'b5608c2959d3e7ad09b20fc8f9e5bd4bc87b3bc8ba5936a513c04ed8f1391a18'
default['nginx']['source']['modules']  = %w(
  nginx::http_ssl_module
  nginx::http_gzip_static_module
)
default['nginx']['source']['use_existing_user'] = false
```

* versionを指定するようになっている。
* prefixが/optになっている。/usr/localではない。nginxのように規模が大きいアプリケーションの場合は/optの以下に設置する。[参考](http://www.itmedia.co.jp/help/howto/linux/0007master/14/04.html)
* urlとchecksumを記入するようになっている。
* modulesでsourceで設置するときのmoduleを定義することができる。
* これだけでもよく出来上がったクックブックだということがわかるだろう。

## Attributeについて

* Attributeが書けるファイルはattribute、recipe、environment、roleである。
* 優先順位は （低い）attribute ＞ recipe ＞ environment ＞ role（高い）である。
* 今まではクックブックの中のattributes/default.rbとenvironments/development.jsonにattributeを指定して使っていた。
* 自分なりにattributeの書き方を考えてみた。
  - 該当レシピだけが使えそうなattributeはクックブックの中のattributeに書く。
  - 環境別に異なるattributeはenvironmentsに書く。
  - 役割別に定める必要があるattributeはroleに書く。
* nginxはWebサーバなので、webという役割を持ってるroleに書くのが正しい。

## roleについて

### roleを生成する。

* roleを生成してnginxのattributeを上書きしよう。

```sh
% bin/knife role create web -z

{
  "name": "web",
  "override_attributes": {
    "nginx": {
      "install_method": "source",
      "source": {
        "version": "1.8.1",
        "checksum": "8f4b3c630966c044ec72715754334d1fdf741caa1d5795fb4646c27d09f797b7",
        "modules": [
          "nginx::http_ssl_module",
          "nginx::http_stub_status_module",
          "nginx::http_gzip_static_module",
          "nginx::http_mp4_module"
        ]
      }
    }
  },
  "run_list": [
    "recipe[nginx]"
  ]
}
```

* 現在安定化されているnginxの最新バージョンは1.8.1である。（2016年3月）
* nginxの本家ではファイルの検証方法としてchecksumではないpgpを提供している。
* 1.8.1をダウンロードしてchecksumを作り出す。

```sh
% wget http://nginx.org/download/nginx-1.8.1.tar.gz
% shasum -a 256 nginx-1.8.1.tar.gz
```

### roleを追加する。

```sh
% bin/knife node run_list add dev "role[web]" -z
```

### クックブックをノードへ転送して実行させる。

```sh
% bin/knife solo cook dev -E development
```

### ノード上で確認する。

```sh
$ ps aux | grep nginx
root      7752  0.0  0.1  44628  1180 ?        Ss   08:41   0:00 nginx: master process /opt/nginx-1.8.1/sbin/nginx
nginx     7754  0.0  0.1  44984  1772 ?        S    08:41   0:00 nginx: worker process
vagrant   7912  0.0  0.0 103320   912 pts/0    S+   14:00   0:00 grep nginx

$ /opt/nginx-1.8.1/sbin/nginx -V
nginx version: nginx/1.8.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/opt/nginx-1.8.1 --conf-path=/etc/nginx/nginx.conf --sbin-path=/opt/nginx-1.8.1/sbin/nginx --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_mp4_module
```

## 参考

* http://dev.classmethod.jp/server-side/chef/attribute-overrides-pattern/ 
* Chef活用ガイド
* Chef実践入門