要從 WSL 的 Ubuntu 裡面,把 Windows C 槽底下的一個 Next.js 專案建置結果,同步到遠端 VPS 主機上。成功的執行畫面:

主要就是利用 rsync 這個工具,搭配 SSH 連線,來執行推送(push)與同步的動作。
執行前的準備
首先,請確認你的 WSL Ubuntu 和 VPS 主機 都已經安裝好 rsync。一般來說,Ubuntu 預設會安裝。
在 WSL Ubuntu 裡,檢查一下:
rsync --version
如果沒有,就安裝一下:
sudo apt update
sudo apt install rsync
確認你的 WSL Ubuntu 可以透過 SSH 連線到 VPS 主機,並且最好使用 SSH Key 進行身份驗證,這樣比較安全也比較方便,不用每次都輸入密碼。
rsync 的指令
你要推送的本機路徑在 WSL Ubuntu 裡面是 /mnt/c/Max/Documents/nextjs/nextjs-hello-world/,遠端主機的路徑是 /home/max/nextjs/nextjs-hello-world/
假設你的 VPS 主機 IP 是 192.168.1.100,使用者名稱是 root。
這是你要執行的 rsync 同步指令:
rsync -avz --delete /mnt/c/Max/Documents/nextjs/nextjs-hello-world/ [email protected]:/home/max/nextjs/nextjs-hello-world/
指令解析
rsync:這是執行同步的程式。-avz:這是一組常用的選項:a(archive mode):封存模式。會遞迴(recursive)複製目錄,並保留所有權限、時間戳記、符號連結等檔案資訊。v(verbose):詳細模式。會顯示正在傳輸的檔案清單,讓你看到同步的進度。z(compress):壓縮傳輸。在傳輸時會壓縮資料,可以減少傳輸時間,特別是網路速度不快的時候。
--delete:這個選項很重要。它會刪除遠端(目的地)中,源頭(本機)沒有的檔案。這樣可以確保兩邊的.next資料夾內容是完全同步的,不會留下舊的、不需要的建置檔案。/mnt/c/Max/.../nextjs-hello-world/:這是源頭路徑。注意看路徑最後面有一個斜線/。這個斜線代表 rsync 會複製這個目錄裡面的所有內容,而不是複製這個目錄本身。如果沒有斜線,它會把一個叫做nextjs-hello-world的資料夾複製到遠端。[email protected]:/root/nextjs/nextjs-hello-world:這是目的地路徑。格式是使用者名稱@主機位址:完整路徑。這告訴 rsync 要透過 SSH 連線到 VPS 主機,並把資料放在指定的路徑。
注意事項
- 路徑末尾的斜線:
/mnt/c/.../nextjs-hello-world/**/**這個斜線很重要,影響同步的結果。你確定要同步.next資料夾裡面的內容,所以要加上斜線。 --delete的風險:--delete是一個強力的選項。它會讓你遠端目錄中的資料和本機一模一樣。請務必確定你的源頭路徑(本機)是正確的,避免誤刪 VPS 上的重要檔案。- SSH 連線:如果你的 VPS 主機 SSH 服務不是預設的 Port 22,你需要加上
-e "ssh -p <Port號碼>"這個選項來指定 Port。
範例 (如果 SSH Port 是 2222):
rsync -avz --delete -e "ssh -p 2222" /mnt/c/Max/Documents/nextjs/nextjs-hello-world/ [email protected]:/home/max/nextjs/nextjs-hello-world/附註: 不要允許 root 可以進行 ssh, 對系統較安全.
設定 WSL Ubuntu 的 SSH 私鑰(Private Key)主要有兩個步驟:產生金鑰和使用金鑰。這個過程跟在一般的 Linux 環境下很像。
產生 SSH 金鑰
請在你的 WSL Ubuntu 終端機裡面操作。
- 檢查現有的金鑰先看看你的家目錄底下有沒有
.ssh這個隱藏資料夾。Bashls -al ~/.ssh如果看到id_rsa或id_ed25519這類檔案,代表你已經有金鑰了,可以直接跳到「複製公鑰到遠端主機」那一步。 - 產生新的金鑰對如果沒有金鑰,建議使用現代、安全的
Ed25519演算法來產生。Bashssh-keygen -t ed25519 -C "你的電子郵件@example.com"-t ed25519:指定金鑰的類型。1-C:加上註解,通常是你的電子郵件,用來識別這組金鑰。2
Enter file in which to save the key (~/.ssh/id_ed25519):直接按 Enter 接受預設路徑和檔名就好,金鑰會存放在~/.ssh/資料夾內。3Enter passphrase (empty for no passphrase):4這是設定保護私鑰的密碼。強烈建議設定,這樣即使私鑰被偷,駭客也不知道密碼也無法使用。每次用金鑰連線時會需要輸入這個密碼。如果不想設密碼就直接按 Enter。Enter same passphrase again:再次輸入密碼確認。
~/.ssh/資料夾會產生兩個檔案:id_ed25519:這是你的私鑰(Private Key),必須保密。5id_ed25519.pub:這是你的公鑰(Public Key),這個可以分享給遠端主機。6
複製公鑰到遠端主機
接著,你需要把這個公鑰(id_ed25519.pub 的內容)放到你想要連線的遠端主機上。7
- 檢視公鑰內容把公鑰的完整內容印出來,準備複製。
cat ~/.ssh/id_ed25519.pub複製從ssh-ed25519開頭到最後(包含你的電子郵件註解)的所有內容。 - 上傳到遠端主機如果你有安裝
ssh-copy-id,這是最簡單的方法:ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote_host_ip如果你沒有ssh-copy-id,或者想手動操作:- 先用密碼登入你的遠端主機:Bash
ssh user@remote_host_ip - 在遠端主機上建立
.ssh資料夾和authorized_keys檔案(並設定正確的權限):Bashmkdir -p ~/.ssh && chmod 700 ~/.ssh touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys - 把剛剛複製的公鑰內容貼到
~/.ssh/authorized_keys這個檔案的最後一行。
- 先用密碼登入你的遠端主機:Bash
測試連線
當公鑰設定好之後,從你的 WSL Ubuntu 終端機試著連線:
ssh user@remote_host_ip
如果設定了私鑰密碼(passphrase),會提示你輸入密碼。如果一切順利,你不需要輸入遠端主機的登入密碼就可以連上去了。
如果你覺得每次都要輸入私鑰密碼很麻煩,可以考慮使用 ssh-agent 服務:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
這樣你只需要輸入一次密碼,ssh-agent 就會在當前會話中幫你記住私鑰的解密狀態,直到你關閉 WSL 視窗。
在這個情境中 WSL Ubuntu 就是扮演 Client 端,而 VPS 上的 sshd 服務 就是扮演 Server 端。
為了讓 WSL Ubuntu 能夠順利連線並執行 rsync 同步,Client 端主要有兩個重點要設定:SSH 金鑰和連線設定。
SSH 金鑰的設定 (身份驗證)
這是最重要的一步,可以讓你免密碼且安全地登入 VPS。
- 私鑰(Private Key):私鑰檔案必須存放在 WSL Ubuntu 的家目錄底下,也就是
~/.ssh/資料夾內,通常檔名是id_ed25519或id_rsa。這個檔案是 Client 端用來證明自己身份的憑證。 - 公鑰(Public Key):公鑰檔案的內容必須已經複製到 VPS Server 端 的
~/.ssh/authorized_keys檔案中。Server 端會用這個公鑰來驗證你帶來的私鑰是否吻合。
如果你是使用 SSH Key 加上密碼保護(passphrase),你可能還需要執行:
eval "$(ssh-agent -s)"
ssh-add
這樣可以讓 ssh-agent 服務記住你的私鑰解密密碼,這樣在執行 rsync 時就不用一直重複輸入密碼。
rsync 的設定 (傳輸協定)
rsync 在透過 SSH 傳輸時,不需要額外設定什麼。它會直接調用 Client 端的 ssh 程式來建立連線,所以只要你的 ssh user@vps_ip 指令能夠成功登入,rsync 就可以使用。
WSL Ubuntu 上的連線設定檔
你可以選擇在 WSL Ubuntu 的 ~/.ssh/config 檔案中設定 VPS 主機的連線參數,這樣可以讓你的連線指令更簡潔,也方便管理多台主機。
如果你想設定,可以編輯這個檔案:
Bash
nano ~/.ssh/config
並加入以下內容(假設你的 VPS IP 是 192.168.1.100,使用者名稱是 user):
Plaintext
Host my_vps
HostName 192.168.1.100
User user
Port 22
IdentityFile ~/.ssh/id_ed25519
# 如果要避免第一次連線詢問確認,可以加上下面這行,但不建議新手使用
# StrictHostKeyChecking no
設定好之後:
- SSH 連線指令:原本的
ssh [email protected]就可以簡化成ssh my_vps。 - rsync 指令:原本很長的指令也可以用這個設定檔名稱來取代 IP 位址:
Bash
rsync -avz --delete /mnt/c/Max/.../.next/ my_vps:/root/nextjs/.../.next
總結來說,Client 端(WSL Ubuntu)要設定的重點就是產生並保護好你的私鑰,並確保私鑰的公鑰已經安裝在 Server 端。
錯誤訊息:
➜.ssh eval "$(ssh-agent -s)"
ssh-add
Agent pid 636
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/max32/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
➜ .ssh
你遇到的這個問題很常見。它主要有兩個狀況:
Could not open a connection to your authentication agent.這代表你第一次輸入ssh-add的時候,ssh-agent服務還沒有啟動,所以沒辦法連線。你後來執行了eval "$(ssh-agent -s)"之後,Agent (PID 636) 就成功啟動了,這個問題就解決了。WARNING: UNPROTECTED PRIVATE KEY FILE!這是現在主要的問題。系統檢查到你的私鑰檔案/home/max32/.ssh/id_rsa的權限設定太過寬鬆了(Permissions 0644)。私鑰(Private Key) 必須只有擁有者(也就是你本人)可以讀取和寫入。0644這個權限代表其他人也可以讀取這個私鑰,這樣非常不安全。為了保護你的帳號,SSH 程式會拒絕使用權限過鬆的私鑰。
如何解決私鑰權限問題
你需要使用 chmod 指令,把私鑰檔案的權限設定成只有擁有者可以讀取和寫入 (0600)。
請在 .ssh 資料夾裡面執行這個指令:
chmod 600 id_rsa
完整正確的步驟
當你解決權限問題之後,請依照這個順序執行,讓你的私鑰成功加入 ssh-agent:
- 設定正確權限
chmod 600 id_rsa - 啟動 ssh-agent (如果還沒啟動的話,但你之前執行過了,可以再跑一次確保 Agent 服務還在)
eval "$(ssh-agent -s)" - 把私鑰加入 Agent
ssh-add id_rsa
如果你的 id_rsa 有設定密碼(passphrase),執行 ssh-add 後系統會提示你輸入密碼。輸入成功之後,你的私鑰就可以被 SSH 連線使用了。
如果只有同步 .next, 會顯示錯誤訊息:
➜ nextjs-hello-world npm run start
npm error code ENOENT
npm error syscall open
npm error path /home/max/nextjs/nextjs-hello-world/package.json
npm error errno -2
npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/home/max/nextjs/nextjs-hello-world/package.json'
npm error enoent This is related to npm not being able to find a file.
npm error enoent
npm error A complete log of this run can be found in: /root/.npm/_logs/2025-12-15T02_50_19_874Z-debug-0.log
➜ nextjs-hello-world pwd
/home/max/nextjs/nextjs-hello-world
➜ nextjs-hello-world ls -al
total 12
drwxr-xr-x 3 max max 4096 Dec 15 02:47 .
drwxr-xr-x 3 max max 4096 Dec 15 02:47 ..
drwxrwxrwx 8 max max 4096 Dec 15 02:01 .next
➜ nextjs-hello-world
執行 npm run start 遇到錯誤
你遇到的這個錯誤訊息是 npm error enoent Could not read package.json,這是一個很常見但關鍵的錯誤。
錯誤分析
- 錯誤碼 (
ENOENT):代表 Error NO ENTry,意思是「找不到檔案或目錄」。 - 系統呼叫 (
syscall open):npm 試圖打開一個檔案。 - 檔案路徑 (
path /home/max/nextjs/nextjs-hello-world/package.json):npm 試圖讀取這個路徑下的package.json檔案。 - 主要問題:你的 Next.js 專案資料夾
/home/max/nextjs/nextjs-hello-world缺少了package.json和node_modules等重要檔案。
你的檔案狀況
你執行的 ls -al 指令結果也證實了這個問題:
total 12
drwxr-xr-x 3 max max 4096 Dec 15 02:47 .
drwxr-xr-x 3 max max 4096 Dec 15 02:47 ..
drwxrwxrwx 8 max max 4096 Dec 15 02:01 .next
- 一個正常的 Next.js 專案,在執行
npm install之後,至少應該有package.json、package-lock.json、node_modules、app或pages等檔案或資料夾。 - 但你的目錄裡只有
.next資料夾,這表示你的專案內容可能在之前建立或傳輸時沒有完整複製過來。
.next 資料夾是執行 npm run build 之後才產生的 編譯結果,它本身不包含運行專案所需的原始程式碼和依賴設定。
解決步驟
你需要把 完整的 Next.js 專案檔案 重新放回 /home/max/nextjs/nextjs-hello-world 資料夾。
如果你手邊有完整的專案檔案 (例如你在本地電腦上建立的專案):
- 複製原始碼:將
package.json、app(或pages)、next.config.js等所有原始碼檔案都上傳到你的 VPS 上的/home/max/nextjs/nextjs-hello-world。 - 安裝依賴:在 VPS 的專案目錄下執行
npm install。這個指令會根據package.json裡列出的依賴項,下載所有必要的模組到node_modules資料夾。 - 重新建構:執行
npm run build,確保.next資料夾是用最新的依賴建立的。 - 啟動服務:最後再執行
npm run start。
這樣就能正確運行你的 Next.js 網站了。