SSH config を構造的に書くための Ruby の DSL Nymphia の紹介
Tweet
たくさんのサーバを日々扱うエンジニアにとって、SSH config をキレイに保つことは大切です。 そもそも SSH config は構造的に書きにくい仕様になっているし、「まあそんなものか..」と妥協して、SSH config のメンテが適当になってしまうこともあると思います。
今までわたしもそうだったのですが、さすがにそろそろ破滅が見えてきていて、なんとなく Ruby で DSL を作るやっていきが高まったので、Ruby の DSL で設定を書くと SSH config を生成する Nymphia というものを作りました。
https://github.com/mozamimy/nymphia
また、色があまりつかなくてさみしかったので、vim の syntax も作りました。
https://github.com/mozamimy/nymphia.vim
インストール
例によって Rubygems から。
$ gem install nymphia
こんな感じで SSH config が書けちゃうよ
基本形
まず、いちばん基本的なサンプルコードです。
identity_file :private, '~/.ssh/id_rsa.1' my_server_port = 4321 host 'alice', 'my server on VPS' do hostname 'alice.example.com' user 'alice' port my_server_port use_identify_file :private end
これをトランスレータにかけると、
#
# This config is generated by Nymphia 0.1.0
#
# my server on VPS
Host alice
Hostname alice.example.com
User alice
Port 4321
IdentityFile ~/.ssh/id_rsa.1
こんな感じの SSH config が生成されます。トランスレートは以下のようなコマンドを使います。
$ nymphia -f /path/to/nymphia_file.rb -o /path/to/output_file
ホストの定義は host
メソッドで行います。第一引数にホスト名、第二引数に説明を書きます。第二引数は省略可能で、書いた場合は生成後の Host
ディレクティブの上に添えられます。
基本的に Ruby なので、my_server_port
のように変数を定義して使うといったことも可能です。
また、SSH config の不満点のひとつに、あらゆる場所に IdentityFile に設定する同じファイルパスを書かないといけないという点があります。
この問題は identity_file
と use_identify_file
で解決していて、identity_file
に :private
のような名前をつけて、host
ブロックの中で use_identify_file
のように書くといい感じに IdentityFile
ディレクティブを埋め込んでくれます。
また、use_identify_file :usausa, :pyonpyon
のように、複数指定することも可能です。
ファイル分割
load
メソッドを使えば、ファイル分割をして設定を管理できます。
以下のように書くと、トランスレータ時に other_nymphia_file.rb を読み込んで実行します。
identity_file :private, '~/.ssh/id_rsa.1' host 'alice', 'my server on VPS' do hostname 'alice.example.com' user 'alice' port 4321 use_identify_file :private end load 'other_nymphia_file.rb'
Proxy を定義する
素の SSH config では、ホストの定義はすべて Host
ディレクティブで定義するので、そのホストがプロクシとして使われるのか、通常の接続先として使われるのか、ゲートウェイとして踏み台にするのか、コードだけではわかりにくいのも不満でした。
そこで、Nymphia では、proxy
というメソッドを使うことで、明示的にその接続先がプロクシとして使われることをコードで示すことができます。また、proxy
コンテキスト中では、local_forward
メソッドでよくあるフォワーディングの設定を読みやすく書くことができます。
以下は proxy
を使った例です。
identity_file :company_gateway, '~/.ssh/id_rsa.company.gw' proxy 'awsproxy.company.apne1' do hostname 'gw.apne1.example.com' user 'alice' port 19822 use_identify_file :company_gateway # SOCKS proxy dynamic_forward 23921 # ssh tunnels local_forward 'mysql-server', { 'localhost' => 13306, 'mysql.apne.aws.example.com' => 3306, } local_forward 'ldap', { 'localhost' => 10389, 'ldap.apne.aws.example.com' => 398, } end
このサンプルコードを Nymphia にかけると、以下のような出力が得られます。
#
# This config is generated by Nymphia 0.1.0
#
Host awsproxy.company.apne1
Hostname gw.apne1.example.com
User alice
Port 19822
IdentityFile ~/.ssh/id_rsa.company.gw
DynamicForward 23921
LocalForward localhost:13306 mysql.apne.aws.example.com:3306
LocalForward localhost:10389 ldap.apne.aws.example.com:398
応用編: ホストをグループにまとめる、group、use_gateway、default_params
構造化のための強力な機構として、Nymphia は group
、gateway
、use_gateway
、default_params
といったメソッドを提供します。
以下にそれらのメソッドを使った例を示します。
identity_file :company, '~/.ssh/id_rsa.company' identity_file :company_gateway, '~/.ssh/id_rsa.company.gw' gateway 'company.gateway' do hostname 'gw.example.com' user 'alice' port 19822 end group 'company.ap-northeast-1' do use_gateway 'company.gateway' default_params do check_host_ip 'no' strict_host_key_checking 'no' user 'alice' port 9822 use_identify_file :company, :company_gateway end host '*.apne.aws.example.com' host 'alice.apne.aws.example.com' do hostname '10.16.16.16' user 'white_rabbit' port 7777 end end
この例をトランスレートすると、以下のような出力が得られます。
#
# This config is generated by Nymphia 0.1.0
#
Host company.gateway
Hostname gw.example.com
User alice
Port 19822
Host *.apne.aws.example.com
CheckHostIp no
StrictHostKeyChecking no
User alice
Port 9822
IdentityFile ~/.ssh/id_rsa.company
IdentityFile ~/.ssh/id_rsa.company.gw
ProxyCommand ssh company.gateway -q -W %h:%p
Host alice.apne.aws.example.com
CheckHostIp no
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_rsa.company
IdentityFile ~/.ssh/id_rsa.company.gw
ProxyCommand ssh company.gateway -q -W %h:%p
Hostname 10.16.16.16
User white_rabbit
Port 7777
gateway
メソッドも proxy
メソッドと似ていて、host
とほぼおなじはたらきをします。
ただし、gateway
として登録されたホストは、group
メソッドによるグループの中で use_gateway
で指定することで、グループに含まれるホストの中で ProxyCommand ssh company.gateway -q -W %h:%p
のような ProxyCommand
ディレクティブをいい感じに生成してくれます。
また、default_params
を使うと、グループ中のホストに対するデフォルトのパラメータを設定することができます。
host '*.apne.aws.example.com'
で何も書いていないのに、種々のディレクティブが生成されているのがわかると思います。
また、host 'alice.apne.aws.example.com'
の例のように、デフォルト値をオーバーライドすることも可能です。
GitHub 上の examples を見ると、以上の機構をすべて使った例があるので、Nymphia を使う際に参考になると思います。
Vim の syntax もあるよ
Ruby で気持ちよく書けるようになったのはいいのですが、種々の機能はメソッドとして実装されているので、vim のシンタックス定義 を作ってにぎやかに書けるようにしました。 nymphia.vim を入れると、以下のような感じでにぎやかに Nymphia ファイルを編集できます。

vim の syntax 定義を作るのが初めてで、ハチャメチャだったのを @Linda_pp さんが添削してくれました 🐶 🐰 vim のマニュアルは非常に親切なのでちゃんと読まねば..