ssh-copy-idの使い方 完全ガイド:SSH鍵認証を簡単設定
はじめに – SSH鍵認証をもっと手軽に
インターネット上でサーバーを管理したり、複数のコンピュータ間で安全に通信したりする際に、SSH (Secure Shell) は不可欠なツールです。SSHを使うことで、暗号化された通信路を通じて、リモートマシンにログインしたり、ファイルを安全に転送したりすることができます。
SSHの認証方式にはいくつか種類がありますが、最も一般的で推奨されているのが「公開鍵認証」です。パスワード認証に比べて、推測されにくい長い鍵を使用するためセキュリティが高く、一度設定すればパスワードを入力する手間がなくなるため、サーバー管理者にとって非常に便利です。
しかし、このSSH公開鍵認証を設定する作業は、特に初心者にとっては少し面倒に感じられるかもしれません。クライアント側で鍵ペア(公開鍵と秘密鍵)を生成し、その公開鍵をリモートサーバーの特定のディレクトリ(通常 ~/.ssh
)にある authorized_keys
というファイルに追記し、さらにこれらのファイルやディレクトリのパーミッション(アクセス権限)を適切に設定する必要があります。これらのステップを手動で行うのは、ファイルパスを間違えたり、パーミッションの設定を忘れたりといったミスにつながりやすく、SSH接続がうまくいかない原因となることがあります。
そこで登場するのが、ssh-copy-id
コマンドです。このコマンドは、前述した一連の公開鍵設定作業を自動で行ってくれる、まさに救世主のようなツールです。ssh-copy-id
を使うことで、複雑な手順を意識することなく、コマンド一つで簡単にSSH鍵認証を設定できます。
この記事では、ssh-copy-id
コマンドの使い方を、基本的なことから応用に至るまで、徹底的に詳しく解説します。コマンドの実行方法はもちろん、その内部で何が行われているのか、どのようなオプションがあるのか、そして困ったときにどう対処すれば良いのかまで、網羅的に説明します。この記事を読めば、あなたはSSH鍵認証設定の達人となり、より安全で効率的なリモート作業が可能になるでしょう。
さあ、ssh-copy-id
の世界へ踏み込み、SSH鍵認証をマスターしましょう!
SSH鍵認証の基礎をおさらい
ssh-copy-id
の使い方に入る前に、SSH鍵認証の仕組みを簡単におさらいしておきましょう。すでに理解している方は、この章をスキップしても構いません。
SSH鍵認証は、クライアント(あなたのPCなど)とサーバー(リモートホスト)の間で、「公開鍵」と「秘密鍵」というペアの鍵を使って認証を行う方式です。
-
鍵ペアの生成: まず、クライアントマシン上で
ssh-keygen
コマンドなどを使って、公開鍵と秘密鍵のペアを生成します。デフォルトでは、これらの鍵はクライアントのユーザーのホームディレクトリ直下にある.ssh
ディレクトリに保存されます(例:~/.ssh/id_rsa
が秘密鍵、~/.ssh/id_rsa.pub
が公開鍵)。- 秘密鍵 (Private Key): クライアントマシンに厳重に保管されるべき鍵です。この鍵を持っている人だけが、対応する公開鍵が登録されたサーバーにログインできます。絶対に他人に見せてはいけません。 通常、ファイル名は
id_rsa
やid_ed25519
のようになっています。 - 公開鍵 (Public Key): 秘密鍵とペアになる鍵で、サーバー側に配置します。公開鍵は他の人に見られても問題ありません。通常、ファイル名は対応する秘密鍵の名前に
.pub
が付いたもの(例:id_rsa.pub
,id_ed25519.pub
)になっています。公開鍵ファイルの中身は、ssh-rsa AAAA...
あるいはssh-ed25519 AAAA...
のような文字列と、ユーザー名やホスト名を含むコメントで構成されます。
- 秘密鍵 (Private Key): クライアントマシンに厳重に保管されるべき鍵です。この鍵を持っている人だけが、対応する公開鍵が登録されたサーバーにログインできます。絶対に他人に見せてはいけません。 通常、ファイル名は
-
公開鍵の配置: 生成した公開鍵 (
id_rsa.pub
など) の内容を、接続したいリモートサーバーのユーザーのホームディレクトリにある.ssh
ディレクトリ内のauthorized_keys
というファイルに追記します。このファイルは、そのユーザーアカウントに対して鍵認証を許可する公開鍵のリストです。 -
認証の仕組み: クライアントがSSH接続を試みると、以下のやり取りが行われます。
- サーバーはクライアントに対して、ランダムなデータ(チャレンジ)を送信します。
- クライアントは、手元の秘密鍵を使ってそのチャレンジデータを暗号化し、サーバーに送り返します。
- サーバーは、クライアントから受け取った暗号化データを、
authorized_keys
に登録されている公開鍵のいずれかを使って復号化しようとします。 - もし、秘密鍵とペアになっている公開鍵で正常に復号化できた場合、サーバーはクライアントが正当なユーザーであると判断し、認証成功となります。
この仕組みにより、パスワードを知らなくても、秘密鍵を持っているクライアントだけがサーバーにログインできるようになります。そして、authorized_keys
ファイルこそが、サーバー側で「誰の公開鍵を信用するか」を管理する重要なファイルなのです。
手動で鍵認証を設定する際は、以下のステップを踏むことになります。
- クライアントで鍵ペアを生成 (
ssh-keygen
)。 - クライアントの公開鍵の内容を表示 (
cat ~/.ssh/id_rsa.pub
)。 - リモートサーバーにパスワード認証でログイン (
ssh user@remote_host
)。 - リモートサーバー上で
.ssh
ディレクトリが存在しない場合は作成 (mkdir ~/.ssh
)。 .ssh
ディレクトリのパーミッションを700
に設定 (chmod 700 ~/.ssh
)。- 公開鍵の内容を
~/.ssh/authorized_keys
ファイルに追記(コピー&ペーストまたはリダイレクトecho "..." >> ~/.ssh/authorized_keys
)。 authorized_keys
ファイルのパーミッションを600
に設定 (chmod 600 ~/.ssh/authorized_keys
)。- パスワード認証でログアウトし、鍵認証で再接続を試みる (
ssh user@remote_host
)。
これらのステップは、特に複数のサーバーに設定する場合や、新しいマシンから接続する場合に繰り返す必要があり、手間がかかりますし、パーミッション設定を間違えたりすると鍵認証が機能しない原因となります。ここで ssh-copy-id
が活躍するのです。
ssh-copy-id
とは何か? 何をしてくれるのか?
ssh-copy-id
は、名前の通り「SSHのID(公開鍵)をコピーする」ためのコマンドです。より正確には、ローカルマシンにあるSSH公開鍵の内容を、リモートホストの指定したユーザーの ~/.ssh/authorized_keys
ファイルに追記するためのシェルスクリプトです。
このコマンドの主な目的は、前章で述べた手動での公開鍵設定作業を自動化し、鍵認証のセットアッププロセスを大幅に簡略化することです。
ssh-copy-id
を実行すると、具体的には以下のステップが自動的に行われます。
- リモートホストへの接続: 指定されたユーザー名とホスト名を使って、リモートホストへのSSH接続を試みます。この接続は、最初にパスワード認証(または他の利用可能な認証方法)を使用して行われます。初回接続時には、リモートホストのフィンガープリント(ホストキー)を確認するメッセージが表示され、
yes
と入力して接続を続行する必要があります。 - リモートの
.ssh
ディレクトリ確認・作成: リモートホスト上で、指定されたユーザーのホームディレクトリに.ssh
ディレクトリが存在するか確認します。存在しない場合は新しく作成します (mkdir -p ~/.ssh
)。 .ssh
ディレクトリのパーミッション設定: 作成または確認した.ssh
ディレクトリのパーミッションを700
(所有者のみ読み書き実行可能) に設定します (chmod 700 ~/.ssh
)。これはSSHが要求する適切なパーミッションです。- リモートの
authorized_keys
ファイル確認・作成:.ssh
ディレクトリ内にauthorized_keys
ファイルが存在するか確認します。存在しない場合は新しく作成します。 - ローカル公開鍵の取得: ローカルマシンで、デフォルトの公開鍵ファイル(通常
~/.ssh/id_rsa.pub
または他の種類の鍵)の内容を取得します。-i
オプションで別の公開鍵を指定することも可能です。 authorized_keys
への公開鍵追記: 取得したローカルの公開鍵の内容を、リモートの~/.ssh/authorized_keys
ファイルの末尾に追記します (cat >> ~/.ssh/authorized_keys
)。既に同じ公開鍵がファイルに存在する場合、多くのバージョンのssh-copy-id
は重複を検出して追記しないように動作します。authorized_keys
ファイルのパーミッション設定:authorized_keys
ファイルのパーミッションを600
(所有者のみ読み書き可能) に設定します (chmod 600 ~/.ssh/authorized_keys
)。これもSSHが要求する適切なパーミッションです。
これらのステップは、手動で行うとコマンドを複数回実行したり、ファイルの内容をコピー&ペーストしたりする必要があり、面倒でエラーの元になりがちです。ssh-copy-id
は、これらの操作をまとめて、ユーザーはリモートホストのパスワードを入力するだけで済むようにしてくれます。
ssh-copy-id
を使う最大のメリットは以下の通りです。
- 簡単さ: コマンド一つで完了します。
- 確実性:
.ssh
ディレクトリやauthorized_keys
ファイルの作成、公開鍵の追記、そして最も忘れがちなパーミッション設定まで、SSH鍵認証に必要な一連の作業を漏れなく行います。 - エラーの削減: 手動入力によるミス(ファイルパス、コマンド、パーミッションなど)を防ぎます。
- 重複防止: 多くの実装では、既に登録されている公開鍵を二重に登録するのを防ぎます。
つまり、ssh-copy-id
はSSH鍵認証を設定する上で、最も簡単かつ確実な方法を提供してくれるツールなのです。
ssh-copy-id
の基本的な使い方:パスワード認証から鍵認証へ
それでは、ssh-copy-id
の最も基本的で一般的な使い方を見ていきましょう。これは、パスワード認証が可能なリモートホストに対して、手元のデフォルトの公開鍵を使って鍵認証を設定するケースです。
前提条件:
- ローカルマシンにSSHクライアントがインストールされていること。
- ローカルマシンにSSH鍵ペア(公開鍵と秘密鍵)が生成されていること。デフォルトの場所 (
~/.ssh/id_rsa.pub
など) に存在する場合、特別なオプションは不要です。まだ鍵ペアを持っていない場合は、ssh-keygen
コマンドで生成してください (ssh-keygen -t rsa -b 4096
またはssh-keygen -t ed25519
が推奨されます)。 - リモートホストにSSHサーバーが起動しており、パスワード認証が可能であること。
- リモートホストに、鍵認証を設定したいユーザーアカウントが存在すること。
基本的なコマンド形式:
bash
ssh-copy-id [options] [user@]hostname
[options]
: 後述するオプションを指定します。基本的には不要です。[user@]hostname
: 接続先のリモートホストを指定します。user
はリモートホストのユーザー名、hostname
はリモートホストのホスト名またはIPアドレスです。ローカルのユーザー名とリモートのユーザー名が同じ場合は、user@
を省略してhostname
だけを指定することもできます。
実行例:
例えば、リモートホスト remote-server.example.com
のユーザー myuser
に対して、手元の公開鍵を登録したい場合、ローカルマシンで以下のコマンドを実行します。
bash
ssh-copy-id [email protected]
コマンドを実行すると、以下のような流れで処理が進みます。
-
リモートホストのフィンガープリント確認 (初回接続時):
The authenticity of host 'remote-server.example.com (192.168.1.100)' can't be established.
ECDSA key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no)?
これは、初めてそのリモートホストに接続する際に表示されるメッセージです。表示されているフィンガープリントが信頼できるものであることを確認し(組織の管理者から聞くなど)、問題なければyes
と入力してEnterキーを押します。これにより、リモートホストの公開鍵がローカルの~/.ssh/known_hosts
ファイルに記録され、次回以降はこのメッセージは表示されません(ホスト鍵が変更された場合を除く)。 -
リモートユーザーのパスワード入力:
Warning: Permanently added 'remote-server.example.com' (ECDSA) to the list of known hosts.
[email protected]'s password:
リモートホスト上のユーザーmyuser
のパスワード入力が求められます。正確に入力してEnterキーを押します。ここで求められるのは、鍵認証を設定したいリモートユーザーのパスワードです。 -
公開鍵のコピーと設定:
パスワードが正しければ、ssh-copy-id
はリモートホストに接続し、前章で説明した一連の自動処理(.ssh
ディレクトリやauthorized_keys
ファイルの作成・パーミッション設定、公開鍵の追記)を実行します。この間、通常はいくつかのメッセージが表示されます。 -
成功メッセージ:
処理が正常に完了すると、以下のような成功を示すメッセージが表示されます。“`
Number of key(s) added: 1Now try logging into the machine, with: “ssh ‘[email protected]'”
and check to make sure that only the key(s) you wanted were added.
“`このメッセージは、「公開鍵が1つ追加されました」という結果と、「これでパスワードなしでSSH接続できるはずなので試してみてください」というガイダンスを示しています。
設定後の確認:
ssh-copy-id
の実行が成功したら、本当にパスワードなしでSSH接続できるようになったか確認しましょう。以下のコマンドを実行します。
bash
ssh [email protected]
もし設定が正しく行われていれば、パスワード入力は求められず、直接リモートホストのコマンドプロンプトが表示されるはずです。
bash
Last login: Tue Oct 26 10:00:00 2023 from your-local-ip
[myuser@remote-server ~]$
これで、myuser
として remote-server.example.com
へのSSH鍵認証設定が完了しました。次回以降の接続は、パスワードなしでスムーズに行えます。
もしパスワードを求められる場合は、設定に問題がある可能性があります。その場合は、後述の「トラブルシューティング」の章を参照してください。
ssh-copy-id
の内部を探る:コマンドの裏側
ssh-copy-id
コマンドは、実際にはシェルスクリプトとして実装されています。多くのLinuxディストリビューションやmacOSに含まれており、内部で標準の ssh
コマンドなどを組み合わせて実行しています。
基本的な使い方で見たように、ssh-copy-id user@remote_host
というシンプルなコマンドの裏側では、実はもう少し複雑な処理が行われています。その仕組みを理解することで、コマンドの動作原理が分かり、トラブルシューティングや応用的な使い方をする際に役立ちます。
ssh-copy-id
が実行する主なステップは以下の通りです(具体的な実装はバージョンやOSによって多少異なりますが、概念は共通です)。
-
ローカルで使用する公開鍵の特定:
ssh-copy-id
は、デフォルトでは~/.ssh/id_rsa.pub
,~/.ssh/id_dsa.pub
,~/.ssh/id_ecdsa.pub
,~/.ssh/id_ed25519.pub
といった標準的な名前の公開鍵ファイルを順番に探し、最初に見つかったもの、または-i
オプションで指定された公開鍵を使用します。見つかった公開鍵ファイルの内容を読み込みます。 -
リモートホストへの接続とコマンド実行:
ssh-copy-id
は、指定されたuser@remote_host
に対して 一度だけ SSH接続を確立します。この接続確立時に、リモートホスト上で複数のコマンドを実行します。これは、複数のSSHセッションを確立するよりも効率的です。内部で実行されるリモートコマンドは、概ね以下のような処理をまとめて行います。
-
.ssh
ディレクトリの作成とパーミッション設定:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
mkdir -p
は、ディレクトリが存在しない場合にのみ作成し、親ディレクトリもまとめて作成します。chmod 700
は、作成した.ssh
ディレクトリのパーミッションを所有者のみ読み書き実行可 (drwx------
) に設定します。これはSSHの要件です。 -
authorized_keys
ファイルへの公開鍵追記とパーミッション設定:
cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
ここで、ローカルの公開鍵の内容が、SSH接続の標準入力としてリモートホストに渡されます。リモート側ではcat
コマンドが標準入力から読み込んだ内容を>> ~/.ssh/authorized_keys
によってauthorized_keys
ファイルの末尾に追記します。
追記後、&&
で繋がれた次のコマンドchmod 600 ~/.ssh/authorized_keys
が実行され、authorized_keys
ファイルのパーミッションが所有者のみ読み書き可 (-rw-------
) に設定されます。これもSSHが鍵認証でこのファイルを読み込むための必須要件です。多くの場合、
ssh-copy-id
は追記する前に、リモートのauthorized_keys
ファイル内に既に同じ公開鍵が存在しないかを確認し、重複している場合は追記をスキップするロジックを含んでいます。この確認も、リモートでSSHコマンドを使ってファイルの内容をチェックすることで実現されます。
これらのリモートコマンドは、
ssh user@remote_host 'command1 && command2 && command3 ...'
のように、一つのSSHセッション内でまとめて実行されることが多いです。例えば、シンプル化すると以下のようなSSHコマンドが内部で実行されているイメージです。bash
ssh user@remote_host \
'mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys' \
< ~/.ssh/id_rsa.pub
このコマンドは、ローカルの~/.ssh/id_rsa.pub
ファイルの内容を標準入力 (< ~/.ssh/id_rsa.pub
) としてssh
コマンドに渡しています。リモートで実行される'...'
内のコマンドでは、cat >> ~/.ssh/authorized_keys
がその標準入力を受け取り、authorized_keys
ファイルに追記する、という流れです。ssh-copy-id
は、これらの処理に必要なロジック(使用する公開鍵の特定、重複チェック、パーミッションチェックなど)を自動で行ってくれるラッパーコマンドです。手動で同じことをしようとすると、上記の複雑なコマンドを正確に入力する必要があり、特にパーミッション設定は忘れがちです。ssh-copy-id
は、これらの手間とエラーの可能性を排除し、確実に鍵認証を設定するためのツールとして設計されています。 -
さらに使いこなす:ssh-copy-id
の便利なオプション
ssh-copy-id
はシンプルなコマンドですが、いくつかの便利なオプションが用意されています。これらを活用することで、デフォルト以外の公開鍵を使ったり、非標準的なポート番号でSSHサーバーが動作している場合にも対応したりできます。
1. 使用する公開鍵を指定する (-i identity_file
)
デフォルトでは、ssh-copy-id
は標準的な公開鍵ファイル (~/.ssh/id_rsa.pub
など) を探して使用します。しかし、複数の鍵ペアを持っていて、特定の公開鍵をリモートホストに登録したい場合があります。そのような場合は、-i
オプションを使用します。
-i
オプションの引数には、使用したい公開鍵ファイルのパスを指定します。
bash
ssh-copy-id -i /path/to/your/public/key.pub [user@]hostname
注意: -i
オプションには、対応する秘密鍵ではなく、公開鍵ファイルのパスを指定します。公開鍵ファイルは通常 .pub
という拡張子が付いています。
実行例:
例えば、~/.ssh/my_new_key.pub
という公開鍵を remote-server.example.com
のユーザー myuser
に登録したい場合:
bash
ssh-copy-id -i ~/.ssh/my_new_key.pub [email protected]
このコマンドを実行すると、ssh-copy-id
は指定された ~/.ssh/my_new_key.pub
ファイルの内容をリモートホストにコピーしようとします。それ以外の挙動(パスワード入力要求、リモートでのファイル操作など)は基本的な使い方と同じです。
2. SSHポートを指定する (-p port
または -o "Port=port"
)
リモートホストのSSHサーバーがデフォルトの22番ポート以外で動作している場合があります。そのような場合、ssh-copy-id
はデフォルトで22番ポートに接続しようとするため、接続できません。SSHポートを指定するには、以下の2つの方法があります。
-
-p port
オプション:
最も簡単な方法は-p
オプションを使うことです。これはssh
コマンドの-p
オプションと全く同じ働きをします。bash
ssh-copy-id -p 2222 [user@]hostname実行例:
リモートホスト
remote-server.example.com
のユーザーmyuser
に対して、SSHサーバーがポート2222
で動作している場合に鍵認証を設定したい場合:bash
ssh-copy-id -p 2222 [email protected] -
-o "Option=value"
オプション:
ssh-copy-id
は内部でssh
コマンドを呼び出しているため、ssh
コマンドで使える設定オプションを-o
オプションを使って渡すことも可能です。ポートを指定する場合は、-o "Port=port"
とします。bash
ssh-copy-id -o "Port=2222" [user@]hostname実行例:
上記の例を
-o
オプションで実現する場合:bash
ssh-copy-id -o "Port=2222" [email protected]-o
オプションはポート指定以外にも、より詳細なSSHクライアントの設定(例:ConnectTimeout=10
,IdentityFile=...
など)を渡すことができるため、より柔軟な設定が可能です。-i
オプションと異なり、-o "IdentityFile=/path/to/your/private/key"
のように秘密鍵ファイルを指定することに注意してください(SSHクライアントのIdentityFile
オプションは秘密鍵を指定するため)。ただし、公開鍵を指定する-i
オプションの方が直感的で一般的です。~/.ssh/config
ファイルとの関連:
ssh-copy-id
は内部でssh
コマンドを呼び出すため、ローカルの~/.ssh/config
ファイルにリモートホストの設定が記述されていれば、その設定(例: ホスト名、ユーザー名、ポート番号、IdentityFileなど)が自動的に適用されます。
例えば、~/.ssh/config
に以下のような設定がある場合:Host remote-server
Hostname remote-server.example.com
User myuser
Port 2222
IdentityFile ~/.ssh/my_special_keyこの設定がある状態で以下のコマンドを実行すると:
bash
ssh-copy-id remote-serverssh-copy-id
は~/.ssh/config
の設定を読み取り、ユーザーmyuser
、ホスト名remote-server.example.com
、ポート2222
を使用して接続しようとします。また、使用する公開鍵はIdentityFile ~/.ssh/my_special_key
に対応する~/.ssh/my_special_key.pub
となります(-i
オプションで明示的に指定されていない場合)。このように、~/.ssh/config
を活用することで、コマンドラインでのオプション指定を省略することも可能です。
3. 冗長出力を有効にする (-v
)
コマンドが意図した通りに動作しない場合や、内部で何が行われているのか詳しく確認したい場合に便利なのが -v
オプションです。これは ssh
コマンドの -v
オプションと同様に、処理の進行状況やデバッグ情報を詳細に表示します。
bash
ssh-copy-id -v [user@]hostname
実行例:
bash
ssh-copy-id -v [email protected]
-v
オプションを付けると、ssh-copy-id
がリモートホストへの接続を確立する過程、認証の試行、リモートで実行しているコマンドなどが逐一表示されます。エラーが発生した場合、どの段階で問題が起きているのかを特定するのに役立ちます。
4. 標準入力から公開鍵を読み込む (-
ハイフン)
通常、ssh-copy-id
はファイルから公開鍵を読み込みますが、標準入力から公開鍵の内容を受け取るように指定することもできます。これは、公開鍵を一時的に生成してファイルに保存せずに直接 ssh-copy-id
に渡したい場合などに便利です。標準入力を指定するには、ホスト名の代わりに -
(ハイフン) を使用します。
bash
cat /path/to/your/public/key.pub | ssh-copy-id - [user@]hostname
または、ssh-keygen -y
コマンドで秘密鍵から公開鍵を生成して直接パイプで渡すこともできます。
bash
ssh-keygen -y -f /path/to/your/private/key | ssh-copy-id - [user@]hostname
実行例:
デフォルトの秘密鍵 ~/.ssh/id_rsa
に対応する公開鍵を、ファイルから読み込むのではなく、ssh-keygen -y
で生成して直接 remote-server.example.com
のユーザー myuser
に登録する場合:
bash
ssh-keygen -y -f ~/.ssh/id_rsa | ssh-copy-id - [email protected]
この方法は、公開鍵ファイルが手元にない場合や、一時的な公開鍵を使いたい場合に便利です。
これらのオプションを組み合わせることも可能です。例えば、非標準ポートで動作するリモートホストに、デフォルト以外の公開鍵を使って設定する場合:
bash
ssh-copy-id -i ~/.ssh/my_other_key.pub -p 2222 [email protected]
ssh-copy-id
のマニュアル (man ssh-copy-id
) を参照すれば、さらに詳細なオプションや挙動について確認できます。しかし、ここで紹介したオプションが、日常的なSSH鍵認証設定のほとんどのケースをカバーできるでしょう。
困ったときは? ssh-copy-id
のトラブルシューティング
ssh-copy-id
は通常非常にうまく機能しますが、環境によっては問題が発生することもあります。コマンドが成功しない場合、以下の点をチェックし、対処してみてください。
1. コマンド入力や基本設定の確認
まず基本に戻って、コマンドの入力ミスがないか、前提条件を満たしているかを確認します。
- コマンド形式:
ssh-copy-id [user@]hostname
の形式が正しいか。ユーザー名を省略している場合、ローカルユーザー名とリモートユーザー名が一致しているか。 - ホスト名/IPアドレス: リモートホストのホスト名やIPアドレスが正しいか。名前解決ができているか (
ping hostname
)。 - ユーザー名: リモートホスト上のユーザー名が正しいか。そのユーザーアカウントが存在し、ログイン可能か。
- パスワード:
ssh-copy-id
実行時に求められるリモートユーザーのパスワードが正しいか。パスワード認証自体でリモートログインできるか確認してください (ssh user@hostname
)。パスワード認証ができない場合は、リモートホスト側の設定やアカウントに問題があります。 - SSHサーバーの状態: リモートホストでSSHサーバー (
sshd
) が起動しているか (systemctl status sshd
など)。 - ファイアウォール: クライアント側とサーバー側の両方で、SSHポート(デフォルトは22番、または設定されたポート)がファイアウォールでブロックされていないか確認してください。
- 公開鍵ファイルの存在と内容:
-i
オプションを使っている場合、指定した公開鍵ファイルが存在し、正しい形式 (ssh-rsa AAAA...
などで始まる文字列) で書かれているか確認してください。デフォルトの鍵を使う場合も、~/.ssh/id_rsa.pub
などが存在するか確認します。cat ~/.ssh/id_rsa.pub
で内容を表示してみましょう。
2. エラーメッセージから原因を探る
ssh-copy-id
が失敗した場合、通常はエラーメッセージが表示されます。そのメッセージを注意深く読むことが、原因特定の手がかりになります。
-
Permission denied, please try again.
またはPermission denied (publickey,password,...)
:- パスワード入力時: 入力したパスワードが間違っています。
- パスワード入力がスキップされ、いきなり拒否される: 公開鍵認証やパスワード認証以外の認証方法(例: GSSAPI)が試され、それが失敗している可能性があります。または、リモートホストの
sshd_config
でパスワード認証が無効になっているのに、鍵認証もまだ機能しない状態かもしれません。 ssh -v user@hostname
でパスワード認証できるか試してみてください。パスワード認証が成功するなら、ssh-copy-id
コマンドの再実行で解決することが多いです。
-
Host key verification failed.
:
リモートホストのSSHホスト鍵が以前接続した時と変わっています。これは、リモートホストが再インストールされたか、あるいは中間者攻撃の可能性があります。正当な変更であれば、ローカルの~/.ssh/known_hosts
ファイルから該当するホストのエントリを削除(エラーメッセージに削除すべき行番号が表示されることが多いです)してから再試行してください。 -
No such file or directory
:
-i
オプションで指定した公開鍵ファイルのパスが間違っているか、ファイルが存在しません。正しいパスを指定してください。 -
ssh: connect to host ... port ...: Connection refused
:
リモートホストのSSHサーバーが起動していないか、指定したポートで待機していません。または、ファイアウォールによって接続が拒否されています。リモートホストの状態とファイアウォール設定を確認してください。 -
ssh: connect to host ... port ...: Network is unreachable
またはConnection timed out
:
リモートホストが存在しない、ネットワーク的に到達できない、またはファイアウォールで完全にブロックされています。ネットワーク接続、ホスト名/IPアドレス、ファイアウォール設定を確認してください。
3. リモートホスト側の設定を確認する(sshd_config
)
ssh-copy-id
はリモートホスト側のSSHサーバー設定が適切であることを前提としています。リモートホストの /etc/ssh/sshd_config
ファイルを確認し、必要に応じて設定を変更し、SSHサービスを再起動 (systemctl restart sshd
) してください。
PubkeyAuthentication yes
: 公開鍵認証が有効になっているか確認します。通常はデフォルトで有効ですが、無効になっている場合はyes
に変更します。AuthorizedKeysFile .ssh/authorized_keys
:authorized_keys
ファイルの場所がデフォルト (.ssh/authorized_keys
) から変更されていないか確認します。変更されている場合は、ssh-copy-id
が内部で使用するコマンド形式を調整する必要があるかもしれません(通常、デフォルトの場所が使われます)。PermitRootLogin no
: rootユーザーへの直接ログインが許可されていない場合、root宛ての鍵認証設定はできません。許可する場合は設定を変更する必要がありますが、通常はセキュリティのため非推奨です。AllowUsers
,AllowGroups
,DenyUsers
,DenyGroups
: これらの設定で、鍵認証を設定したいユーザーやグループがSSH接続を許可されているか確認します。
4. リモートホスト側のディレクトリ・ファイルのパーミッションを確認する
SSH鍵認証が機能するためには、リモートホスト上の以下のディレクトリとファイルのパーミッションが適切である必要があります。ssh-copy-id
は自動で設定しようとしますが、何らかの理由で失敗したり、後から手動で変更してしまったりする可能性があります。
- ユーザーのホームディレクトリ: 所有者のみ書き込み可能 (
drwx------
またはdrwxr-x---
のような設定)。他のユーザーが書き込める設定 (drwxrwxrwx
など) になっていると、SSHはセキュリティ上の理由から鍵認証を拒否します。
bash
chmod go-w ~ ~/.ssh
ディレクトリ: 所有者のみ読み書き実行可能 (drwx------
)。
bash
chmod 700 ~/.ssh~/.ssh/authorized_keys
ファイル: 所有者のみ読み書き可能 (-rw-------
)。
bash
chmod 600 ~/.ssh/authorized_keys
これらのパーミッションを手動で修正した後、再度ssh user@hostname
で鍵認証を試してみてください。
5. SELinuxなどのセキュリティ機構
SELinux (Security-Enhanced Linux) や AppArmor のようなセキュリティ機構が有効になっている場合、SSH関連のファイルへのアクセスが制限されている可能性があります。SELinuxが原因の場合は、ログ (/var/log/audit/audit.log
など) を確認し、適切なSELinuxコンテキストが設定されているか確認します。必要なSELinux Booleanを有効にしたり、ファイルのコンテキストを修正したりする必要があるかもしれません (restorecon -Rv ~/.ssh
)。これはより高度なトラブルシューティングになります。
6. デバッグオプション -v
を活用する
トラブルシューティングの強力な味方が -v
オプションです。ssh-copy-id -v user@hostname
を実行し、出力される詳細なログを一つずつ確認します。どのステップ(鍵の読み込み、リモートへのSSH接続、リモートでのコマンド実行など)で問題が発生しているのかが特定しやすくなります。
7. サーバー側のログを確認する
リモートホスト側のSSHサーバーのログファイルを確認することも重要です。主なログファイルの場所はOSによって異なります。
- Debian/Ubuntu系:
/var/log/auth.log
- RHEL/CentOS/Fedora系:
/var/log/secure
これらのログファイルには、SSH接続の試行、認証の成否、エラーメッセージなどが記録されています。ssh-copy-id
が失敗した時間帯のログを確認し、鍵認証が拒否された理由(例: “Authentication refused: bad ownership or modes for directory /home/myuser”, “Authentication refused: bad ownership or modes for file /home/myuser/.ssh/authorized_keys”, “Authenticaton refused: key not in authorized_keys” など)を探します。
これらのステップを踏むことで、ssh-copy-id
が失敗するほとんどの原因を特定し、解決することができるはずです。
発展的な使い方:複数サーバーへの展開、踏み台サーバー経由
ssh-copy-id
は単一のリモートホストへの鍵設定に便利ですが、少し工夫することで、より多くのシナリオで役立てることができます。
1. 複数のサーバーにまとめて設定する
管理対象のサーバーが複数ある場合、それぞれのサーバーに対して ssh-copy-id
コマンドを手動で実行していくのは手間がかかります。このような場合は、シェルスクリプトを使って複数のホストに対して自動的に ssh-copy-id
を実行させることができます。
例えば、servers.txt
というファイルに接続先のホスト名やIPアドレスがリストされているとします。
server1.example.com
server2.example.com
192.168.1.10
このリストを使って、それぞれのサーバーに鍵認証を設定するシェルスクリプトは以下のようになります。
“`bash
!/bin/bash
設定したいユーザー名
REMOTE_USER=”myuser”
サーバーリストファイル
SERVER_LIST=”servers.txt”
使用する公開鍵ファイル (デフォルト以外の場合)
PUBLIC_KEY=”~/.ssh/my_special_key.pub” # 必要に応じてコメントを外して指定
サーバーリストを読み込み、各サーバーに対してssh-copy-idを実行
while IFS= read -r HOST
do
# 空行やコメント行をスキップ
[[ -z “$HOST” || “$HOST” =~ ^# ]] && continue
echo "--- Copying key to $HOST for user $REMOTE_USER ---"
# ssh-copy-id コマンドを構築
SSH_COPY_CMD="ssh-copy-id ${REMOTE_USER}@${HOST}"
# もしPUBLIC_KEYが指定されていればオプションを追加
# if [ -n "$PUBLIC_KEY" ]; then
# SSH_COPY_CMD="ssh-copy-id -i $PUBLIC_KEY ${REMOTE_USER}@${HOST}"
# fi
# コマンドを実行
# コマンドが失敗してもスクリプトが停止しないように || true を追加
$SSH_COPY_CMD || echo "### Failed to copy key to $HOST ###"
echo "" # 見やすくするために改行
done < “$SERVER_LIST”
echo “— Key copy process finished —”
“`
このスクリプトを実行する前に、REMOTE_USER
や SERVER_LIST
を環境に合わせて修正してください。PUBLIC_KEY
を使う場合はコメントを外します。
このスクリプトを実行すると、リストされたサーバーに対して順番に ssh-copy-id
が試行されます。それぞれのサーバーへの初回接続時にはホストキーの確認が、そしてパスワード認証が有効な場合はパスワード入力が求められます。一度実行すれば、パスワード入力の手間は初回のみとなります。
構成管理ツールとの連携:
より大規模な環境や、継続的なサーバー構成管理を行っている場合は、Ansible, Chef, Puppet といった構成管理ツールを使用する方が推奨されます。これらのツールは、SSH鍵認証設定を含む、より複雑なサーバー設定をコードとして管理し、自動的に適用することができます。例えば、Ansibleには authorized_key
というモジュールがあり、これを使えば冪等性(何度実行しても結果が同じになる性質)を保ちながら、指定したユーザーの authorized_keys
ファイルに公開鍵を適切に設定できます。ssh-copy-id
はあくまで手軽な初回設定ツールとして、構成管理ツールはより体系的な自動化ツールとして使い分けるのが良いでしょう。
2. Jump Host (踏み台サーバー) 経由での設定
直接アクセスできないサーバーがあり、Jump Host(踏み台サーバー)を経由する必要がある場合があります。このような環境でも、ssh-copy-id
を利用して最終的なターゲットサーバーに鍵認証を設定することが可能です。
最も簡単な方法は、ローカルマシンの ~/.ssh/config
ファイルにJump Hostの設定を記述しておくことです。ssh
クライアントは ssh_config
を読み込んで接続方法を判断するため、ssh-copy-id
もその設定を利用してくれます。
~/.ssh/config
に以下の設定を追加します。
“`
Jump Host の設定
Host jump-host
Hostname jump-host.example.com
User jumpuser
ターゲットサーバーの設定 (Jump Host 経由)
Host target-server
Hostname target-server.internal.com
User targetuser
ProxyJump jump-host
# または ProxyCommand ssh -W %h:%p jump-host
“`
jump-host
: Jump Host にアクセスするための短いエイリアス名。jump-host.example.com
: Jump Host の実際のホスト名またはIPアドレス。jumpuser
: Jump Host にログインするユーザー名。target-server
: ターゲットサーバーにアクセスするための短いエイリアス名。target-server.internal.com
: ターゲットサーバーの実際のホスト名またはIPアドレス(Jump Host から見える名前/IP)。targetuser
: ターゲットサーバーにログインするユーザー名。ProxyJump jump-host
:jump-host
という設定(上記で定義)を経由してこのホストに接続することを指定。
この設定を行った後、ローカルマシンで以下のコマンドを実行します。
bash
ssh-copy-id target-server
ssh-copy-id
は、target-server
の設定を ~/.ssh/config
から読み取り、Jump Host (jump-host
) を経由して target-server.internal.com
に targetuser
として接続を試みます。
この際、認証は以下の流れで進みます。
- ローカルから Jump Host (
jump-host.example.com
としてjumpuser
で) への認証。Jump Host への鍵認証がまだ設定されていない場合は、Jump Host のパスワードが求められます。 - Jump Host から ターゲットサーバー (
target-server.internal.com
としてtargetuser
で) への認証。Jump Host 上で秘密鍵を使ってターゲットサーバーへの認証が試行されます。この際、ssh-copy-id
はローカルマシンの秘密鍵(~/.ssh/id_rsa
など)ではなく、Jump Host 側に存在し、SSHエージェントによって転送された認証情報(ローカルの秘密鍵の利用権限)を使用しようとします。そのため、ローカルでSSHエージェントが起動しており、秘密鍵がエージェントに登録されている必要があります (ssh-add
)。 - ターゲットサーバーでの公開鍵のコピー処理。
ssh-copy-id
はターゲットサーバーに接続できた後、Jump Host 経由で、ターゲットサーバーのtargetuser
のauthorized_keys
ファイルにローカルの公開鍵を追記します。この時、ターゲットサーバーへの最初の接続となるため、ターゲットサーバーのパスワードが求められます。
つまり、Jump Host 経由で ssh-copy-id
を使う場合、通常は以下のパスワード入力が必要になります:
- Jump Host へのパスワード(もしJump Hostへの鍵認証が未設定の場合)
- ターゲットサーバーへのパスワード(鍵認証設定前なので必須)
一度設定が完了すれば、以降はローカル → Jump Host → ターゲットサーバー の全てでパスワードなしの鍵認証が可能になります(Jump Host への鍵認証も設定済みで、SSHエージェント転送を利用する場合)。
Jump Host 経由でのSSH接続や鍵認証設定は、ネットワーク構成によって様々なパターンがあり得ます。ssh_config
の詳細な設定やSSHエージェント転送 (ssh -A
オプション) について理解しておくと、より柔軟に対応できます。
ssh-copy-id
がない環境での代替方法(手動設定)
ssh-copy-id
は非常に便利ですが、古いOSの最小構成環境や、特別な組み込みシステムなど、すべての環境に最初からインストールされているわけではありません。そのような場合、公開鍵認証を設定するには手動で行う必要があります。
手動での設定方法を知っておくことは、ssh-copy-id
が使えない環境に遭遇した際の対応力を高めるだけでなく、ssh-copy-id
の内部の仕組みをより深く理解する上でも役立ちます。
以下に、手動で公開鍵をリモートホストにコピーし、設定する主な方法を2つ紹介します。どちらの方法も、リモートホストへのパスワード認証が一時的に可能であることが前提です。
前提条件:
- ローカルマシンにSSH鍵ペアが生成されており、公開鍵ファイル(例:
~/.ssh/id_rsa.pub
)が存在する。 - リモートホストにSSHサーバーが起動しており、設定したいユーザーアカウントが存在し、パスワード認証が可能である。
方法1: scp
コマンドで公開鍵ファイルをコピーし、リモートで追記する
この方法は、公開鍵ファイルを一時的にリモートホストにコピーし、リモートにログインしてからそのファイルを authorized_keys
に追記・整理するという手順です。
-
ローカルからリモートへ公開鍵ファイルをコピー:
ローカルマシンで、scp
(Secure Copy) コマンドを使って公開鍵ファイルをリモートホストの一時的な場所(例:/tmp
ディレクトリ)にコピーします。bash
scp ~/.ssh/id_rsa.pub user@remote_host:/tmp/id_rsa.pub
ここで、リモートホストのパスワード入力が求められます。 -
リモートホストにログインし、設定を行う:
リモートホストにSSHでパスワード認証してログインします。bash
ssh user@remote_host
ここでもパスワード入力が必要です。ログイン後、以下のコマンドを順に実行します。“`bash
1. .ssh ディレクトリが存在しない場合は作成し、パーミッションを設定
mkdir -p ~/.ssh
chmod 700 ~/.ssh2. コピーした公開鍵の内容を authorized_keys に追記
cat /tmp/id_rsa.pub >> ~/.ssh/authorized_keys
3. authorized_keys ファイルのパーミッションを設定
chmod 600 ~/.ssh/authorized_keys
4. 一時ファイルとしてコピーした公開鍵を削除
rm /tmp/id_rsa.pub
5. ログアウト
exit
“`
この方法の欠点は、scp
と ssh
で合計2回ログインする必要があること、リモートで複数のコマンドを手入力する必要があること、そして一時ファイルの削除を忘れる可能性があることです。
方法2: ssh
コマンドとパイプ、cat
コマンドを組み合わせて直接追記する
この方法は、ローカルで公開鍵ファイルの内容を cat
で表示し、それをパイプ (|
) を通じて ssh
コマンドのリモート実行に渡し、リモート側で cat >> authorized_keys
で追記するという、より効率的な方法です。
ローカルマシンで、以下のコマンドを実行します。
bash
cat ~/.ssh/id_rsa.pub | ssh user@remote_host 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
このコマンドは、リモートホストへのSSH接続時にパスワード入力を求めます。パスワードが正しければ、ローカルの ~/.ssh/id_rsa.pub
の内容が標準入力としてリモートの ssh
コマンドに渡され、シングルクォーテーション ('...'
) 内の複数のコマンドが順番に実行されます。
mkdir -p ~/.ssh
:.ssh
ディレクトリが存在しない場合のみ作成。chmod 700 ~/.ssh
:.ssh
ディレクトリのパーミッションを設定。cat >> ~/.ssh/authorized_keys
: 標準入力から受け取った公開鍵の内容をauthorized_keys
ファイルに追記。chmod 600 ~/.ssh/authorized_keys
:authorized_keys
ファイルのパーミッションを設定。
この方法は、ログイン回数が1回で済み、リモートでの手入力も不要なため、方法1よりも効率的でミスを減らせます。多くの点で ssh-copy-id
の内部的な処理に近いアプローチと言えます。ただし、コマンドが少し複雑になるため、タイポの可能性はあります。
どちらの方法も、手動で行う必要があるため、ssh-copy-id
に比べると手間がかかり、パーミッション設定を忘れがちです。これらの手動方法を知ることで、改めて ssh-copy-id
の利便性と、それが自動化してくれている作業の価値を実感できるでしょう。
鍵認証のセキュリティをさらに高める
ssh-copy-id
を使ってSSH鍵認証を設定することは、パスワード認証に比べてセキュリティを大幅に向上させます。しかし、さらにセキュリティを高めるために、いくつかの追加の対策を講じることができます。
1. 秘密鍵には必ずパスフレーズを設定する
ssh-keygen
で鍵ペアを生成する際に、パスフレーズを設定できます。パスフレーズを設定すると、秘密鍵を使用する際にそのパスフレーズの入力が必要になります。これにより、もし秘密鍵ファイルが第三者の手に渡ってしまっても、パスフレーズが分からなければ悪用されるリスクを減らせます。
パスフレーズを設定した場合、SSH接続時にパスフレーズの入力が求められます。これを毎回入力するのは手間ですが、SSHエージェント (ssh-agent
) を使うことで、一度パスフレーズを入力すれば、エージェントが起動している間はパスフレーズなしで秘密鍵を利用できるようになります。セキュリティと利便性のバランスを取るために、パスフレーズの設定とSSHエージェントの活用を強く推奨します。
2. 秘密鍵ファイルのパーミッションを確認する
秘密鍵ファイル (~/.ssh/id_rsa
など) は、所有者以外が読み書きできないように、パーミッションが 600
(-rw-------
) またはそれより厳しい設定になっている必要があります。もしパーミッションが緩い(例: 他のユーザーも読める)場合、SSHクライアントはセキュリティ上の理由からその秘密鍵を使用しないことがあります。
bash
chmod 600 ~/.ssh/id_rsa
3. authorized_keys
ファイル内のオプションを活用する
リモートホストの ~/.ssh/authorized_keys
ファイルに追記された各公開鍵のエントリには、オプションを追加することで、その公開鍵を使った接続に制限を設けることができます。ssh-copy-id
は通常オプションなしで公開鍵を追記しますが、必要に応じて手動で authorized_keys
ファイルを編集し、オプションを追加することを検討してください。
以下に代表的なオプションをいくつか紹介します。
-
from="pattern"
: 接続元IPアドレスやホスト名を制限します。指定されたパターンに一致する接続元からのみ、この鍵を使った認証を許可します。
例:from="192.168.1.*,*.example.com" ssh-rsa AAAA...
-
command="command"
: この鍵で認証された接続に対して、対話的なシェルアクセスを許可せず、指定されたコマンドのみを実行可能にします。これは、特定のタスク(例: rsyncによるバックアップ)のためだけに鍵認証を設定する場合に特に有用です。
例:command="/usr/local/bin/run_backup_script.sh" ssh-rsa AAAA...
-
機能制限オプション: 不要なSSH機能を無効化することで、攻撃者がサーバー内の他のリソースにアクセスしたり、攻撃の足がかりにしたりするリスクを減らします。
no-port-forwarding
: ポートフォワーディングを無効化。no-agent-forwarding
: SSHエージェント転送を無効化。no-pty
: 擬似端末の割り当てを無効化(対話的なシェルアクセスができなくなる)。no-X11-forwarding
: X11転送を無効化。
これらのオプションはまとめて指定できます。
例:no-port-forwarding,no-agent-forwarding,no-pty,no-X11-forwarding ssh-rsa AAAA...
これらのオプションを適切に設定することで、公開鍵が漏洩した場合のリスクを軽減したり、鍵の用途を特定の操作に限定したりすることが可能になります。ただし、これらのオプション設定は ssh-copy-id
では自動で行われないため、手動での編集が必要です。編集後は、SSHサービスを再起動する必要はありませんが、設定が正しく反映されるか確認すると良いでしょう。
これらのセキュリティ対策に加えて、定期的な鍵の更新や、不要になった公開鍵を authorized_keys
ファイルから削除することも重要です。
まとめ:鍵認証設定の最良のツール
この記事では、SSH鍵認証を簡単かつ確実に行うための ssh-copy-id
コマンドについて、その使い方、仕組み、応用、トラブルシューティング、そして関連するセキュリティ対策まで、詳しく解説してきました。
ssh-copy-id
は、手動では手間がかかりミスをしやすい「クライアントの公開鍵をリモートサーバーの authorized_keys
ファイルに追記し、適切なパーミッションを設定する」という一連の作業を自動化してくれる、非常に価値のあるツールです。特にSSH鍵認証を初めて設定する方や、複数のサーバーに鍵認証を設定したい方にとって、これほど便利なコマンドはありません。
基本的な使い方は ssh-copy-id [user@]hostname
と非常にシンプルですが、-i
オプションで特定の公開鍵を指定したり、-p
オプションで非標準ポートに対応したり、-v
で詳細な情報を得たりと、用途に応じたオプションも用意されています。また、標準入力から公開鍵を受け取る -
オプションのような、知っておくと便利な応用的な使い方も可能です。
コマンドがうまく動作しない場合でも、焦る必要はありません。この記事で紹介したトラブルシューティングのステップ(コマンドや設定の確認、エラーメッセージの分析、リモートホスト側の設定やパーミッションのチェック、ログの確認など)を順に試すことで、ほとんどの問題は解決できるはずです。
さらに、シェルスクリプトと組み合わせて複数のサーバーに自動展開したり、~/.ssh/config
を活用してJump Host経由のサーバーに設定したりといった応用も可能です。そして、たとえ ssh-copy-id
が使えない環境に遭遇したとしても、手動での代替方法を知っていれば対応できます。
SSH鍵認証は、リモート接続のセキュリティと利便性を両立させるための基本中の基本です。そして、その設定の第一歩を圧倒的に容易にしてくれるのが ssh-copy-id
です。
この記事を通じて、あなたが ssh-copy-id
を自在に使いこなし、安全で効率的なSSH環境を構築できるようになることを願っています。さらにSSHを深く学びたい場合は、ssh_config
や sshd_config
ファイルの詳細、SSHエージェント、鍵のオプションについて調べてみてください。
これで、あなたはもうSSH鍵認証設定で迷うことはありません。自信を持って ssh-copy-id
を使い、快適なSSHライフを送りましょう!