# 巡樓部署 (infra)

部署拓樸：

```
瀏覽器 → nginx(systemd, :80/:443)
            ├─ 靜態前端  /var/www/haixun  (frontend/dist)
            └─ /api 反向代理 → Go gateway (systemd, 127.0.0.1:8890)
Go gateway / Go worker (systemd) → Mongo / Redis (docker compose, 綁 127.0.0.1)
Node playwright worker (systemd) → 透過 HTTP 打 gateway
```

- 資料服務（Mongo/Redis）用 docker compose，只綁 `127.0.0.1`。
- Go gateway / Go worker / Node worker 都是 systemd 原生服務。
- secret 一律放 `/opt/haixun/etc/haixun.env`（不進 repo），yaml 用 `${VAR}` 讀取。

## 目錄

```
infra/
  docker-compose.yml          # mongo + redis
  etc/haixun.env.example      # systemd EnvironmentFile 範本（secret）
  nginx/haixun.conf           # 正式環境（靜態檔 + /api）
  nginx/haixun-dev.conf       # 開發環境（Vite 前端 proxy + /api）
  systemd/
    haixun-gateway.service
    haixun-worker.service
    haixun-node-worker.service
```

> compose 的 env 一律從 `deploy/.env.dev`（dev）或 `deploy/.env.prod`（prod）讀，infra 本身不再放 `.env`。

## 1. 起資料服務 (docker)

```bash
make dev-infra     # 讀 deploy/.env.dev
docker compose --env-file deploy/.env.dev -f infra/docker-compose.yml ps
```

## 2. 建置產物（本機或 CI）

```bash
make build        # 前端 dist + 兩個 linux Go binary（backend/bin/）
```

## 3. 安裝到目標主機

於目標主機（需 root）：

```bash
sudo make install
```

`make install` 會：

1. 建立使用者 `haixun` 與目錄 `/opt/haixun/{bin,etc,node-worker}`、`/var/www/haixun`。
2. 複製 `backend/bin/{gateway,worker}`、`backend/etc/gateway.prod.yaml`、`backend/etc/gateway.worker.prod.yaml`。
3. 複製 `frontend/dist/*` → `/var/www/haixun`。
4. 複製 `backend/worker/*`（Node worker）→ `/opt/haixun/node-worker`，並 `npm ci` + `npx playwright install`。
5. 安裝 `infra/systemd/*.service` 與 `infra/nginx/haixun.conf`。

接著手動建立 secret 檔（**只做一次**）：

```bash
sudo cp infra/etc/haixun.env.example /opt/haixun/etc/haixun.env
sudo chmod 600 /opt/haixun/etc/haixun.env
sudoedit /opt/haixun/etc/haixun.env   # 填入實際 secret
```

## 4. 初始化資料庫與 admin 帳號（只做一次）

Mongo 起來、secret 填好後，建立索引 / 權限 catalog / role_permissions，並建立第一個 admin：

```bash
# 可在 haixun.env 內設定 INIT_ADMIN_EMAIL / INIT_ADMIN_PASSWORD，或在這裡用環境變數覆寫
sudo make prod-init
# 等同：source /opt/haixun/etc/haixun.env 後執行 /opt/haixun/bin/tool init -f /opt/haixun/etc/gateway.prod.yaml
```

之後一般使用者可走 `POST /api/v1/auth/register` 自助註冊（前端登入頁）。

## 5. 啟用服務

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now haixun-gateway haixun-worker haixun-node-worker
sudo nginx -t && sudo systemctl reload nginx
```

## 6. 健康檢查

```bash
curl http://127.0.0.1:8890/api/v1/health
sudo systemctl status haixun-gateway haixun-worker haixun-node-worker
journalctl -u haixun-gateway -f
```

## 產生 secret

```bash
openssl rand -base64 48   # JWT access / refresh / worker secret
openssl rand -base64 32   # HAIXUN_SECRETS_KEY（機敏資料落地加密）
```

---

## 本地開發使用 nginx 反向代理（推薦搭配 https 網域）

當你用 `make run` + `make web-dev` 直接啟動前後端時，建議再加一層 nginx 來：

- 用正式網域名稱 `https://threads-tool.30cm.net` 存取
- 自動處理 http → https 轉址
- `/` 給前端 Vite（含 HMR websocket）
- `/api/` 給後端（正確處理 SSE 串流）

### 步驟

1. 確認前後端已在跑：
   ```bash
   make run          # 後端 8890
   make web-dev      # 前端 5173
   ```

2. 準備 SSL 憑證（強烈建議）：
   ```bash
   # 安裝 certbot（Ubuntu/Debian 範例）
   sudo apt install certbot python3-certbot-nginx
   sudo certbot --nginx -d threads-tool.30cm.net
   ```

3. 啟用開發版 nginx 設定：
   ```bash
   sudo cp infra/nginx/haixun-dev.conf /etc/nginx/conf.d/haixun.conf
   # 或傳統 sites-available 方式
   # sudo ln -s ... /etc/nginx/sites-enabled/

   sudo nginx -t
   sudo systemctl reload nginx
   ```

4. 存取測試：
   - https://threads-tool.30cm.net          ← 前端
   - https://threads-tool.30cm.net/api/v1/health  ← 後端

### 重要設定說明（haixun-dev.conf 內）

- `upstream haixun_frontend` → 127.0.0.1:5173
- `upstream haixun_backend`  → 127.0.0.1:8890
- `/api/` location 已開啟完整 SSE 長連線設定（proxy_buffering off 等）
- `/` location 已加上 `Upgrade` + `Connection` 讓 Vite HMR 正常運作
- 預設會把 http 301 轉 https
- SSL 路徑預設為 Let's Encrypt（certbot 會自動產生）

### 切回正式版

部署正式靜態檔後，換回原本的設定：

```bash
sudo cp infra/nginx/haixun.conf /etc/nginx/conf.d/haixun.conf
sudo nginx -t && sudo systemctl reload nginx
```

### 常見問題

- **HMR 不更新**：檢查 nginx location / 有沒有 `proxy_set_header Upgrade` 和 `Connection "upgrade"`
- **API 串流斷掉**：確認 `/api/` location 有 `proxy_buffering off; proxy_read_timeout 3600s;`
- **憑證錯誤**：先用 `curl -k` 測試，或暫時註解 return 301 那行用 http 測試
- **權限問題**：nginx 需能連 127.0.0.1:5173 / :8890（通常沒問題）
- **想同時支援 IP 直接存取**：在 server_name 後面加上 `10.0.0.5;` 或 `_`

開發時用這個 dev conf 就很夠了，之後正式上線再切回靜態檔版本。
