こんにちは、エンジニアの @hanhan1978です。
OpenSSHのバージョン7.3以降だと、ssh_configにおいてInclude
オプションが利用できるのはご存知でしょうか?これを利用すると、ssh_configを複数に分割して利用することが可能になります。分割して何が嬉しいのかというと、例えば仕事で接続するサーバの接続情報を共通のconfigとして読み込むことが出来ます。
具体的な構成例でいうと、下記のように config
と common_config
の2つを用意して、config
から common_config
を読み込むことが出来ます。
~/.ssh ├─ config └─ common_config
config
の中に、下記のようなInclude
オプションを記述するだけです。
Include ~/.ssh/common_config
ここからが本題なのですが、ssh_configの Include
オプションの仕様を正確に把握しておかないと、このInclude
が意図したように動作しないことがあります。
説明のための事前準備
config1
とconfig2
の2つのファイルがあったとします。ファイルの中身はそれぞれ server1, server2の接続情報が書かれています。
config1
の中身
Host server1 HostName xx.xxxx.xx User somebody IdentityFile ~/.ssh/id_rsa_server1
config2
の中身
Host server2 HostName xx.xxxx.xx User somebody IdentityFile ~/.ssh/id_rsa_server2
上手くいかない設定例
例えば、config1
からconfig2
を読み込もうとして、下記のように記述すると意図した通りに動作しません。
Host server1 HostName xx.xxxx.xx User somebody IdentityFile ~/.ssh/id_rsa_server1 Include ~/.ssh/config2
この状態で、server2
にログインしようとすると、下記のようにエラーが出てしまいます。※ちなみにserver1
へのログインは成功します。
$ ssh server2 ssh: Could not resolve hostname server2: nodename nor servname provided, or not known
上手くいかない理由
ssh_configのマニュアルには下記のような記述があります。
ssh_config(5) - Linux manual page
Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(3) wildcards and, for user configurations, shell-like ‘~’ references to user home directories. Files without absolute paths are assumed to be in ~/.ssh if included in a user configuration file or /etc/ssh if included from the system configuration file. Include directive may appear inside a Match or Host block to perform conditional inclusion.
簡単に解説するとInclude
は MatchやHostのblock内に書かれると、そのblock内にInclude
したファイルの設定内容を取り込むと書かれています。
実際に読み込まれた設定内容は下記のようになっていたものと思います。※説明のためにインデントを使って表現しています。
Host server1 HostName xx.xxxx.xx User somebody IdentityFile ~/.ssh/id_rsa_server1 Host server2 HostName xx.xxxx.xx User somebody IdentityFile ~/.ssh/id_rsa_server2
Include
したconfig2
の内容がHost server1
の設定として読み込まれてしまいます。かつ、Host
, Hostname
, IdentityFile
, User
の設定は2回目の定義なので無視されてしまいます。
こうして、server1
には接続出来るけど、server2
にはログインできない設定になってしまいました。
上手くいく設定例
意図通りに動かすためには ~/.ssh/config
の先頭に Includeオプションを持ってきます。これでconfig2
の設定が意図したとおりに読み込まれます。
Include ~/.ssh/config2 Host server1 HostName xx.xxxx.xx User somebody IdentityFile ~/.ssh/id_rsa_server1
まとめ
ssh_configのInclude
でハマったというタイトルですが、Include
の仕様を無視して使って失敗していただけですね。
Include
の仕様を上手に利用すれば、例えば一部の設定だけ共通化してHost
内の共通設定として利用することも出来ますね。
それでは、皆様も楽しいconfig共通化ライフをお過ごし下さい!
おまけ
Include
は便利なのですが、実はbash_completion
はInclude
した設定内容を補完してくれません。
なので利用する際はbash
をversion4以降にアップグレードした上でbash_completion2
を利用すると、Include
した設定内容も補完対象にしてくれるので幸せになれます。