apache2.4のrecipeを書いてみた

windowsでchef使うの面倒くさいとかずっと思ってて使ってなかったけど、
というか、windowsにRubyをインストールしたくなくて使わなかったのだけど、
Heroku toolbeltをインストールしたらついでにRubyが入っちゃったので、これは神のお告げということにしてchefを早速使ってみた第一弾。

まずはnginxに押されていまいちぱっとしないapache2.4のrecipe。
いろんなブログとか公式サイトとか漁って何とか書いてみた。

##### 以下感想
confファイルをerbでテンプレート作って設定値を変数で割り当てられるのが嬉しい。
recipeにテンプレートに割り当てる変数書かなくても、どっか別のところに定義しておけるっぽい。
公式サイトのサンプルには`node[hoge][fuga]`みたいな感じで書いてたけど、何処で設定してるんだろ？
ソースからコンパイルしてインストールすると殆どshell書いてるような感覚、もっとカッコいいやり方あるような気がしているが調べてはいない。

もっと美味しそうなrecipeが作れるようになりたいです...

### recipe

```ruby:cookbooks/httpd/recipes/default.rb
#
# Cookbook Name:: httpd
# Recipe:: default
#
# Copyright 2013, k-motoyan
#

# sourceのインストールディレクトリ
install_dir = '/usr/local/src'

# インストールするソースの情報
source_info = {
  :apr => {
    :file_name  => 'apr-1.4.8.tar.gz',
    :file_dir   => 'apr-1.4.8',
    :configure  => './configure',
    :remote_uri => 'http://ftp.kddilabs.jp/infosystems/apache/apr/apr-1.4.8.tar.gz'
  },
  :apr_util => {
    :file_name  => 'apr-util-1.5.2.tar.gz',
    :file_dir   => 'apr-util-1.5.2',
    :configure  => './configure --with-apr=/usr/local/apr',
    :remote_uri => 'http://ftp.kddilabs.jp/infosystems/apache/apr/apr-util-1.5.2.tar.gz'
  },
  :httpd => {
    :file_name  => 'httpd-2.4.6.tar.gz',
    :file_dir   => 'httpd-2.4.6',
    :configure  => './configure --enable-modules=all --enable-ssl',
    :remote_uri => 'http://ftp.riken.jp/net/apache/httpd/httpd-2.4.6.tar.gz'
  }
}

# vhosts利用可否
use_vhosts = true

# 作成するvhostsの情報、複数登録可能
vhosts = {
  :sample => {
    :path          => '/usr/local/apache2/conf/extra/httpd-vhosts-sample.conf',
    :source        => 'httpd-vhosts-sample.conf.erb',
    :listen        => 80,
    :server_admin  => 'localhost@vhosts.com',
    :server_name   => 'vhosts',
    :document_root => '/var/www/vhosts',
    :log_directory => '/var/log/vhosts/',
    :error_log     => 'error_log',
    :access_log    => 'access_log common'
  }
}

%w(openssl-devel pcre-devel).each do |package_name|
  package "#{package_name}" do
    :install
  end
end

script 'register_httpd_to_service' do
  action :nothing
  only_if 'ls /usr/local/apache2/bin/apachectl'
  interpreter 'bash'
  user        'root'

  code <<-EOL
    cp /usr/local/apache2/bin/apachectl /etc/init.d/httpd
    echo "# chkconfig: 3 65 35" >> /etc/init.d/httpd
    echo "# description: Apache httpd Web server" >> /etc/init.d/httpd
    chkconfig --add httpd
  EOL
end

source_info.each do |key, info|
  remote_file "/tmp/#{info[:file_name]}" do
    source "#{info[:remote_uri]}"
  end

  script 'install_httpd' do
    not_if 'ls /etc/init.d/httpd'
    interpreter 'bash'
    user        'root'

    code <<-EOL
      install -d #{install_dir}
      tar xvfz /tmp/#{info[:file_name]} -C #{install_dir}
      cd #{install_dir}/#{info[:file_dir]} && #{info[:configure]} && make && make install
    EOL

    notifies :run, resources(:script => 'register_httpd_to_service')
  end
end

template '/usr/local/apache2/conf/httpd.conf' do
  only_if 'ls /usr/local/apache2/conf'
  owner 'root'
  mode 0644
  source 'httpd.conf.erb'

  variables ({
    :listen          => 80,
    :user            => 'apache',
    :group           => 'apache',
    :server_admin    => 'localhost@example.com',
    :server_name     => 'localhost',
    :document_root   => '/usr/local/apache2/htdocs',
    :directory_index => 'index.html',
    :use_vhosts      => use_vhosts,
  })
end

vhosts.each do |key, vhost|
  template "#{vhost[:path]}" do
    only_if 'ls /usr/local/apache2/conf/extra'
    owner 'root'
    mode 0644
    source vhost[:source]

    variables ({
      :listen        => vhost[:listen],
      :server_admin  => vhost[:server_admin],
      :server_name   => vhost[:server_name],
      :document_root => vhost[:document_root],
      :error_log     => "#{vhost[:log_directory]}#{vhost[:error_log]}",
      :access_log    => "#{vhost[:log_directory]}#{vhost[:access_log]}"
    })
  end

  script 'make_document_root' do
    not_if "ls #{vhost[:document_root]}"
    interpreter 'bash'
    user        'root'
    code <<-EOL
      mkdir -p #{vhost[:document_root]}
    EOL
  end

  script 'make_log_directory' do
    not_if "ls #{vhost[:log_directory]}"
    interpreter 'bash'
    user        'root'
    code <<-EOL
      mkdir -p #{vhost[:log_directory]}
    EOL
  end
end
```

### httpd.confのtemplate

```ruby:cookbooks/httpd/templates/default/httpd.conf.erb
ServerRoot "/usr/local/apache2"
Listen <%= @listen %>

<IfModule unixd_module>
User <%= @user %>
Group <%= @group %>
</IfModule>

ServerAdmin <%= @server_admin %>
ServerName <%= @server_name %>

<Directory />
    AllowOverride none
    Require all denied
</Directory>

DocumentRoot "<%= @document_root %>"
<Directory "<%= @document_root %>">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<IfModule dir_module>
    DirectoryIndex <%= @directory_index %>
</IfModule>

<Files ".ht*">
    Require all denied
</Files>

ErrorLog "logs/error_log"
LogLevel warn

<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    CustomLog "logs/access_log" common
</IfModule>

<IfModule mime_module>
    TypesConfig conf/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
</IfModule>

<% if @use_vhosts %>Include conf/extra/httpd-vhosts-*.conf<% end %>
```

### httpd-vhosts.confのtemplate
httpd-vhosts-*.confのファイル名の形式でrecipe中に指定しすれば複数作成される。

```ruby:cookbooks/httpd/templates/default/httpd-vhosts-sample.conf.erb
NameVirtualHost *:<%= @listen %>

<VirtualHost *:<%= @listen %>>
  ServerName <%= @server_name %>
  DocumentRoot <%= @document_root %>

  <Directory "<%= @document_root %>">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  ErrorLog <%= @error_log %>
  CustomLog <%= @access_log %> common
</VirtualHost>
```