odeの開発メモ日記

プログラマーやってます。今までの道のり ポケコンbasic→C(DirectX5 ネットやろうぜ)→Perl(ちょろっと)→Java→C#→Ruby→Android(Java)

capistranoでssh越しのサーバーに設置する場合

sshgatewayに接続した後、そこを踏み台として他のpc(Webサーバー,DBサーバー等)に繋いで作業する場合があると思います。
(設置先が自社サーバーではなく、外部のサーバーを使う場合やレンタルサーバー等で仮想環境を使用している場合等でしょうか)


capistranoのデフォルトでは直接接続できるサーバーを対象にしてますが、設定することで上記のようなssh越しの設置も可能です。

やり方

下記の2つのオプションを指定ですればOKです。

deploy.rb

# sshのgateway(踏み台)のIPを指定
set :gateway, "203.182.58.106"

# ファイルの転送にsvnでなく、ファイルコピーを使用する。大抵はssh越しのサーバーから開発のsvnは参照できないため。
set :deploy_via, :copy

注意点

  • gatewayになるサーバーと奥にある設置対象サーバーとでパスワードは同じにしなければならない。
  • idは基本一緒がいいが、一応変えられる。
    • ipの前に@で区切りでユーザー名を付けれる。
    • set :gateway, "root@203.182.58.106"
調査メモ

各サーバーごとに個別にパスワードを設定したいのでいろいろ調べたんですが最終的にソース見た限りできなそうでした。
(パスワードはそろえる方向で運用さんにお願いして解決しました。)

  • パスワードは設定ファイルのoptions[:password]を使っていた。
  • options[:password]が空の場合は入力プロンプトを表示して入力させるが、その値を保存して次に使用しているために違うサーバーでも同じパスワードが使用されてしまう。


cli/options.rb

        password = options.has_key?(:password)
        options[:password] = Proc.new { self.class.password_prompt } #パスワード入力を受け付けるProcを作成
        options[:password] = options[:password].call if password # このpassword変数は設定ファイルのではなく、コマンドラインの引数で -p, --passwordが指定された場合のもの

capistrano/ssh.rb

      password_value = nil

   ・・・・

      begin
        connection_options = ssh_options.merge(
          :password => password_value,
          :auth_methods => ssh_options[:auth_methods] || methods.shift
        )

        yield host, user, connection_options
      rescue Net::SSH::AuthenticationFailed
        raise if methods.empty? || ssh_options[:auth_methods]
        password_value = options[:password] #←ここで何故かパスワード入力Procが発動する。そんな発動の仕方あるの?Rubyの黒魔術でもあるのかな?
        retry
      end
    end

実行環境

rails(2.1.2)
capistrano (2.5.5)