SSH configの書き方|~/.ssh/configで接続設定をまとめる方法

コマンドリファレンス

SSH configとは、~/.ssh/config に接続先ごとの設定をまとめておき、毎回 -p-i などのオプションを打たずに ssh ホスト名 だけで接続できるようにする仕組みです。サーバーごとにユーザー名・ポート・秘密鍵が違っても、Hostエイリアスを1つ覚えるだけで済みます。ここで登録したHostエイリアスは scpsftprsync など他のSSH関連コマンドからもそのまま使えます。この記事では ~/.ssh/config の書き方、主要なディレクティブ、複数サーバーの使い分けや踏み台サーバー経由の接続設定、接続を高速化する設定まで、実際に動作を確認したコマンド例とあわせて解説します。

SSH configとは

SSH configは、OpenSSHクライアントが接続時に読み込む設定ファイルです。ユーザーごとの設定は ~/.ssh/config、システム全体の設定は /etc/ssh/ssh_config に置かれ、通常はユーザー個別の ~/.ssh/config を編集します。

SSH configがなくても ssh コマンドはオプション指定だけで動作しますが、次のようなケースで真価を発揮します。

  • 接続先ごとにユーザー名・ポート・秘密鍵が異なる
  • 踏み台サーバー(Bastion)を経由して内部サーバーへ接続する
  • GitHub・GitLabなどで複数アカウントを鍵で使い分ける
  • 接続が切れやすい回線でKeepAliveを常時有効にしたい

設定ファイルの場所と作成方法

~/.ssh/config は自動生成されないため、存在しなければ自分で作成します。

mkdir -p ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config

~/.ssh ディレクトリのパーミッションは 700、config ファイルは 600 にしておく必要があります。パーミッションが緩いと、OpenSSHが警告を出したり設定が無視されたりすることがあります。

基本の書き方(構文)

SSH configは Host ブロックの繰り返しで構成します。Host に続けてエイリアス名(任意の文字列)を書き、その下にインデントして接続先の詳細を記述します。

Host エイリアス名
    HostName 実際のホスト名またはIPアドレス
    User ログインユーザー名
    Port ポート番号
    IdentityFile 秘密鍵のパス

設定後は次のように、エイリアス名だけで接続できます。

ssh エイリアス名

主要ディレクティブ一覧

ディレクティブ説明設定例
HostName接続先の実際のホスト名・IPアドレスHostName 203.0.113.10
Userログインユーザー名User admin
Port接続先ポート(デフォルト22)Port 2222
IdentityFile認証に使う秘密鍵のパスIdentityFile ~/.ssh/id_ed25519
IdentitiesOnly指定した鍵のみを使用(ssh-agent内の他の鍵を無視)IdentitiesOnly yes
ProxyJump踏み台サーバーを経由して接続(OpenSSH 7.3以降)ProxyJump bastion
ProxyCommand接続前に任意のコマンドでトンネルを作成(ProxyJump登場以前の書き方)ProxyCommand ssh bastion -W %h:%p
ForwardAgentssh-agentの鍵を接続先に転送するかForwardAgent yes
LocalForwardローカルポートフォワーディングLocalForward 8080 localhost:80
ServerAliveIntervalサーバーへの生存確認を送る間隔(秒)ServerAliveInterval 60
ServerAliveCountMax応答がない場合に切断するまでの回数ServerAliveCountMax 3
StrictHostKeyCheckingknown_hostsにないホストキーの扱い(noは検証省略。恒久的な設定は非推奨)StrictHostKeyChecking accept-new
Include他の設定ファイルを読み込むInclude ~/.ssh/conf.d/*.conf
ControlMaster接続を再利用するマルチプレクシングを有効にするControlMaster auto
ControlPathマルチプレクシング用ソケットの保存先ControlPath ~/.ssh/sockets/%r@%h:%p
ControlPersist最後の接続が閉じた後もマスター接続を維持する時間ControlPersist 10m
Compression通信を圧縮する(低速回線やテキスト中心の転送で有効)Compression yes
DynamicForwardSOCKSプロキシとしてポートフォワーディングするDynamicForward 1080
MatchHostより柔軟な条件(コマンド実行結果や複数条件)で設定を切り替えるMatch host *.internal exec "ping -c1 -W1 %h"

設定例1: Hostエイリアスで接続を簡略化する

ユーザー名・ポート・秘密鍵の組み合わせをエイリアスに閉じ込めます。

# ~/.ssh/config
Host myserver
    HostName example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/my_key

これで ssh -p 2222 -i ~/.ssh/my_key admin@example.com の代わりに、次の1行で接続できます。

ssh myserver

-G オプションを使うと、実際に接続せずに解決後の設定内容だけを確認できます。設定ミスの切り分けに便利です。

$ ssh -G myserver | grep -E "^(hostname|user|port|identityfile) "
user admin
hostname example.com
port 2222
identityfile ~/.ssh/my_key

設定例2: 複数サーバーを使い分ける

Host ブロックを増やすだけで、サーバーごとの接続情報を管理できます。

# ~/.ssh/config
Host web01
    HostName 203.0.113.10
    User deploy
    IdentityFile ~/.ssh/web_key

Host db01
    HostName 203.0.113.20
    User dbadmin
    Port 2222
    IdentityFile ~/.ssh/db_key

Host bastion
    HostName bastion.example.com
    User ec2-user
    IdentityFile ~/.ssh/aws_key.pem
ssh web01
ssh db01
ssh bastion

設定例3: 踏み台サーバー経由で接続する(ProxyJump)

内部ネットワークのサーバーに直接SSHできない構成では、ProxyJump で踏み台サーバー(Bastion)を経由させます。OpenSSH 7.3以降で利用できる書き方です。

# ~/.ssh/config
Host bastion
    HostName bastion.example.com
    User ec2-user
    IdentityFile ~/.ssh/aws_key.pem

Host internal
    HostName 10.0.0.5
    User deploy
    ProxyJump bastion
    IdentitiesOnly yes

ssh internal と打つだけで、自動的に bastion を経由して 10.0.0.5 に接続します。-G で確認すると、proxyjump が解決されていることが分かります。

$ ssh -G internal | grep -E "^(hostname|user|proxyjump) "
user deploy
hostname 10.0.0.5
proxyjump bastion

古い環境向けには、同じ動作を ProxyCommand で書くこともできます。

Host internal
    HostName 10.0.0.5
    User deploy
    ProxyCommand ssh -W %h:%p bastion

設定例4: GitHubなど複数アカウントを鍵で使い分ける

GitHubの個人アカウントと組織アカウントで鍵を分けたい場合、HostName は同じ github.com のまま、Hostエイリアスだけを変えて使い分けます。

# ~/.ssh/config
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_personal

Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_work

個人用は通常どおり git@github.com:... を使い、仕事用リポジトリは clone 時のURLを git@github-work:org/repo.git に書き換えることで、鍵を自動的に使い分けられます。

Host * で共通設定をまとめる

Host * はすべてのHostにマッチするワイルドカードです。全接続先に共通させたい設定(KeepAliveなど)をまとめておくと、個別のHostブロックがシンプルになります。

# ~/.ssh/config
Host myserver
    HostName example.com
    User admin

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes

myserver に接続すると、個別設定に加えて Host *ServerAliveInterval 60 も適用されます。

$ ssh -G myserver | grep -E "^(hostname|user|serveraliveinterval) "
user admin
hostname example.com
serveraliveinterval 60

設定の優先順位(先勝ちルール)に注意する

SSH configで最もつまずきやすいのが優先順位です。OpenSSHは各パラメータについて最初にマッチした値を採用し、後から出てくる同じパラメータは無視します。上書きではなく「先勝ち」である点が、他の設定ファイル(後勝ちが多い)と逆なので注意が必要です。

そのため Host * のような汎用的なブロックは、必ず個別のHostブロックより後に書きます。先に書いてしまうと、個別設定より Host * の値が優先されてしまいます。

# NGな例: Host * が先頭にあると個別設定が無視される
Host *
    User wildcarduser
    Port 22

Host myserver
    HostName example.com
    User admin
    Port 2222
$ ssh -G myserver | grep -E "^(user|port) "
user wildcarduser
port 22

意図した admin / 2222 ではなく Host * の値が採用されているのが分かります。Host * は必ずファイルの末尾に置いてください。

接続を高速化する(ControlMaster / ControlPersist)

同じサーバーへ何度も接続し直す場合、ControlMaster による接続の使い回し(マルチプレクシング)が効果的です。最初の1回だけ本来の認証を行い、2回目以降はそのTCP接続を再利用するため、認証処理が省略されます。

# ~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h:%p
    ControlPersist 10m

ControlPath に指定したソケットファイルを置くディレクトリは、事前に作成しておく必要があります。

mkdir -p ~/.ssh/sockets

ローカルにテスト用のsshdを立てて実測したところ、1回目の接続(マスター確立込み)は約0.23秒だったのに対し、ControlPersist で維持されたマスター接続を再利用した2回目以降の接続は約0.008秒でした。回線やサーバー環境によって差はありますが、同じホストへ何度も接続・切断を繰り返す用途(デプロイスクリプトやrsyncの多重実行など)ほど効果を体感しやすくなります。マスター接続が有効かどうかは次のコマンドで確認できます。

$ ssh -O check myserver
Master running (pid=12345)

マスター接続を手動で終了したい場合は次のコマンドを使います。

ssh -O exit myserver

低速な回線を使う場合は Compression yes をあわせて設定すると、テキストベースの転送量が多い作業(ソースコードの同期など)で通信量を削減できます。バイナリファイル中心の転送では効果が薄いため、用途に応じて使い分けてください。

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

接続先が増えて1ファイルが肥大化してきたら、Include で用途別に分割できます。

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

Host myserver
    HostName example.com
    User admin
# ~/.ssh/conf.d/work.conf
Host workserver
    HostName work.example.com
    User worker

Include の相対パスは ~/.ssh を基準に解決されます。案件別・環境別(仕事用/個人用など)にファイルを分けておくと、管理しやすくなります。

よくあるトラブルと対処法

  • 設定が反映されない
    「先勝ちルール」により、同じパラメータが複数のマッチするHostブロックに書かれていないか確認します。とくに Host * がファイルの先頭にないか要チェックです。
  • Bad owner or permissions on ~/.ssh/config
    configファイルやディレクトリのパーミッションが緩いと出るエラーです。chmod 600 ~/.ssh/configchmod 700 ~/.ssh を実行します。
  • 特定のHostだけ設定が効かない
    Host の後ろの文字列は完全一致(ワイルドカード * / ? は使用可)です。ssh myserver.example.com のようにFQDNで接続すると、エイリアス myserver にはマッチしません。
  • 設定内容を事前に確認したい
    ssh -G ホスト名 で、実際に接続せずに解決後の設定値だけを一覧表示できます。別ファイルで試すときは ssh -F パス -G ホスト名 を使います。

接続そのものができない場合は SSH接続できないときのチェックリスト もあわせて確認してください。

よくある質問(FAQ)

Q. ~/.ssh/config がない場合はどうすればいいですか?

A. 自動生成されないため、touch ~/.ssh/config で新規作成し、chmod 600 ~/.ssh/config でパーミッションを設定してください。

Q. Windowsでも同じ書き方ができますか?

A. OpenSSH for Windowsであれば %USERPROFILE%\.ssh\config に同じ構文で設定できます。VS CodeのRemote-SSH拡張機能もこのファイルを参照します。

Q. StrictHostKeyChecking no は使ってもいいですか?

A. 中間者攻撃の検知を無効化するため、常時 no にするのは推奨しません。頻繁に作り直す検証環境などに限定し、必要なら accept-new(未知のホストキーのみ自動登録し、変化したホストキーは拒否する)を使う方が安全です。

Q. 同じサーバーへの接続を高速化するには?

A. ControlMaster autoControlPersist でマルチプレクシングを有効にすると、2回目以降の接続で認証処理が省略されます。設定方法は「接続を高速化する(ControlMaster / ControlPersist)」を参照してください。

関連コマンド

  • ssh
    SSH configが対象とする接続コマンド本体。基本構文やオプション一覧はこちら。
  • ssh-keygen
    IdentityFileに指定する鍵ペアを生成するコマンド。
  • ssh-copy-id
    生成した公開鍵をリモートサーバーへ登録するコマンド。
  • ssh-agent
    ForwardAgentやAddKeysToAgentと組み合わせて使う鍵管理エージェント。

参考

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント