# live.gp777s.com GCP 部署 README

本文件整理 `live.gp777s.com` 在 GCP VM 上的完整部署流程。

目標架構：

```text
Browser
  ↓
https://live.gp777s.com
  ↓
Nginx
  ├── /        → 127.0.0.1:3000 Next.js
  ├── /chat    → 127.0.0.1:3001/chat WebSocket
  └── /streams → 127.0.0.1:3001/streams WebSocket
```

目前服務：

```text
Next.js   → 3000
WebSocket → 3001
Nginx     → 80 / 443
PM2       → 常駐 Next.js 與 WebSocket
SSL       → Let's Encrypt
```

---

## 1. GCP 防火牆設定

GCP VM 需要開放：

```text
tcp:80
tcp:443
```

如果使用 gcloud，可以執行：

```bash
gcloud compute firewall-rules create allow-http-https \
  --allow tcp:80,tcp:443 \
  --target-tags nginx-web \
  --description="Allow HTTP and HTTPS traffic"
```

VM 需要套用同樣的 network tag：

```text
nginx-web
```

---

## 2. 安裝 Nginx

Debian / Ubuntu：

```bash
sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx
```

確認 Nginx 狀態為：

```text
active (running)
```

---

## 3. 建立網站目錄

```bash
sudo mkdir -p /var/www/live.gp777s.com/
sudo chown -R $USER:www-data /var/www/live.gp777s.com/
sudo chmod -R 775 /var/www/live.gp777s.com/
```

可以先建立測試頁：

```bash
echo "live.gp777s.com nginx ready" | sudo tee /var/www/live.gp777s.com/index.html
```

---

## 4. 安裝 Node.js

本專案曾使用 Node.js 20：

```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
```

若套件要求 Node.js 22，例如 `whip-whep-client@1.3.0`，可改裝 Node.js 22：

```bash
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
```

---

## 5. 專案部署目錄

專案放置在：

```bash
/var/www/live.gp777s.com
```

專案主要檔案結構範例：

```text
/var/www/live.gp777s.com/
├── .env
├── .next/
├── _server/
├── app/
├── components/
├── data/
├── i18n/
├── lib/
├── node_modules/
├── package.json
├── package-lock.json
├── next.config.js
├── ecosystem.config.js
└── public/
```

---

## 6. 本地打包，上傳到 GCP

本專案採用「本地 build，GCP 只跑服務」策略。

本地專案目錄執行：

```bash
npm ci
npm run build
```

確認本地可啟動：

```bash
npm start
```

上傳到 GCP 建議使用 `rsync`：

```bash
rsync -avz --delete \
  .next public package.json package-lock.json next.config.js ecosystem.config.js \
  data i18n lib _server gp-live.sqlite \
  je4122731@YOUR_GCP_EXTERNAL_IP:/var/www/live.gp777s.com/
```

如需指定 SSH key：

```bash
rsync -avz --delete -e "ssh -i ~/.ssh/YOUR_KEY" \
  .next public package.json package-lock.json next.config.js ecosystem.config.js \
  data i18n lib _server gp-live.sqlite \
  je4122731@YOUR_GCP_EXTERNAL_IP:/var/www/live.gp777s.com/
```

`.env` 建議在 GCP VM 上手動建立，不建議放進 Git 或隨意同步。

---

## 7. 安裝 production 依賴

進入 GCP VM：

```bash
cd /var/www/live.gp777s.com
npm ci --omit=dev
```

若遇到權限問題：

```bash
sudo chown -R je4122731:www-data /var/www/live.gp777s.com
sudo chmod -R 775 /var/www/live.gp777s.com
```

再重新安裝：

```bash
cd /var/www/live.gp777s.com
npm ci --omit=dev
```

---

## 8. package.json 服務指令

本專案的 `package.json` scripts：

```json
{
  "scripts": {
    "dev": "concurrently -n \"next,ws\" -c \"cyan,magenta\" \"next dev\" \"npm run dev:ws\"",
    "dev:next": "next dev",
    "dev:ws": "nodemon --config nodemon.json --exec tsx _server/startWsServer.mjs",
    "dev:all": "npm run dev",
    "build": "next build",
    "start": "next start",
    "start:ws": "tsx _server/startWsServer.mjs",
    "start:next": "node _server/nextAppServer.js",
    "lint": "next lint"
  }
}
```

正式環境需要跑兩個服務：

```text
npm run start     → Next.js
npm run start:ws  → WebSocket
```

---

## 9. 手動測試 Next.js

```bash
cd /var/www/live.gp777s.com
HOST=127.0.0.1 PORT=3000 npm run start
```

另開一個 SSH 視窗測試：

```bash
curl -I http://127.0.0.1:3000
```

只要回應 `200`、`301`、`302`、`307`，代表服務正常。

測完按：

```text
Ctrl + C
```

---

## 10. 手動測試 WebSocket

啟動 WS：

```bash
cd /var/www/live.gp777s.com
PORT=3001 npm run start:ws
```

確認 port：

```bash
ss -lntp | grep 3001
```

WebSocket server 會輸出：

```text
[WS Server] WebSocket 聊天: ws://localhost:3001/chat
[WS Server] WebSocket 直播狀態: ws://localhost:3001/streams
[Stream Live] 伺服器定期輪詢 Cloudflare live_inputs API，間隔 5000ms
```

測試工具：

```bash
sudo npm install -g wscat
```

測試本機 WS：

```bash
wscat -c ws://127.0.0.1:3001/chat
wscat -c ws://127.0.0.1:3001/streams
```

如果看到：

```text
Connected (press CTRL+C to quit)
```

代表 WS 正常。

注意：不要測 `ws://127.0.0.1:3001`，因為此專案的 WS endpoint 是 `/chat` 和 `/streams`。

---

## 11. 使用 PM2 常駐服務

安裝 PM2：

```bash
sudo npm install -g pm2
```

啟動 Next.js：

```bash
cd /var/www/live.gp777s.com
HOST=127.0.0.1 PORT=3000 pm2 start npm --name live-next -- run start
```

啟動 WebSocket：

```bash
cd /var/www/live.gp777s.com
PORT=3001 pm2 start npm --name live-ws -- run start:ws
```

確認服務：

```bash
pm2 list
```

應看到：

```text
live-next  online
live-ws    online
```

確認 port：

```bash
ss -lntp | grep -E '3000|3001'
```

應看到：

```text
*:3000
*:3001
```

---

## 12. PM2 開機自啟

保存目前 PM2 process list：

```bash
pm2 save
```

建立 systemd 開機自啟：

```bash
pm2 startup
```

系統會輸出一段指令，例如：

```bash
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u je4122731 --hp /home/je4122731
```

把該指令複製貼上執行。

本機實際使用指令：

```bash
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u je4122731 --hp /home/je4122731
pm2 save
```

確認 systemd 已啟用：

```bash
systemctl status pm2-je4122731
```

---

## 13. Nginx 設定

建立 Nginx site config：

```bash
sudo nano /etc/nginx/sites-available/live.gp777s.com
```

HTTP 基礎版設定：

```nginx
server {
    listen 80;
    listen [::]:80;

    server_name live.gp777s.com;

    root /var/www/live.gp777s.com;
    index index.html;

    access_log /var/log/nginx/live.gp777s.com.access.log;
    error_log /var/log/nginx/live.gp777s.com.error.log;

    client_max_body_size 50M;

    location /chat {
        proxy_pass http://127.0.0.1:3001/chat;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
        proxy_cache_bypass $http_upgrade;
    }

    location /streams {
        proxy_pass http://127.0.0.1:3001/streams;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
        proxy_cache_bypass $http_upgrade;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;

        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_cache_bypass $http_upgrade;
    }
}
```

啟用 site：

```bash
sudo ln -s /etc/nginx/sites-available/live.gp777s.com /etc/nginx/sites-enabled/live.gp777s.com
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
```

---

## 14. 測試 HTTP 與 WS

測 Next.js 本機：

```bash
curl -I http://127.0.0.1:3000
```

測 Nginx HTTP：

```bash
curl -I http://live.gp777s.com
```

測外部 WS：

```bash
wscat -c ws://live.gp777s.com/chat
wscat -c ws://live.gp777s.com/streams
```

如果都 `Connected`，代表 HTTP 與 WS 已通。

---

## 15. 安裝 Let's Encrypt SSL 憑證

瀏覽器正式環境通常會使用：

```text
wss://live.gp777s.com/chat
wss://live.gp777s.com/streams
```

所以必須安裝 HTTPS 憑證。

安裝 Certbot：

```bash
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
```

申請憑證：

```bash
sudo certbot --nginx -d live.gp777s.com
```

過程中如果詢問是否 redirect HTTP to HTTPS，建議選：

```text
2: Redirect
```

檢查 Nginx：

```bash
sudo nginx -t
sudo systemctl reload nginx
```

確認 443 已啟動：

```bash
sudo ss -lntp | grep ':443'
```

測 HTTPS：

```bash
curl -I https://live.gp777s.com
```

---

## 16. HTTPS / WSS 的 Nginx 注意事項

Certbot 可能會建立 `listen 443 ssl` 的 server block。

請確認 HTTPS 的 `server { ... }` 內也有：

```nginx
location /chat {
    proxy_pass http://127.0.0.1:3001/chat;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_read_timeout 86400;
    proxy_send_timeout 86400;
    proxy_cache_bypass $http_upgrade;
}

location /streams {
    proxy_pass http://127.0.0.1:3001/streams;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_read_timeout 86400;
    proxy_send_timeout 86400;
    proxy_cache_bypass $http_upgrade;
}

location / {
    proxy_pass http://127.0.0.1:3000;

    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_cache_bypass $http_upgrade;
}
```

如果 `/chat` 和 `/streams` 只存在於 `listen 80` 的 server block，會出現：

```text
ws://live.gp777s.com/chat      OK
ws://live.gp777s.com/streams   OK
wss://live.gp777s.com/chat     Failed
wss://live.gp777s.com/streams  Failed
```

這代表 HTTP WS 已通，但 HTTPS/WSS 未正確代理。

---

## 17. 測試 WSS

```bash
wscat -c wss://live.gp777s.com/chat
wscat -c wss://live.gp777s.com/streams
```

成功時會看到：

```text
Connected (press CTRL+C to quit)
```

`/streams` 可能會收到加密後的資料，例如：

```text
U2FsdGVkX18...
```

這代表 stream 狀態推送有正常送出。

---

## 18. 常用檢查指令

查看 PM2：

```bash
pm2 list
pm2 logs live-next --lines 80
pm2 logs live-ws --lines 80
```

查看 port：

```bash
ss -lntp | grep -E '3000|3001|80|443'
```

查看 Nginx 設定：

```bash
sudo nginx -t
sudo nginx -T | grep -n "listen 443\|location /chat\|location /streams\|server_name live.gp777s.com"
```

重載 Nginx：

```bash
sudo systemctl reload nginx
```

查看 Nginx log：

```bash
sudo tail -f /var/log/nginx/live.gp777s.com.error.log
sudo tail -f /var/log/nginx/live.gp777s.com.access.log
```

測 HTTP：

```bash
curl -I http://127.0.0.1:3000
curl -I http://live.gp777s.com
```

測 HTTPS：

```bash
curl -I https://live.gp777s.com
```

測 WS：

```bash
wscat -c ws://127.0.0.1:3001/chat
wscat -c ws://127.0.0.1:3001/streams
wscat -c ws://live.gp777s.com/chat
wscat -c ws://live.gp777s.com/streams
```

測 WSS：

```bash
wscat -c wss://live.gp777s.com/chat
wscat -c wss://live.gp777s.com/streams
```

---

## 19. 常見問題

### 19.1 npm ci 顯示找不到 package.json

錯誤類似：

```text
Could not read package.json
```

原因：不在專案目錄。

解法：

```bash
cd /var/www/live.gp777s.com
npm ci
```

---

### 19.2 npm EACCES permission denied

錯誤類似：

```text
EACCES: permission denied, open '/var/www/live.gp777s.com/package-lock.json'
```

解法：

```bash
sudo chown -R je4122731:www-data /var/www/live.gp777s.com
sudo chmod -R 775 /var/www/live.gp777s.com
```

---

### 19.3 wscat 連 `ws://127.0.0.1:3001` 顯示 socket hang up

原因：此專案 WS 不在根路徑 `/`。

正確測法：

```bash
wscat -c ws://127.0.0.1:3001/chat
wscat -c ws://127.0.0.1:3001/streams
```

---

### 19.4 ws:// 通，但 wss:// 失敗

原因通常是：

1. 未安裝 SSL 憑證
2. 443 沒開
3. HTTPS server block 沒有 `/chat`、`/streams` proxy 設定
4. Certbot 修改 Nginx 後沒有 reload

檢查：

```bash
curl -I https://live.gp777s.com
sudo ss -lntp | grep ':443'
sudo nginx -T | grep -n "listen 443\|location /chat\|location /streams"
```

---

### 19.5 PM2 重開機後沒有恢復

重新執行：

```bash
pm2 save
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u je4122731 --hp /home/je4122731
pm2 save
```

---

## 20. 完整上線檢查清單

上線前確認：

```text
[ ] GCP firewall 已開 80 / 443
[ ] DNS live.gp777s.com 已指向 GCP 外部 IP
[ ] Nginx active running
[ ] Node.js 已安裝
[ ] 專案已上傳至 /var/www/live.gp777s.com
[ ] .env 已設定
[ ] .next 已存在
[ ] npm ci --omit=dev 已完成
[ ] PM2 live-next online
[ ] PM2 live-ws online
[ ] 3000 listening
[ ] 3001 listening
[ ] http://live.gp777s.com 可訪問
[ ] ws://live.gp777s.com/chat 可連線
[ ] ws://live.gp777s.com/streams 可連線
[ ] Let's Encrypt SSL 已安裝
[ ] https://live.gp777s.com 可訪問
[ ] wss://live.gp777s.com/chat 可連線
[ ] wss://live.gp777s.com/streams 可連線
[ ] PM2 startup 已設定
[ ] pm2 save 已執行
```

---

## 21. 部署更新流程

日後更新版本：

本地：

```bash
npm ci
npm run build
rsync -avz --delete \
  .next public package.json package-lock.json next.config.js ecosystem.config.js \
  data i18n lib _server gp-live.sqlite \
  je4122731@YOUR_GCP_EXTERNAL_IP:/var/www/live.gp777s.com/
```

GCP：

```bash
cd /var/www/live.gp777s.com
npm ci --omit=dev
pm2 restart live-next
pm2 restart live-ws
pm2 save
```

驗證：

```bash
curl -I https://live.gp777s.com
wscat -c wss://live.gp777s.com/chat
wscat -c wss://live.gp777s.com/streams
```

---

## 22. WHIP 代理（OBS 推流）

> **注意**：`sites-enabled/` 僅存在於 Git 倉庫，GCP 上 Nginx 實際路徑是 `/etc/nginx/sites-available/live.gp777s.com`，不要從 `/var/www/live.gp777s.com/sites-enabled/` 複製。

### 22.1 本機上傳到 GCP

在本機專案目錄（Windows PowerShell 範例，請改 `gplive` 為你的 SSH 別名或 `user@IP`）：

```powershell
# whip-proxy 目錄
scp -r .\whip-proxy gplive:/var/www/live.gp777s.com/

# Nginx 設定（含 WHIP location）
scp .\deploy\nginx\live.gp777s.com.conf gplive:/tmp/live.gp777s.com.conf
```

### 22.2 在 GCP 上安裝 whip-proxy

若 `scp` 曾用 root 上傳，需先修正目錄擁有者（否則 `npm install` 會 EACCES）：

```bash
sudo chown -R "$(whoami):$(whoami)" /var/www/live.gp777s.com/whip-proxy
rm -rf /var/www/live.gp777s.com/whip-proxy/node_modules
```

```bash
cd /var/www/live.gp777s.com/whip-proxy
bash install-on-gcp.sh
```

若 PM2 顯示 online 但 `curl :8787` 失敗，多半是依賴沒裝完，執行 `pm2 logs whip-proxy` 查看 `Cannot find module`。

應看到 `ok`，且：

```bash
pm2 list
# 應有 whip-proxy | online

curl -i http://127.0.0.1:8787/health
# HTTP/1.1 200 ok
```

### 22.3 更新 Nginx

```bash
sudo cp /tmp/live.gp777s.com.conf /etc/nginx/sites-available/live.gp777s.com
sudo nginx -t
sudo systemctl reload nginx
```

確認 WHIP 區塊已生效：

```bash
sudo grep -n webRTC /etc/nginx/sites-available/live.gp777s.com
```

### 22.4 URL 格式

推流（OBS / WHIP）：

```text
https://live.gp777s.com/webRTC/publish/{stream_key}
```

播放（瀏覽器 / WHEP）：

```text
https://live.gp777s.com/webRTC/play/{stream_token}
```

`.env` 設 `NEXT_PUBLIC_WHIP_PUBLISH_ORIGIN=https://live.gp777s.com`（推流與播放共用此代理網域）。

Nginx 需同時有 `location ~ ^/webRTC/play/` 與 `^/webRTC/publish/`（見 `deploy/nginx/live.gp777s.com.conf`）。

---

## 23. 最終服務拓撲

```text
live.gp777s.com
  ↓
Nginx
  ├── HTTP 80  → HTTPS redirect
  ├── HTTPS 443
  │     ├── /webRTC/publish/…  → 127.0.0.1:8787 WHIP 推流
  │     ├── /webRTC/play/…     → 127.0.0.1:8787 WHEP 播放
  │     ├── /{key}/webRTC/…    → 127.0.0.1:8787（session PATCH/DELETE）
  │     ├── /        → 127.0.0.1:3000 Next.js
  │     ├── /chat    → 127.0.0.1:3001/chat
  │     └── /streams → 127.0.0.1:3001/streams
  ↓
PM2
  ├── live-next
  ├── live-ws
  └── whip-proxy
```

這套部署策略的核心是：本地打包、GCP 跑服務、Nginx 做流量入口、PM2 做進程管理、Let's Encrypt 補齊 HTTPS/WSS。架構清楚，後續維運不會變考古現場。
