Edited at

SSH config を Ruby で書けちゃう Nymphia でインフラライフをもっと充実させよう🐰

More than 1 year has passed since last update.

こんにちは。初 Qiita です :rabbit2:

インフラを日々扱うような仕事をしていると、ついついメンテをほったらかしてしまって破滅するのが SSH config、いわゆる ~/.ssh/config に置くアレです。

そもそも SSH config は構造的に書けるような仕組みを備えておらず、なし崩し的に Host ディレクティブを書いていくと、あっという間に地獄に一直線な仕様になっています。

そんな状況も、拙作の Nymphia を使えば打破できちゃうよ!というのがこの記事の趣旨です。

Nymphia を使えば、Ruby で SSH config を書ける上に、いい感じにファイル分割もできるので、SSH config の見通しがよくなり、精神的にもすごく安心できます。


:computer: Nymphia のインストールとソースコード

Ruby で書かれているので、基本的には gem install で一発です。

Rake と組み合わせたければ、適当に Gemfile に書いていい感じにするもよし。

$ gem install nymphia

ソースコードは以下の GitHub 上のリポジトリにあります。

https://github.com/mozamimy/nymphia


:rabbit: さっそく使ってみよう!

以下のコードは、最小のサンプルコードです。

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

これを ssh_confg.nym.rb といったファイル名で保存し、以下のコマンドでトランスレートすると..

$ nymphia -f ssh_confg.nym.rb

以下のような SSH config の出力が得られます。ファイルに吐きたい場合は、適当にリダイレクトするか、nymphia -f ssh_config.nym.rb -o config のように -o オプションをつけてください。

#

# 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

host メソッドの第一引数がホスト名にあたり、第二引数がコメントとして添えられる説明書きになります。第二引数は省略可能です。

あとは、SSH config でいうところの Host ディレクティブの中身をスネークケースでつらつらと書いていくだけです。

Ruby のフル機能を使えるので、 my_server_port のように変数を使うことも思いのままです。

また、素の SSH config では、あらゆる場所に鍵のファイルパスを書く必要があり、これがわたしの不満の種のひとつでした。

Nymphia では、identity_file メソッドで鍵に名前をつけ、host ブロックの中で use_identity_file メソッドに名前を書くようにすることで、鍵のファイルパスが散らばる問題を防いでいます。use_identity_file :key1, :key2 のように、複数書くこともできます。


:floppy_disk: ファイルを分割しよう

たとえば、以下のように load '読み込みたいファイル名' のように書くと、別のファイルに保存した Nymphia ファイルを読み込み、その内容をひとつの SSH config ファイルに吐くことができます。

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 'company_servers.nym.rb'


:fax: proxy でプロキシとして使うサーバを定義しよう

素の SSH config では、ふつうのサーバも、SSH forwarding をするためのプロキシも、踏み台にするためのゲートウェイも、ぜんぶ Host ディレクティブで定義します。

これでは、コード上からは、どういう目的で使われるサーバなのかわかりません。

Nymphia では、プロキシとして使うサーバは明示的に proxy メソッドで定義できます。

以下は 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

これを変換すると、以下のような出力が得られます。

#

# 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

proxy 中では、host では使えなかった local_forward メソッドが使え、いわゆる SSH forwarding をハッシュでそれっぽく書けるようになります。


:pick: 応用編: グルーピング機能と、use_gatewaydefault_params

Nymphia は、サーバをグループにまとめて、そのグループに含まれているサーバは特定のゲートウェイを使うようにしたり、デフォルトのパラメータを適用させるようにできます。

以下がその例です。

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 メソッドは、host とほぼ同じです。出力結果でも、Host ディレクティブとして出力されます。

ただ一つ違うのは、group メソッドで作ったグループの中で、use_gateway に指定すると、グループに含まれているホストに、一括で ProxyCommand ssh company.gateway -q -W %h:%p のようなディレクティブを生成してくれるところです。

この機構により、「このグループに含まれるサーバへの接続にはこのゲートウェイを使うんだよ!」ということが明示的にわかるようになります。

また、グループ中で default_params を書くと、グループに含まれる全てのホストにデフォルトのパラメータを設定できます。この機構により、host '*.apne.aws.example.com' のようにスッキリできます。

もちろん、host 'alice.apne.aws.example.com' での例のように、デフォルト値を上書きすることもできます。


:question: Nymphia はどんなときに便利なの?


:pencil: とにかく SSH config をリーダブルにしたいとき

group のような構造化の仕組みや、hostproxygateway を使い分けることによる可読性の向上、load によるファイル分割など、SSH config をよりリーダブルにできます。


:package: チームメンバーに SSH config を配って使ってもらいたいとき

たとえば、新しく開発チームに迎え入れる人に対して、AWS の VPC 上に配置されているインスタンスや、オンプレのサーバにシュッとログインできるようにするために、SSH config を例を渡すことがあります。

超小さい例ですが、たとえばこんな感じのファイルを渡して、alice になっている部分を、彼のユーザ名である shinjin-kun に変えてね〜と言うわけです。

Host *.apne.aws.example.com

User alice
Port 9822
IdentityFile ~/.ssh/id_rsa.company

こういう作業を、ウサギやニンゲンのような知的生命体がやるのはアホらしいので、たとえばこんな感じの Nymphia ファイルを渡して、各自ビルドしてもらうとラクラクです。

identity_file :company, '~/.ssh/id_rsa.company'

USER = ENV['NYM_USER'] || 'alice'

host '*.apne.aws.example.com' do
user ENV['NYM_USER']
port 9822
use_identity_file :company
end

また、Nymphia ファイルを Git で管理しておけば、もし SSH config に更新が発生しても、それを git pull してもらって、再度ビルドしてもらうようにすれば、いちいちサンプルの SSH config と自分の SSH config を見比べて書き直す.. というような手間が省けます。

もし、チームに入ってきた人が Nymphia ユーザなら、なおのこと happy です :100:

なぜなら、チームに入ってきた人が今使っている Nymphia のファイルに、会社用の Nymphia ファイルを load 'company.nym.rb' のように、たった 1 行書き足すだけで、チームが管理しているサーバにログインできるようになるからです!


:pen_ballpoint: vim の syntax もあるよ!

nymphia.vim を使えば、vim でにぎやかに編集できるようになります :sparkles:

わたしは、*.nym.rb というような拡張を持つファイルに対して、この syntax を適用するようにしています。

そうすれば、Nymphia の syntax に対応していないような GitHub などでも、フォールバックとして Ruby のコードして認識されるからです。

nymphia.vim.png


:paperclip: まとめ

いかがでしたでしょうか?

日頃の SSH config の管理に困っていたら、ぜひ使ってみてください。工夫次第で、思いもつかなかったような使い方もできるかもしれません。

もちろん、パッチやコメントもウェルカムです :muscle_tone1: :rabbit:


:bulb: Nymphia is 何

かわいい


:fried_shrimp: あわせてよみたい