# 如何使用 ssh-copy-id 快速設定 Linux 遠端主機的 SSH 免密碼登入

身為一名開發人員，每天透過 SSH 連線到遠端 Linux 主機進行維運或部署，可以說是家常便飯。如果不設定 SSH 金鑰登入 (Public Key Authentication) ，每次連線都要輸入密碼，長期下來不僅浪費時間，也容易打斷工作的節奏。雖然我們可以手動將本機的公鑰 (Public Key) 內容複製起來，然後貼到遠端主機的 `~/.ssh/authorized_keys` 檔案中，但這個過程繁瑣且容易出錯。這篇文章我將介紹一個內建在 Linux 與 macOS 系統中非常實用的工具 `ssh-copy-id` ，讓你只要一行指令就能輕鬆完成設定，實現無密碼登入。

![Image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/af9d02d2028fd47cbca5-a5da68b6-5acc-4a9e-af51-d5ebd1be5389.webp)

### 準備工作：產生 SSH 金鑰對

在使用 `ssh-copy-id` 之前，請確保你的本機已經產生了 SSH 金鑰對 (Key Pair)。如果還沒有產生，可以使用 `ssh-keygen` 指令來建立。目前建議使用更安全且效能更好的 `Ed25519` 演算法：

```bash
ssh-keygen -t ed25519 -C "your_email@example.com"
```

執行過程中直接按下 Enter 鍵使用預設路徑即可。完成後，你的公鑰會儲存在 `~/.ssh/id_ed25519.pub` 。

### 使用 ssh-copy-id 傳送公鑰

有了公鑰之後，我們就可以使用 `ssh-copy-id` 將它傳送到遠端伺服器。

1.  基本用法
    
    這是最常見的使用情境，假設你要登入的遠端帳號是 `user` ，主機 IP 是 `192.168.1.100` ：
    
    ```bash
    ssh-copy-id user@192.168.1.100
    ```
    
    執行這個指令後，系統會嘗試用 SSH 連線到遠端主機。如果是第一次連線，會詢問你是否信任該主機的指紋 (fingerprint) ，輸入 `yes` 之後，接著會要求你輸入該遠端帳號的密碼。
    
    一旦密碼驗證通過，`ssh-copy-id` 就會自動將你本機預設的公鑰 ( 例如 `~/.ssh/id_rsa.pub` 或 `~/.ssh/id_ed25519.pub` ) 附加到遠端主機的 `~/.ssh/authorized_keys` 檔案末端，並且會自動調整遠端目錄與檔案的權限，確保 SSH Server 能正確讀取。
    
    成功之後，你會看到類似以下的訊息：
    
    ```
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh 'user@192.168.1.100'"
    and check to make sure that only the key(s) you wanted were added.
    ```
    
2.  指定特定的公鑰檔案
    
    如果你電腦中有多組 SSH 金鑰，或者你的公鑰檔案名稱不是預設值，你可以透過 `-i` 參數來指定要傳送哪一個公鑰檔案：
    
    ```bash
    ssh-copy-id -i ~/.ssh/my_custom_key.pub user@192.168.1.100
    ```
    
3.  指定遠端 SSH 連接埠
    
    如果你的遠端伺服器為了安全性考量，將 SSH 的預設 Port 22 改為其他埠號 (例如 2222) ，在使用 `ssh-copy-id` 時就需要特別指定。
    
    在較新版本的 `ssh-copy-id` 中，可以直接使用 `-p` 參數：
    
    ```bash
    ssh-copy-id -p 2222 user@192.168.1.100
    ```
    
    如果你的系統版本較舊，發現不支援 `-p` 參數，可以嘗試將埠號設定包在引號中傳遞給 ssh ：
    
    ```bash
    ssh-copy-id "user@192.168.1.100 -p 2222"
    ```
    

### 常見問題與排除

-   權限問題
    
    設定了 Public Key 之後要是還需要輸入密碼，通常都是因為遠端主機的檔案權限設定太過寬鬆所導致。SSH Server 為了安全起見，如果發現 `.ssh` 目錄或是 `authorized_keys` 檔案可以被其他人寫入，通常會拒絕使用 Key 登入。
    
    `ssh-copy-id` 的好處在於它通常會幫你處理好這些權限問題。但如果你是手動複製，或者權限跑掉了，可以登入遠端主機執行以下修復指令：
    
    ```bash
    # 確保家目錄權限不含群組與其他人的寫入權限
    chmod g-w,o-w ~
    
    # 設定 .ssh 目錄權限為 700
    chmod 700 ~/.ssh
    
    # 設定 authorized_keys 檔案權限為 600
    chmod 600 ~/.ssh/authorized_keys
    ```
    
-   Windows 使用者的替代方案
    
    `ssh-copy-id` 是 OpenSSH 套件中的一個 Shell Script，主要存在於 Linux 與 macOS 環境中。如果你是在 Windows 上使用 PowerShell 或 Command Prompt，預設可能沒有這個指令。
    
    不過，如果你安裝了 **Git for Windows**，在 **Git Bash** 中是可以直接使用 `ssh-copy-id` 的。
    
    如果你堅持要在 PowerShell 中完成類似的工作，可以使用以下指令來模擬 `ssh-copy-id` 的行為：
    
    ```powershell
    type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@192.168.1.100 "cat >> .ssh/authorized_keys"
    ```
    
    當然，前提是遠端主機上的 `.ssh` 目錄必須先存在。
    

### 總結

使用 `ssh-copy-id` 可以大幅簡化 SSH 金鑰的佈署流程，避免手動複製貼上可能產生的錯誤 (例如多複製了換行符號)。設定好免密碼登入後，未來無論是使用 `scp` 傳輸檔案，或是透過 [VS Code Remote - SSH](https://code.visualstudio.com/docs/remote/ssh) 進行遠端開發，都能享受到更流暢的體驗。

#### 相關連結

-   [ssh-copy-id(1) - Linux man page](https://linux.die.net/man/1/ssh-copy-id)
-   [Generating a new SSH key and adding it to the ssh-agent](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)
