SSH設定ファイルの参照をサポート
KamalがSSH接続時に ~/.ssh/config などのSSH設定ファイルを参照できるようになりました。これにより、kamal app logs --follow などのコマンド実行時に、SSH設定ファイルで定義されたホストエイリアスやプロキシ設定を活用できます。
背景
Kamalは run_over_ssh メソッドを使ってリモートサーバーでコマンドを実行しますが、これまでSSH設定ファイル(~/.ssh/config)の設定を参照する機能がありませんでした。#1755 で報告された問題に対応し、#1746 でSSH設定ファイルのサポートが追加されています。
技術的な変更
run_over_ssh メソッドにSSH設定ファイルを指定するための -F オプションが追加されました。
変更前:
def run_over_ssh(*command, host:)
"ssh#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\'")}'"
end
変更後:
def run_over_ssh(*command, host:)
"ssh#{ssh_config_args}#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\'")}'"
end
新たに追加された ssh_config_args メソッドは、設定値に応じて以下のように動作します:
def ssh_config_args
case config.ssh.config
when Array
config.ssh.config.map { |file| " -F #{file}" }.join
when String
" -F #{config.ssh.config}"
when true
"" # デフォルトのSSH設定を使用
when false
" -F /dev/null" # SSH設定を無視
end
end
使用例
単一の設定ファイルを指定
ssh:
config: "~/.ssh/custom_config"
生成されるコマンド:
ssh -F ~/.ssh/custom_config -t root@app-1 -p 22 'ls'
複数の設定ファイルを指定
ssh:
config:
- "~/.ssh/config1"
- "~/.ssh/config2"
生成されるコマンド:
ssh -F ~/.ssh/config1 -F ~/.ssh/config2 -t root@app-1 -p 22 'ls'
SSH設定を明示的に無効化
ssh:
config: false
生成されるコマンド:
ssh -F /dev/null -t root@app-1 -p 22 'ls'
-F /dev/null を指定することで、システムやユーザーのSSH設定ファイルを完全に無視します。
設計判断
柔軟な設定値のサポート
この実装では、config.ssh.config に対して以下の4つの値をサポートしています:
- String: 単一の設定ファイルパス
-
Array: 複数の設定ファイルパス(SSHの
-Fオプションは複数回指定可能) - true: デフォルトのSSH設定を使用(引数を追加しない)
-
false: SSH設定を無視(
-F /dev/nullを指定)
この設計により、ユーザーは環境に応じて細かく制御できます。
オプションの適用順序
SSHコマンドのオプションは以下の順序で適用されます:
"ssh#{ssh_config_args}#{ssh_proxy_args}#{ssh_keys_args} -t ..."
ssh_config_args が最初に来るため、設定ファイルで定義された内容が後続のオプション(プロキシや鍵)よりも先に評価されます。これにより、設定ファイルの設定を基本とし、コマンドライン引数で上書きする標準的なSSHの動作に従っています。