コンテンツへスキップ

~/.ssh/config でホスト別設定を整理する — 複数サーバーを扱う人の定石

WordPressサイトの保守を複数台のサーバーで行っていると、ssh -i ~/.ssh/xxx_key.pem -p 2222 user@203.0.113.10 のような長いコマンドを毎回タイプすることになる。鍵ファイルのパス、ポート番号、ユーザー名——サーバーごとに違う値を覚えておくのは現実的ではなく、シェル履歴から似たコマンドをコピーして接続先を間違える、というヒューマンエラーの温床にもなる。この問題を解決するのが ~/.ssh/config によるホスト別設定の集約である。

補足: ~/.ssh/config はOpenSSHクライアントが読む設定ファイルで、サーバー側の設定ではない。手元の端末(Mac/Linux/WindowsのSSHクライアント)にどのサーバーへどう繋ぐかを覚えさせる仕組みで、サーバー1台につき数行のブロックを書くだけで済む。

基本構造

最小構成は次のようになる。

Host myserver
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/myserver_key
    IdentitiesOnly yes

これを保存しておけば、以後は次のように書くだけで済む。

ssh myserver

Host に書いた文字列(この例では myserver)はエイリアスであり、実際のホスト名とは無関係な任意の文字列でよい。scprsync もこのエイリアスをそのまま使えるため、scp file.txt myserver:/tmp/ のように書ける。ポート番号やユーザー名をコマンドラインで毎回指定する必要がなくなり、鍵ファイルのパスを打ち間違えるリスクも消える。

IdentitiesOnly yes を必ず付ける理由

IdentityFile で鍵を指定しても、IdentitiesOnly yes を書かないとOpenSSHクライアントは指定した鍵に加えてssh-agent に登録されている他の鍵も一緒にサーバーへ提示してしまう。サーバー側に接続試行回数の上限(MaxAuthTries)や、一定回数の認証失敗でIPを一時ブロックするセキュリティ機構(fail2ban等)が入っている場合、意図しない鍵を何本も提示した結果、正しい鍵にたどり着く前に接続がブロックされることがある。

IdentitiesOnly yes を指定すると、そのHostブロックで明示したIdentityFileだけを提示するようになり、余計な認証試行を防げる。複数のSSH鍵を使い分けている環境(案件ごとに鍵を分けている、個人用と業務用を分けている等)では、事実上必須のオプションと考えてよい。

ワイルドカードで複数サーバーに共通設定をまとめる

似た環境のサーバーが複数ある場合、Host にワイルドカードを使って共通設定をまとめられる。

Host staging-*
    User deploy
    IdentitiesOnly yes
    ServerAliveInterval 30

Host staging-web1
    HostName 203.0.113.10
    IdentityFile ~/.ssh/staging_key

Host staging-web2
    HostName 203.0.113.20
    IdentityFile ~/.ssh/staging_key

OpenSSHは設定ファイルを上から順に読み、先に見つかった値を優先する(後から書いた同名オプションでは上書きされない)という挙動を持つため、個別のHostブロックを共通ブロックよりに書く必要がある点には注意が必要になる。staging-* を先に書いてしまうと、個別ブロックのHostNameが読まれず全て同じサーバーに繋ごうとしてしまう。

ServerAliveInterval 30 は、一定時間操作がないと切断されるネットワーク環境(一部のルーターやファイアウォールでアイドルタイムアウトが設定されている場合など)で、30秒おきにキープアライブパケットを送って接続を維持するオプションである。長時間かかるバックアップ処理などをSSH越しに実行する際に切断を防ぐ効果がある。

設定ファイルを分割する(Include

案件数が増えてくると、1つの~/.ssh/configに全サーバーの設定を書き連ねるのは見通しが悪くなる。OpenSSH 7.3以降ではIncludeディレクティブでファイルを分割できる。

# ~/.ssh/config
Include ~/.ssh/config.d/*.conf

Host *
    IdentitiesOnly yes

~/.ssh/config.d/ ディレクトリに案件別・顧客別のファイルを置いておけば、案件が終了した際にそのファイルを削除するだけで設定がきれいに片付く。Includeファイル内のその位置で展開されるため、Host *のような全体に効く共通設定より前に置くか後に置くかで優先順位が変わる点は覚えておきたい。

WP-CLI aliasとの役割の違い

WP-CLIのaliasで複数のWordPress環境を安全に切り替えるで扱ったwp-cli.ymlのエイリアスは、WP-CLIというアプリケーション層のツールが「どのWordPressサイトに対してコマンドを実行するか」を管理する仕組みだった。一方、~/.ssh/configはOSのSSHクライアントというさらに下の層で「どのサーバーにどう接続するか」を管理する。

両者は独立した仕組みだが、組み合わせると効果が大きい。~/.ssh/configでサーバーへの接続そのものを整理し、その上でWP-CLI aliasが各サーバー内の複数サイトを整理する、という二段構えにすると、接続コマンドとサイト指定コマンドの両方が短く安全になる。

セキュリティ上の注意点

~/.ssh/configにはサーバーのホスト名やIPアドレス、ポート番号が平文で書かれる。ファイル自体のパーミッションは600(自分だけ読み書き可能)にしておくのが基本で、OpenSSHクライアントによっては緩いパーミッションだと警告を出す実装もある。

chmod 600 ~/.ssh/config

また、このファイルを誤ってGitリポジトリにコミットしてしまうと、社内的な接続情報が外部に漏れる事故につながる。個人の~/.ssh/配下は通常Gitの管理対象外だが、プロジェクトのdotfiles管理をリポジトリ化している場合は.gitignoreで明示的に除外しておくと安心である。

まとめ

設定項目 役割
Host エイリアス名(自由に命名可)
HostName 実際の接続先(IPまたはドメイン)
IdentityFile 使用する秘密鍵のパス
IdentitiesOnly yes 指定した鍵だけを提示し、余計な認証試行を防ぐ
Host パターン* ワイルドカードで複数サーバーに共通設定を適用
Include 設定ファイルを案件別・顧客別に分割

複数のWordPress環境をSSH経由で保守する運用では、~/.ssh/configは一度整えてしまえばあとはエイリアス名を覚えるだけで済む。コマンドが短くなること自体より、接続先を間違えるリスクが構造的に減ることが最大の効果になる。鍵の種類の選び方についてはSSH鍵の種類(RSA / ED25519 / ECDSA)はどう違い、どれを選ぶべきかも参考にしてほしい。