リモートサーバにrailsアプリケーションをCapistranoでデプロイしようとしていました。
Capistranoによるデプロイの流れはザックリとこんな感じです。
- 自分の端末からcap production deploy を実行する。
- デプロイ先のサーバにて、github上のプロジェクトのcloneリクエストが行われる。
- githubからプロジェクトがデプロイ先サーバにcloneされる。
そうしたところ、2番目の手順でエラーが発生しました。
$ bundle exec cap production deploy …… 00:06 git:check 01 git ls-remote --heads git@github.com:quotto/HatenaBlog.git 01 Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts. 01 Permission denied (publickey). # こいつだ! 01 fatal: The remote end hung up unexpectedly (Backtrace restricted to imported tasks) cap aborted!
cloneする前に「git ls-remote」でリポジトリの中身を確認しているようですが、その時に「Permission denied(publickey)」とエラーが出ています。
ということで、解決までの道のりをまとめました。
デプロイ先サーバからgithubへの接続確認
まずは、デプロイ先のサーバから本当に接続ができないのか確認してみます。
サーバのコンソールから直接コマンドを実行すると……
$ git ls-remote --heads git@github.com:quotto/HatenaBlog.git Enter passphrase for key '/home/quotto/.ssh/id_rsa': 87675c005b2992fe734dd54c2b560ea5c54512e5 refs/heads/master
つながるやんけ!
と突っ込みたいところですがチョット待った。
これ、Capistranoでのデプロイ時には求められませんでした。
つまり現状はssh経由でのgithubへの接続にパスフレーズが必要な状態であり、自動デプロイ時には秘密鍵の入力を省略するようにしなければならないようです。
ssh-agent
どうすればパスフレーズの入力を省略できるのか。
その答えは「ssh-agentに秘密鍵を登録する」というものになります。
ssh-agentは秘密鍵とパスフレーズの組み合わせを預かってくれる仕組みです。
※図ではssh-agentが外部サービスのように見えますが、サーバ上のサービスです。
ssh-agentに秘密鍵を預けておくことで、リモートサーバにsshで接続する場合にssh-agentが認証を代行してくれます。
じゃあサーバ上で設定すればいいんだね!……とはいきません。
セキュリティ上の懸念
デプロイ先サーバ上のssh-agentにgithubの秘密鍵を登録すれば解決するはずではありますが、その場合「サーバ上に秘密鍵を置いておく」ことになります。
外部から参照されるサーバ上にこのような大事なものを置いておくのは、セキュリティ上よろしくありません。
そこで登場するのが「エージェント転送機能」です。
エージェント転送機能で安全に接続する
エージェント転送とは、要するに「ローカル端末の秘密鍵をサーバ上で利用する」機能です。
ローカル端末上のssh-agentが管理する秘密鍵をサーバへ転送し、サーバはその秘密鍵を使ってさらに先(github)へsshで接続します。このため、サーバ上には秘密鍵を置いておく必要がありません。
では実際に設定してみます。
ローカル端末側の設定
まずは現在ssh-agentで管理している秘密鍵を確認します。
$ ssh-add -l The agent has no identities.
何もありません。
秘密鍵の場所を指定して、ssh-agentに登録します。
$ ssh-add ~/.ssh/github_rsa Enter passphrase for /Users/localuser/.ssh/github_rsa: #パスフレーズを入力 Identity added: /Users/localuser/.ssh/github_rsa (/Users/localuser/.ssh/github_rsa) # 登録されたことを確認 $ ssh-add -l 2048 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /Users/localuser/.ssh/github_rsa (RSA)
サーバ側の設定
サーバ側では、エージェント転送機能により接続を許可するホストを「~/.ssh/config」に設定する必要があります。
#~/.ssh/config Host github Hostname github.com Port 22 User git ForwardAgent yes
ポイントは一番最後の「ForwardAgent yes」ですね。
確認
まずはコンソール上から試してみます。
sshコマンドに「-A」オプションを付けることでエージェント転送機能を有効にします。
$ ssh -A hatenablog.wackwack.net Last login: Sun Nov 13 20:49:55 2016 from pnnnnnn-ipngnnnnnxxxxxx.xxxxx.xx.xx $ git ls-remote --heads git@github.com:quotto/HatenaBlog.git 87675c005b2992fe734dd54c2b560ea5c54512e5 refs/heads/master $
パスフレーズの入力なしにgithubへ接続することができました。
さらにCapistranoでデプロイしてみます。
$ bundle exec cap production deploy …… 00:02 git:check 01 git ls-remote --heads git@github.com:quotto/HatenaBlog.git 01 87675c005b2992fe734dd54c2b560ea5c54512e5 refs/heads/master ✔ 01 localuser@hatenablog.wackwack.net 1.924s
これでバッチリです!
(参考?)Capistranoの設定ファイル
Capistranoの「config/deploy/デプロイ先.rb」には「ssh_options」という設定項目があります。
この設定項目を見る限りだと、OSのssh-agentには登録しなくともCapistranoの設定だけでエージェント転送できそうなんですが……できないんですよねぇ。
#config/deploy/production.rb …… set :ssh_options, { keys: %w(~/.ssh/wackwack_id_rsa), forward_agent: true, auth_methods: %w(publickey) }
参考にしたリンク先を見る感じだと設定ファイルだけでいけそうなんですが……
参考にさせていただいたサイト
Githubのsshで何故かPermission denied (publickey)となる場合の設定メモ
capistrano3でssh agent forwarding
ssh-agent でパスフレーズの入力を省く - WebOS Goodies
OpenSSH[実践]入門 (Software Design plus)
- 作者: 川本安武
- 出版社/メーカー: 技術評論社
- 発売日: 2014/11/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
- 作者: 黒田努
- 出版社/メーカー: インプレス
- 発売日: 2013/03/22
- メディア: Kindle版
- この商品を含むブログを見る