自作cookbooksは最小限にしてなるべくcommunity cookbookを使う方針で。
けっこうハマりました。特にNginx + Passengerあたりがcommunity cookbookではうまくいかず(rbenvだからいけなかったか?)、仕方なく自前でソースコードをコンパイルするレシピを書いたりした。
環境はMac 10.9 marvericksで。
お料理するよ!
Vagrant, Chef, knife-solo, Berkshelfなどのインストールは過去にやっているので参照されたし。
Vagrant
Vagrantで簡単にUbuntu 12.04を動かしてみるところまで。
Chef, knife-solo
CentOS 6.4でchef soloとknife soloを使ってphp実行環境を構築
berkshelfとpluginのインストール
$ gem install berkshelf $ vagrant plugin install vagrant-omnibus
vagrant-berkshelfはvagrantのエコシステムから外れてしまったらしく将来的にどうなるかわからないので使わずに行きます。
作業用ディレクトリを作成。
$ mkdir rails_chef $ cd rails_chef
Berksfileを準備します。
1 2 3 4 5 6 |
source "http://api.berkshelf.com" cookbook 'ruby_build' cookbook 'rbenv', github: "fnichol/chef-rbenv" cookbook 'iptables' cookbook 'vim' |
Vagrantfileを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "CentOS-6.5-x86_64-minimal" config.omnibus.chef_version = :latest config.vm.provision :chef_solo do |chef| chef.log_level = :debug chef.cookbooks_path = ["./berks-cookbooks", "./site-cookbooks" ] chef.json = { rbenv: { rubies: ["2.1.1"], global: "2.1.1" }, nginx_passenger: { nginx_ver: "1.6.0", passenger_ver: "4.0.42" } } chef.run_list = [ "vim", "ruby_build", "rbenv::system", "iptables", "rails_chef::nginx_passenger", "rails_chef" ] end # localhost:10080にアクセスするとゲストOSの80に転送させる config.vm.network :forwarded_port, host: 10080, guest: 80 # debugのためにwebrickの3000番もあけておく config.vm.network :forwarded_port, host: 13000, guest: 3000 # ssh-agentに登録されているキーをゲストOSからもそのまま使えるようにする config.ssh.forward_agent = true end |
ちなみに CentOS-6.5-x86_64-minimal という名前でbox addされている必要があります。boxは自由に変えていただければと思います。
berkshelfを使ってcommunity cookbookをダウンロードしておく。パスを指定しなければカレントディレクトリのberks-cookbooksにダウンロードされます。
$ berks vendor
以前はberks install –path /path/to/cookbooks だったんですが、新しいバージョンではエラーが出るようになってました。
あと、berks vendorで落としてきた場合、再度 berks vendor すると「既にディレクトリがあるよ!」って怒られるので、めんどうなんですが rm -rf berks-cookbooks してから berks vendor してました。こうじゃない感があるのですが正しいやり方が見つけられなかった。
自作のcookbookを作成するためにknifeでcookbook一式を生成します。自作cookbookはsite-cookbooks下に置くのが一般的。
$ knife cookbook create rails_chef -o site-cookbooks
iptables設定のためのテンプレートファイルと、自作レシピを書いて行きます。
site-cookbooks/rails-chef/recipes/default.rb
1 2 |
iptables_rule "ssh" iptables_rule "http" |
site-cookbooks/rails-chef/templates/default/http.erb
-A FWR -p tcp -m tcp --dport 80 -j ACCEPT
site-cookbooks/rails-chef/templates/default/ssh.erb
-A FWR -p tcp -m tcp --dport 443 -j ACCEPT
続いて、nginxとpassenger用のレシピ。こちらを参考にさせていただいた!
https://gist.github.com/philwo/3051666
site-cookbooks/rails-chef/recipes/nginx_passenger.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
%w{ curl-devel }.each do |pkg| package pkg end execute 'rbenv rehash' do command "rbenv rehash" end # passengerをインストール gem_package 'passenger' do version node['nginx_passenger']['passenger_ver'] end # nginxのソースコードをダウンロード remote_file 'download nginx' do action :create_if_missing owner 'root' group 'root' mode 0644 path "/tmp/nginx-#{node['nginx_passenger']['nginx_ver']}.tar.gz" source "http://nginx.org/download/nginx-#{node['nginx_passenger']['nginx_ver']}.tar.gz" end # nginxのソースコードを展開する execute 'extract nginx' do cwd '/tmp' command "tar xvfz /tmp/nginx-#{node['nginx_passenger']['nginx_ver']}.tar.gz" not_if do File.directory? "/tmp/nginx-#{node['nginx_passenger']['nginx_ver']}" end end # passenger-install-nginx-moduleコマンドを使用してnginxをビルドする execute 'build nginx' do command "passenger-install-nginx-module" << " --auto" << " --prefix=/usr/local/nginx" << " --nginx-source-dir=/tmp/nginx-#{node['nginx_passenger']['nginx_ver']}" << " --extra-configure-flags=--with-http_ssl_module" not_if do File.exists?("/usr/local/nginx") end end # nginx設定ファイル用ディレクトリへのシンボリックリンクを作成 link "/etc/nginx" do to "/usr/local/nginx/conf" end # nginxの共通confファイルを配置 cookbook_file "/etc/nginx/nginx.conf" do source "nginx.conf" end # アプリケーション個別の設定ファイル格納ディレクトリを作成 directory "/etc/nginx/conf.d" do owner "root" group "root" end # アプリケーション個別のconfファイルを配置 cookbook_file "/etc/nginx/conf.d/sample_rails.conf" do source "sample_rails.conf" notifies :restart, "service[nginx]" end # 起動スクリプトを設置 cookbook_file "/etc/init.d/nginx" do source "nginx" mode 0755 not_if "ls /etc/init.d/nginx" notifies :run, "execute[chkconfig add nginx]" end # 自動起動設定 execute 'chkconfig add nginx' do action :nothing command "chkconfig --add nginx" notifies :run, "execute[chkconfig nginx on]" notifies :start, "service[nginx]" end execute 'chkconfig nginx on' do action :nothing command "chkconfig nginx on" end service "nginx" do action :nothing end |
設定ファイル類はあらかじめfilesに用意しておく。今回は決めうちでやってしまったが、この辺は汎用性を高めた方がよい気がする。
nginx共通設定ファイル
site-cookbooks/rails-chef/files/default/nginx.conf
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { passenger_root /usr/local/rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/passenger-4.0.42; passenger_ruby /usr/local/rbenv/versions/2.1.1/bin/ruby; include 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"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
railsアプリケーションの設定ファイル
site-cookbooks/rails-chef/files/default/sample_rails.conf
server { listen 80; server_name localhost; location / { root /var/www/sample_rails/public; index index.html index.htm; passenger_enabled on; } }
nginxの起動スクリプト
site-cookbooks/rails-chef/files/default/nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
#!/bin/sh # # nginx - this script starts and stops the nginx daemon # # chkconfig: - 85 15 # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ # proxy and IMAP/POP3 proxy server # processname: nginx # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/local/nginx/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf" lockfile=/usr/local/nginx/logs/nginx.lock start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { configtest || return $? stop sleep 1 start } reload() { configtest || return $? echo -n $"Reloading $prog: " killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac |
起動スクリプトはこちらを参考にさせていただいた。
http://www.happytrap.jp/blogs/2012/02/23/8243/
ソースコード取得はcapistranoでやる予定なので、今回は手作業でやってしまえ。ごめんなさい。
$ sudo mkdir /var/www $ cd /var/www $ git clone GIT_REPOSITORY_URL
git cloneするとき、githubなどを使う場合は公開鍵認証が必要になるので、ssh-agentに鍵登録して、Vagrantfileで config.ssh.forward_agent = true の設定をしておくと楽。ゲストOS側で鍵の設定がいらないです。
あとは gem install bundler, bundle installなどなどRailsに関わる操作を行いますが、そこらへんは割愛しちゃいますね。
最後に
自作cookbookにcommity cookbookに依存するレシピを書いてしまっていたり、アプリケーション個別のレシピがnginx_passengerのレシピに入っていたり、ちょっと保守性アレでイケてないのでのちのち改善していきたい。
今回のブログを書くために書いたものはGithubにアップしてます。十分に検証出来てませんが、少しでも参考になれば幸い。
https://github.com/harada4atsushi/rails_chef
原田 敦
最新記事 by 原田 敦 (全て見る)
- AWS S3のCLI(コマンドラインインターフェース)を試してみる - 2014年7月1日
- RailsのActive SupportのHash拡張をいくつか試してみた - 2014年6月15日
- CentOS6.5にWeb Application Firewallのmod_securityを入れてみる - 2014年6月3日