Edited at

`Include`キーワードで`ssh_config`を分割できるようになった件

More than 1 year has passed since last update.


要約



  • ssh_configの分割にはIncludeキーワードが使えます


  • Includeキーワードは2016-08-01リリースのOpenSSH 7.3から導入されています


Includeキーワード

先日、何気なくman ssh_configしていたところIncludeという便利キーワードの存在に気づきました。Includeキーワードは、どうやら2016-08-01にリリースされたOpenSSH 7.3で導入されたようです。


Includeでできること

$ man ssh_config

...
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キーワードを使うことで~/.ssh/configの設定を別ファイルに切り出すことができることがわかります。


ファイルの分割方法

Includeキーワードを使うことで

$ cat ~/.ssh/config

Host hoge
HostName hoge.example.com
User hoge
IdentityFile ~/.ssh/id.pem

Host fuga
HostName fuga
Port 2222
User abc
IdentityFile ~/.ssh/abc.pem

Host xyz
HostName xyz.example.com
Port 2222
User abc
IdentityFile ~/.ssh/abc.pem

Host *
ServerAliveInterval 300
AddKeysToAgent yes

このような~/.ssh/configを下記のように分割することができます。


ディレクトリー構成

今回は分割したファイルを$HOME/.ssh/conf.d/配下に置くことにします。

$ tree ~/.ssh

/Users/masa0x80/.ssh
├── ...
├── conf.d
│   ├── commons
│   │   └── abc
│   └── hosts
│   ├── hoge
│   └── misc
├── config
└── ...


~/.ssh/configの中身

Includeを使ってHost directiveを切り出してみます。

$ cat ~/.ssh/cofig

Include conf.d/hosts/*

Host *
ServerAliveInterval 300
AddKeysToAgent yes

ssh_configの設定は基本的に先勝(先に定義されたものが優先される)なので、まずIncludeHost directiveを読み込んでからHost *で全体的な設定を行うのが良いです。

IncludeMatchHostの中にも置くことができますので記述順序には注意が必要です。例えば、下記のようにHost directiveの後にIncludeを記載すると、ssh fooの時にのみconf.d/hogeが読み込まれるために、期待通りの挙動になりません。

Host foo

HostName ...

Include conf.d/hosts/*


~/.ssh/conf.d/hosts/hogeの中身

hogeに関する設定を単純にファイルに切り出しただけです。

$ cat ~/.ssh/conf.d/hosts/hoge

Host hoge
HostName hoge.example.com
User hoge
IdentityFile ~/.ssh/id.pem


~/.ssh/conf.d/hosts/miscの中身

Host directiveを複数書くこともできますし、更にIncludeすることもできます。

$ cat ~/.ssh/conf.d/hosts/misc

Host fuga
HostName fuga.example.com
Include conf.d/commons/abc

Host xyz
HostName xyz.example.com
Include conf.d/commons/abc

*?を使って設定を書きにくい場合は、Host directiveの中でIncludeを使用して共通設定を読み込むと便利です。今回は下記の様にも書けますが、設定が大きくなってくるとIncludeを使った方が誤爆を防ぎやすいと思います。

Host fuga

HostName fuga.example.com

Host xyz
HostName xyz.example.com

Host fuga xyz
Port 2222
User abc
IdentityFile ~/.ssh/abc.pem


~/.ssh/conf.d/commons/abcの中身

~/.ssh/conf.d/hosts/miscから参照される設定値です。

$ cat ~/.ssh/conf.d/commons/abc

Port 2222
User abc
IdentityFile ~/.ssh/abc.pem


fzfとの連携


zshの場合

下記のような関数を準備しておくことで^s^sと入力することで、ssh_configに記載されているホスト名を補完することができて便利です。

なお、読み込むファイルは~/.ssh/config~/.ssh/conf.d/配下のファイルになっているので適宜修正ください。


complete-ssh-host.zsh

complete-ssh-host() {

local host="$(command egrep -i '^Host\s+.+' $HOME/.ssh/config $(find $HOME/.ssh/conf.d -type f 2>/dev/null) | command egrep -v '[*?]' | awk '{print $2}' | sort | fzf)"

if [ ! -z "$host" ]; then
LBUFFER+="$host"
fi
zle reset-prompt
}
zle -N complete-ssh-host
bindkey '^s^s' complete-ssh-host


fzfの部分をpecoに変更することでpeco利用に変更することもできます。


fishの場合

拙作のcomplete_ssh_host.fishを利用すると上記のzshと同等の処理(^s^sで補完)ができるようになります。

fishermanを使ってインストールする場合は下記で利用できます。

fisher masa0x80/complete_ssh_host.fish

あるいは、こちらも拙作のfrescoというプラグインマネージャーを使ってインストールする場合は下記となります。

$ # Install fresco

$ curl https://raw.githubusercontent.com/masa0x80/fresco/master/install | fish
$ exec fish -l

$ # Install plugin
$ fresco masa0x80/complete_ssh_host.fish

frescoを使うとfishのスクリプトをghqを使って管理できて便利です。