これで動いた!さくらのVPS+github+capistranoでrailsアプリ自動デプロイの設定ファイルを置いておく
ローカルPC→さくらVPS→githubという感じで、一回設定したらあとは全部ローカルで作業が完結するというラクラク設定。
公開鍵認証の設定とかgithubの設定とかnginxのインストールとかそういうのは抜きでスクリプト群のみをメモ代わりに置いておく。
Gemfile抜粋
group :assets do gem 'sass-rails', '3.2.5' gem 'coffee-rails', '3.2.2' gem 'therubyracer' gem 'libv8', '~> 3.11.8' gem 'uglifier', '1.2.3' end gem 'jquery-rails', '2.1.4' # Use unicorn as the app server gem 'unicorn' group :deployment do gem 'capistrano' gem 'capistrano_colors' gem 'capistrano-ext' gem 'capistrano_rsync_with_remote_cache' end
therubyracerとかlibv8とかuglifierがないとasset compileができない。最初のbundle install時はlibv8ですごい時間がかかる(さくらのVPS 2Gで10分くらい?)けど焦ってはいけない。
Gemfile以外の以下のファイルは全部#{application_root}/configの下にぶっこんでおく
nginx.conf
upstream your-app-name { server unix:/var/www/your-app-name/shared/unicorn.sock; } server { listen 80; server_name your-app-name; root /var/www/your-app-name/public; access_log /var/www/your-app-name/current/log/access.log; error_log /var/www/your-app-name/current/log/error.log; location ~ ^(/assets/|/audios/) { gzip_static on; root /var/www/your-app-name/current/public; expires 1y; add_header Cache-Control public; add_header ETag ""; break; } location / { if (-f $request_filename) { break; } # ファイルが存在しなければunicornにproxyする 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_pass http://your-app-name; } }
/etc/nginx/conf.d/に置いておく
unicorn.rb
proj_root_dir = File.expand_path("../../../", __FILE__) shared_path = "#{proj_root_dir}/shared" worker_processes 4 timeout 30 preload_app true listen "#{shared_path}/unicorn.sock" pid "#{shared_path}/pids/unicorn.pid" stderr_path "#{shared_path}/log/unicorn.log" stdout_path "#{shared_path}/log/unicorn.log"
とくにコメント無し。
unicorn_init.sh
#!/bin/sh set -e # Feel free to change any of the following variables for your app: TIMEOUT=${TIMEOUT-60} ROOT=/var/www/your-app-name APP_ROOT=$ROOT/current PID=$ROOT/shared/pids/unicorn.pid CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production" AS_USER=your_linux_user set -u OLD_PIN="$PID.oldbin" sig () { test -s "$PID" && kill -$1 `cat $PID` } oldsig () { test -s $OLD_PIN && kill -$1 `cat $OLD_PIN` } run () { if [ "$(id -un)" = "$AS_USER" ]; then eval $1 else su -c "$1" - $AS_USER fi } case "$1" in start) sig 0 && echo >&2 "Already running" && exit 0 run "$CMD" ;; stop) sig QUIT && exit 0 echo >&2 "Not running" ;; force-stop) sig TERM && exit 0 echo >&2 "Not running" ;; restart|reload) sig HUP && echo reloaded OK && exit 0 echo >&2 "Couldn't reload, starting '$CMD' instead" run "$CMD" ;; upgrade) if sig USR2 && sleep 2 && sig 0 && oldsig QUIT then n=$TIMEOUT while test -s $OLD_PIN && test $n -ge 0 do printf '.' && sleep 1 && n=$(( $n - 1 )) done echo if test $n -lt 0 && test -s $OLD_PIN then echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds" exit 1 fi exit 0 fi echo >&2 "Couldn't upgrade, starting '$CMD' instead" run "$CMD" ;; reopen-logs) sig USR1 ;; *) echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>" exit 1 ;; esac
これもなし。っていうかアプリ名とかルートディレクトリが分散するのがイマイチだなぁ、と思っているので環境変数とかに設定して全部そこから読み込んで設定するようにしたらベターだと思っているし、そのうち挑戦しようと思ってる。しなさそうだけど。
require 'capistrano_colors' require "bundler/capistrano" server "your_host", :web, :app, :db, primary: true set :application, "your_app_name proj_root_dir = File.expand_path("../../../../", __FILE__) shared_path = "/var/www/#{application}/shared" set :user, "your_linux_user_id" set :deploy_to, "/var/www/#{application}" set :deploy_via, :remote_cache set :scm, :git set :repository, "git@github.com:your_github_user_id/#{application}.git" set :branch, "master" set :rails_env, "production" default_run_options[:pty] = true ssh_options[:port] = "your_ssh_port_number" ssh_options[:forward_agent] = true ssh_options[:keys] = [File.join(ENV["HOME"], ".ssh", "your_ssh_key")] # precompile load 'deploy/assets' after "deploy", "deploy:cleanup" # keep only the last 5 releases namespace :deploy do %w[start stop restart].each do |command| desc "#{command} unicorn server" task command, roles: :app, except: {no_release: true} do run "/etc/init.d/unicorn_#{application} #{command}" end end task :setup_config, roles: :app do sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/conf.d/#{application}.conf" sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}" run "mkdir -p #{shared_path}/config" # put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml" puts "Now edit the config files in #{shared_path}." end after "deploy:setup", "deploy:setup_config" #task :symlink_config, roles: :app do # run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" #end #after "deploy:finalize_update", "deploy:symlink_config" desc "Make sure local git is in sync with remote." task :check_revision, roles: :web do unless `git rev-parse HEAD` == `git rev-parse origin/master` puts "WARNING: HEAD is not the same as origin/master" puts "Run `git push` to sync changes." exit end end before "deploy", "deploy:check_revision" end
niginx.confとかを適当な名前にして適当なディレクトに配布する感じの処理が入ってる。何かデプロイ時にやりたい処理があればアクションごとにここに書けばいい。
最初だけサーバ側で/var/www/your-app-nameディレクトリ作って、運用ユーザー所有にしておき、あとは、ローカルのプロジェクトルートでcapifyしてcap deploy:setupしてcap deployすればOK。再起動とかはcap deploy:(stop|start|restart)で。やっべチョー楽。
あ、cap:setup時にどういうわけか/var/www/your-app-name以下にいくつかrootでディレクトリが作られちゃって、2〜3回所有者を設定し直す、ということをやったけど、1回やればもうやらなくていいので原因は調べてない。デプロイ時には鍵のパスフレーズを2〜3回打つことになるけど、それはそういうもんだと思うのでしょうがないと思う。
最初に書いたとおり、nginxのインストールとかmysqlのインストールとかgithubに公開鍵の登録とかVPSに秘密鍵の設置とか、インフラ周りでやっておくことはあるので、それは別途ググればいっぱいでてくると思います。