~/.ssh/config による快適 SSH 環境

> 言いだしっぺの法則により、Advent Calendarのトップバッターになってしまったので、Web開発で便利なTipsを紹介したいと思います。

## 概要

`~/.ssh/config` にサーバーごとの接続設定を書いておくと、`ssh` コマンドや `scp` コマンドを実行するたびにいちいち引数を指定する必要がなくなり、幸せになれます。

## 初級編

### ユーザー名やポート番号の指定

通常、ログインユーザーとは異なるユーザーや、22番以外のポートを使ってSSH接続する場合は、次のようにコマンドライン引数で指定してあげる必要があります。

```bash:before
$ ssh -l sample 192.168.0.1
$ ssh –l foobar -p 2222 alpha
```

しかし、`~/.ssh/config` にあらかじめこれらの接続情報を設定しておくと、入力を省略できるようになるので便利です。

```:~/.ssh/config
Host 192.168.0.1
    User    sample
    Port    22
Host alpha
    User    foobar
    Port    2222
```

```bash:after
$ ssh 192.168.0.1  # => ssh -l sample -p 22   192.168.0.1
$ ssh alpha        # => ssh -l foobar -p 2222 alpha
```

### 秘密鍵の指定

同様に、秘密鍵の指定もサーバーごとにあらかじめ設定を済ませておくことができます。

```:~/.ssh/config
Host 192.168.0.2
    User            sample
    IdentityFile    ~/.ssh/id_rsa
    IdentitiesOnly  yes
Host beta
    User            foobar
    IdentityFile    ~/.ssh/id_rsa.beta
    IdentitiesOnly  yes
```

これでどのサーバーがどの秘密鍵だったか悩む必要がなくなります。

```bash:after
$ ssh 192.168.0.2  # => ssh -l sample -i ~/.ssh/id_rsa      192.168.0.2
$ ssh beta         # => ssh -l foobar -i ~/.ssh/id_rsa.beta beta
```

### ホストの別名の指定

サーバーの名前やIPアドレスが覚えづらい場合には、自分の好きな名前を付けることもできます。

```:~/.ssh/config
Host dev
    HostName    192.168.0.3
    User        sample
Host stg
    HostName    gamma
    User        foobar
```

```bash:after
$ ssh dev  # => ssh -l sample 192.168.0.3
$ ssh stg  # => ssh -l foobar gamma
```

### パスワードの指定

残念ながら、パスワード認証の場合のパスワードを `~/.ssh/config` に指定しておくことはできません。セキュリティ上の問題になりうるからだろうと思います。

## 中級編

### ワイルドカードによる指定

管理するサーバーの数が増えてくると、サーバーごとの設定を1台ずつ書くのは面倒です。連番や接頭辞などでサーバーがグループ化されている場合には、ワイルドカード (`*`, `?`) を使って指定できます。

```:~/.ssh/config
Host 192.168.100.*
    User    sample
    Port    22
Host build-0?
    User    foobar
    Port    2222
```

```bash:after
$ ssh 192.168.100.1   # => ssh -l sample -p 22 192.168.100.1
$ ssh 192.168.100.10  # => ssh -l sample -p 22 192.168.100.10

$ ssh build-01        # => ssh -l foobar -p 2222 build-01
$ ssh build-02        # => ssh -l foobar -p 2222 build-02
```

### コネクションの切断防止

しばらく操作しないでいると、知らぬ間に接続が切れていてイラっとすることがあります。そんなときはサーバーに定期的にパケットを送るようにすることで回避できます。

```:~/.ssh/config
Host 192.168.0.4
    User  sample
    Port  22
    ServerAliveInterval  60
```

### コネクションの再利用

なかにはパスワード認証が必要なサーバーも1台や2台はあるかもしれませんが、SSH接続するたびにパスワードを聞かれるのはやはり煩わしいですよね。

次の設定をしておくと、1つの接続で複数のセッションを共有できます。その結果、すでにサーバーと接続が確立していれば、2回目以降はパスワードを聞かれなくなります。`tmux` や `screen` などを使って複数ウィンドウで同時接続する人にはオススメです。

```:~/.ssh/config
Host 192.168.0.5
    User           sample
    ControlMaster  auto
    ControlPath    /tmp/%r@%h:%p
```

```bash:after
(端末1) $ ssh 192.168.0.5  # => パスワード入力が必要
(端末2) $ ssh 192.168.0.5  # => パスワード入力が不要
```

## 上級編

### 踏み台サーバーの指定

本番サーバーなど一部のサーバーは踏み台サーバー経由でしかアクセスできないようになっていると思います。通常であれば、まず踏み台サーバーにSSH接続し、そこから改めて目的のサーバーに接続すると思います。

```bash:before
$ ssh jump
[foobar@jump:~/] $ ssh target
[admin@target:~/] $
```

しかし、`~/.ssh/config` に多段SSH接続の設定をしておくと、あたかも対象サーバーへ直接接続しているかのようにログインすることができます。秘密鍵を踏み台サーバーに配置する必要もなく非常にお手軽です。ただし、お手軽すぎて「踏み台サーバー経由である」ことすら忘れてしまいがちなので、注意してください。

```:~/.ssh/config
Host jump
    User          foobar
    Port          22
    IdentityFile  ~/.ssh/id_rsa
Host target
    User          admin
    Port          2222
    IdentityFile  ~/.ssh/id_rsa.target
    ProxyCommand  ssh -W %h:%p jump
```

```bash:after
$ ssh target  # => jump 経由で target へログイン
```

### 設定ファイルの分割

ここまでくると、開発プロジェクトごとに動作確認環境やステージング環境の設定をまとめて、メンバー間で共有したい！というニーズが出てくると思います。が、`~/.ssh/config` の機能としては分割する仕組みはありません。

代わりに、自前で連結するハックが知られています。例えば、次のようなディレクトリ構成にしておけば、`cat` コマンドで簡単に `~/.ssh/config` ファイルを生成することができます。

```
├── conf.d
│   ├── config           # => 自分専用の設定
│   ├── project1.config  # => project1 用の共有設定
│   └── project2.config  # => project2 用の共有設定
├── config               # => 生成される最終設定
├── id_rsa
├── id_rsa.pub
└── known_hosts
```

```bash
$ cat ~/.ssh/conf.d/* > ~/.ssh/config
```

手打ちするのが面倒な場合は、`ssh` コマンドなどに `alias` を設定しておくのも手です。

```bash
alias ssh="cat ~/.ssh/conf.d/* > ~/.ssh/config;ssh"
alias scp="cat ~/.ssh/conf.d/* > ~/.ssh/config;scp"
alias git="cat ~/.ssh/conf.d/* > ~/.ssh/config;git"
```

## まとめ

この記事では、開発者がよく使う `ssh` コマンドを便利に使うための `~/.ssh/config` について紹介しました。本文中では `ssh` コマンドを例に説明しましたが、そのまま `scp` コマンドにも適用されます。地味ではありますが、最初に1回だけ設定してしまえば、その後 `ssh`, `scp` コマンドを使う度にじわじわ効いてきますので、ぜひ試してみてください。

それでは快適なSSH生活をお楽しみください！