從 WSL 的 Ubuntu 裡面,同步 Windows 的Next.js 專案建置結果到遠端 VPS 主機上

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

主要就是利用 rsync 這個工具,搭配 SSH 連線,來執行推送(push)與同步的動作。


執行前的準備

首先,請確認你的 WSL UbuntuVPS 主機 都已經安裝好 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 主機,並把資料放在指定的路徑。

注意事項

  1. 路徑末尾的斜線/mnt/c/.../nextjs-hello-world/**/** 這個斜線很重要,影響同步的結果。你確定要同步 .next 資料夾裡面的內容,所以要加上斜線。
  2. --delete 的風險--delete 是一個強力的選項。它會讓你遠端目錄中的資料和本機一模一樣。請務必確定你的源頭路徑(本機)是正確的,避免誤刪 VPS 上的重要檔案。
  3. 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 終端機裡面操作。

  1. 檢查現有的金鑰先看看你的家目錄底下有沒有 .ssh 這個隱藏資料夾。Bashls -al ~/.ssh 如果看到 id_rsaid_ed25519 這類檔案,代表你已經有金鑰了,可以直接跳到「複製公鑰到遠端主機」那一步。
  2. 產生新的金鑰對如果沒有金鑰,建議使用現代、安全的 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/ 資料夾內。3
    • Enter passphrase (empty for no passphrase):4這是設定保護私鑰的密碼。強烈建議設定,這樣即使私鑰被偷,駭客也不知道密碼也無法使用。每次用金鑰連線時會需要輸入這個密碼。如果不想設密碼就直接按 Enter。
    • Enter same passphrase again:再次輸入密碼確認。
    完成後,~/.ssh/ 資料夾會產生兩個檔案:
    • id_ed25519:這是你的私鑰(Private Key),必須保密5
    • id_ed25519.pub:這是你的公鑰(Public Key),這個可以分享給遠端主機。6

複製公鑰到遠端主機

接著,你需要把這個公鑰(id_ed25519.pub 的內容)放到你想要連線的遠端主機上。7

  1. 檢視公鑰內容把公鑰的完整內容印出來,準備複製。
    cat ~/.ssh/id_ed25519.pub 複製從 ssh-ed25519 開頭到最後(包含你的電子郵件註解)的所有內容
  2. 上傳到遠端主機如果你有安裝 ssh-copy-id,這是最簡單的方法:
    ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote_host_ip 如果你沒有 ssh-copy-id,或者想手動操作:
    • 先用密碼登入你的遠端主機:Bashssh 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 這個檔案的最後一行

測試連線

當公鑰設定好之後,從你的 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_ed25519id_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

你遇到的這個問題很常見。它主要有兩個狀況:

  1. Could not open a connection to your authentication agent.這代表你第一次輸入 ssh-add 的時候,ssh-agent 服務還沒有啟動,所以沒辦法連線。你後來執行了 eval "$(ssh-agent -s)" 之後,Agent (PID 636) 就成功啟動了,這個問題就解決了。
  2. 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

  1. 設定正確權限
    chmod 600 id_rsa
  2. 啟動 ssh-agent (如果還沒啟動的話,但你之前執行過了,可以再跑一次確保 Agent 服務還在)
    eval "$(ssh-agent -s)"
  3. 把私鑰加入 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.jsonnode_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.jsonpackage-lock.jsonnode_modulesapppages 等檔案或資料夾。
  • 但你的目錄裡只有 .next 資料夾,這表示你的專案內容可能在之前建立或傳輸時沒有完整複製過來

.next 資料夾是執行 npm run build 之後才產生的 編譯結果,它本身不包含運行專案所需的原始程式碼和依賴設定。

解決步驟

你需要把 完整的 Next.js 專案檔案 重新放回 /home/max/nextjs/nextjs-hello-world 資料夾。

如果你手邊有完整的專案檔案 (例如你在本地電腦上建立的專案):

  1. 複製原始碼:將 package.jsonapp (或 pages)、next.config.js 等所有原始碼檔案都上傳到你的 VPS 上的 /home/max/nextjs/nextjs-hello-world
  2. 安裝依賴:在 VPS 的專案目錄下執行 npm install。這個指令會根據 package.json 裡列出的依賴項,下載所有必要的模組到 node_modules 資料夾。
  3. 重新建構:執行 npm run build,確保 .next 資料夾是用最新的依賴建立的。
  4. 啟動服務:最後再執行 npm run start

這樣就能正確運行你的 Next.js 網站了。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *