SSH 設定に forward_agent オプションを追加

basecamp/kamal

Kamal の SSH 設定に forward_agent が指定できるようになり、エージェント転送が不要な環境でも安全にデプロイできるようになりました。

背景

SSHKit は内部で forward_agent: true をハードコードしており、ジャンプホストやトンネル(例: Cloudflare Access for Infrastructure with SSH)を経由するデプロイではエージェント転送が失敗することがありました。Kamal の ssh: 設定は SSHKit のオプションを上書きする手段を提供していなかったため、ユーザーは正しい接続を確保できませんでした。さらに設定は docs/ssh.yml に基づくバリデーションを通過しなければ受け付けられず、未知のキーはエラーとなっていました。これらの制約を解消することが今回の変更の主目的です。

技術的な変更

lib/kamal/configuration/docs/ssh.ymlforward_agent キーのドキュメントが追記され、デフォルトは true(SSHKit の既定)として記述されています。ユーザーは ssh:
forward_agent: false
のように YAML に明示するだけでオプションを無効化できます。

+  # Forward agent
+  #
+  # Whether to forward the local SSH agent to the remote host. Defaults to
+  # true (sshkit's default). Set to false when connecting through a jump
+  # host or tunnel that does not support agent forwarding (for example,
+  # Cloudflare Access for Infrastructure with SSH).
+  forward_agent: false

lib/kamal/configuration/ssh.rb では forward_agent メソッドが新規に追加され、ssh_config["forward_agent"] を返すようになりました。さらに options ハッシュに forward_agent: forward_agent が組み込まれ、SSH 接続時にこの値が SSHKit に渡されます。

@@
   def forward_agent
     ssh_config["forward_agent"]
   end

   def options
-    { user: user, port: port, proxy: proxy, logger: logger, keepalive: true, keepalive_interval: 30, keys_only: keys_only, keys: keys, key_data: key_data, config: config  }.compact
+    { user: user, port: port, proxy: proxy, logger: logger, keepalive: true, keepalive_interval: 30, keys_only: keys_only, keys: keys, key_data: key_data, config: config, forward_agent: forward_agent }.compact
   end

テスト test/configuration/ssh_test.rb も更新され、forward_agent が未設定の場合は nilfalsetrue がそれぞれ期待通りにオプションに反映されることを検証しています。

@@
   assert_nil @config.ssh.options[:forward_agent]

   config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "forward_agent" => false }) })
   assert_equal false, config.ssh.options[:forward_agent]

   config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "forward_agent" => true }) })
   assert_equal true, config.ssh.options[:forward_agent]

設計判断

Kamal は 既存の ssh: キーを拡張 して forward_agent を露出させる方針を採用しました。新たに ssh_forward_agent など別キーを導入する案もあったものの、既存キーの拡張は後方互換性を保ちつつ SSHKit のデフォルト挙動(true)をそのまま継承できるため最小限の変更で済みました。options ハッシュへの追加は compact による nil 削除だけで完結し、既存コードへの影響は実質なしです。

まとめ

この PR により Kamal の SSH 設定で forward_agent オプションを明示的に制御できるようになり、ジャンプホストやトンネル環境でも安全にデプロイが可能になります。設定項目は文書化され、テストで動作が保証されたため、既存ユーザーへの影術的リスクは最小限です。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
722acaef

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断(任意)、まとめがすべて揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックは `言語:ファイルパス` 形式で正しく記述され、PRリンクも `[ #1853 ](URL)` の形式で正しくハイパーリンク化されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

対象はエンジニアで、専門用語中心の記述となっており、過度な初心者向け説明はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論パラグラフ→各論パラグラフ→結論パラグラフで構成され、段落はトピックセンテンスで始まり 1段落1トピック、長さも適切です。空行で区切りもあります。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事中のコードブロックは Diff の内容と一致しており、追加・変更箇所が正確に反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`forward_agent`、SSHKit、jump host などの用語は PR と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

技術的説明は PR の要旨とコード変更に基づいており、誤った主張は見当たりません。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

PR に記載された事実以外の根拠のない数値や外部知識は含まれておらず、ハルシネーションはありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #1853 などの数値は正しく記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは PR の内容(forward_agent オプションの追加)を正確に表現しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

LTS やリリース日程など PR に無い外部情報は記載されていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現のずれはなく、PR の記述と一致しています。