Metadata-Version: 2.4
Name: teamsync-cluster
Version: 0.1.14
Summary: Verified licensed TeamSync kit bootstrap
Author: TeamSync
License: Proprietary
Project-URL: Documentation, https://pypi.org/project/teamsync-cluster/
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# TeamSync 地端安裝與維護指南

TeamSync 地端版（on-prem）是放在<strong>貴公司機房</strong>運作的 TeamSync。員工用瀏覽器連到公司的 TeamSync 網站；聊天、文件與已購買的功能由機房裡的機器提供。您不需要先有 TeamSync 帳號，也不需要下載程式原始碼。

本頁的 `teamsync-cluster` 有兩個工作階段：

1. 在有 Internet 的<strong>下載電腦</strong>安裝小工具，使用 <strong>license key（授權金鑰，TeamSync 提供的兌換碼）</strong>取得 <strong>kit（安裝包，包含程式、離線依賴套件、授權與操作文件）</strong>。
2. 把安裝包搬到<strong>機房機器</strong>，執行包內的 `./teamsync-cluster`，設定、安裝與維護。前面的 `./` 表示「執行目前資料夾裡的檔案」。

做完單機範例，您會有可登入的網站、第一位管理員、健康檢查方法，以及每日備份設定。會議、錄影、Sandbox 與 Edge Workers 依購買的授權啟用。<strong>安裝包沒有公開下載頁；安裝 PyPI 小工具本身不代表取得產品授權。</strong> PyPI 是 Python 套件的發布與安裝服務。

<strong>AI workspace 需要另外完成 hybrid 指南。</strong> TeamSync 主站留在您的伺服器，AI 工作環境建在<strong>您自己的 GCP 專案</strong>；它不是本頁「客戶自有雲端 VM」的主站安裝範例，也不是本機 Sandbox。開始前先取得相符的 workspace 授權元件、雲端工具／映像與 hybrid 指南，並確認固定公網 IPv4、UI／origin／attach 名稱與 DNS。依序完成：主站登入與備份驗收 → 既有站點 inventory → 客戶 site PKI／本機秘密 → GCP foundation／public records → relay enrollment → 兩階段 activation 與 fresh user verification → 公司／房間權限 → 三項使用者旅程。主站目前的合格拓樸為單一 `single` 節點、`entry,app,data,storage`、recording 關閉；不要直接套用 LAN-only 或 HA 範例。站端操作與 UI 設定見隨包 `system/AI-WORKSPACE-SITE.md`（[原始文件](../../docs/deployment/on-prem/AI-WORKSPACE-SITE.md)）。

時間請這樣安排：先留半天給 IT（資訊人員）確認主機、網路與授權；下載可能花數十分鐘至數小時；準備完成後，單機安裝先預留 1–2 小時，含會議錄影另留驗收時間，多機站另排維護時段。這是排程建議，並非時間保證。

```text
有網路的下載電腦
  └─ 授權金鑰 → 下載、驗證安裝包
       └─ 加密隨身碟／公司核准的傳檔方式
            ↓
客戶機房：每台機器都有固定內網 IP
  員工瀏覽器 → 公司網站名稱 → 入口 nginx → 應用、資料、檔案
                                  └─ 已授權的會議／錄影等功能

單機：上面所有工作在 a1 一台完成。
多機：入口、應用、資料、儲存等工作分給不同機器。
若需外部連線，只有入口經客戶防火牆對外；資料機不直接對外。
```

<strong>node（節點）就是一台機器</strong>；<strong>entry（入口）</strong>接收瀏覽器連線，由 nginx 這個網站轉送程式負責。<strong>內網 IP</strong> 是公司網路內的位址，例如 `192.168.50.11`；<strong>固定</strong>表示 IT 已保留且不會自動改變。安裝工具不會替您設定作業系統的 IP。

## 套件與機器對應

交付物是 <strong>kit（安裝包）</strong>的主程式與相符加購元件。本頁檔名與畫面中的 `<版本>` 代表該檔案或工具的實際版號；檔名的產品版號不含開頭的 `v`，請按實際下載的名稱替換。`<arch>` 要換成目標機的 `amd64` 或 `arm64`。`teamsync-base` 永遠必須有；加購檔只有授權金鑰列出的項目才會下載。檔案會解開到同一個 kit 根目錄，不能把加購檔解到另一套 TeamSync：

| kit 檔名 | 它提供什麼 | 單機放哪裡 | HA（高可用）放哪裡 |
|---|---|---|---|
| `teamsync-base-<版本>-<arch>.tar.gz` | 主程式、資料服務、安裝器與指南（必需） | <strong>a1</strong> 一台 `all-in-one`：nginx、API、worker、MySQL、Redis、Qdrant、Silo、Mosquitto（MQTT）、ElasticMQ（本機佇列）、Infisical＋Postgres（密鑰服務） | 入口 <strong>G</strong>：nginx（機房可用 keepalived）；應用 <strong>E</strong>：API、worker、身分／密鑰服務；資料 <strong>D</strong>：MySQL Group Replication、Postgres（Patroni）、Redis、Qdrant、EMQX、RabbitMQ；儲存 <strong>S</strong>：Silo 物件儲存 |
| `teamsync-addon-jitsi-<版本>-<arch>.tar.gz` | Jitsi 視訊會議、JVB 影音轉送、Jibri 錄影 | <strong>b1</strong> 一台；小站也可和 a1 同機 | 兩組以上 meeting group；每組有信令、JVB 與錄影機，依尖峰場數增加 |
| `teamsync-addon-edge-workers-<版本>-<arch>.tar.gz` | Edge Workers 模組執行檔與映像 | 加在 <strong>a1</strong> | 依尖峰模組數與備援需求配置專用主機；部署方式先由支援確認 |
| `teamsync-addon-sandbox-<版本>-<arch>.tar.gz` | Sandbox 隔離工作、建置與執行 runtime | <strong>專用一台</strong>，不要和資料節點同機 | 專用 runtime 主機，數量按尖峰需求再加備援；部署方式先由支援確認 |
| `teamsync-addon-agent_workspace-<版本>-<arch>.tar.gz` | AI workspace 的站端 adapter；<strong>requires the hybrid guide</strong>，另需相符授權及雲端交付物 | 已安裝的單一 base 節點；執行環境／磁碟在客戶 GCP | 本 hybrid 路徑未提供 HA 資格；依 hybrid 指南，不套用一般 HA 範例 |

包含 `agent_workspace` 的授權會由同一個 `fetch` 一併下載並驗證 cloud-tools、workspace／relay OCI 映像及 `workspace-release.json`。工具與附帶文件在 `kit/cloud/gcp/`，映像與簽章材料在 `kit/cloud/images/`；base-only 授權不會取得這些檔案。目前此交付路徑資格為 `amd64`。雲端側請先讀 `cloud/gcp/docs/ai-workspace-hybrid-gcp-client.md`，再以其中的 `import_images.py` 指令匯入您自己專案的 Artifact Registry。工具會核對簽署的 manifest、archive、SDK／protocol 與遠端 digest；不需要 TeamSync registry／repo／CI 帳號。

這張表先回答「檔案要帶到哪台」；它不會替您增加授權、建立主機或設定 IP。加購功能還要完成各自的啟用步驟：Sandbox／Edge Workers 依第 7 節使用隨包的 standalone setup（單機啟用腳本），多機方案先由 TeamSync 支援確認。若 `config` 拒絕某項加購，保留原訊息，不自行改 `cluster.json` 宣稱已啟用。Jitsi 的 cluster roles 則依第 6、8 節部署。

## 目錄

- [1. 安裝包、電腦與操作方式](#1-安裝包電腦與操作方式)
- [2. 開始前檢查表與分工](#2-開始前檢查表與分工)
- [3. 在有網路的電腦下載](#3-在有網路的電腦下載)
- [4. 搬到離線機房](#4-搬到離線機房)
- [5. 範例一：小辦公室單機](#5-範例一小辦公室單機)
- [6. 範例二：單機加會議錄影](#6-範例二單機加會議錄影)
- [7. Sandbox 與 Edge Workers](#7-sandbox-與-edge-workers)
- [8. 範例三：多機站與增減機器](#8-範例三多機站與增減機器)
- [9. 每日檢查、備份與還原](#9-每日檢查備份與還原)
- [10. 憑證與授權續期](#10-憑證與授權續期)
- [11. 升級、停機與回復舊版](#11-升級停機與回復舊版)
- [12. 常見拒絕訊息](#12-常見拒絕訊息)
- [13. 常見問題 FAQ](#13-常見問題-faq)
- [14. 尋求協助](#14-尋求協助)
- [15. 名詞表](#15-名詞表)
- [套件與機器對應](#套件與機器對應)
- [客戶自有雲端 VM 安裝](#客戶自有雲端-vm-安裝)
- [特定舊版升級注意事項](#特定舊版升級注意事項)
- [English quick reference](#english-quick-reference)

<strong>沒有 Internet 的小辦公室閱讀路徑：</strong>若只用一台主機、不含會議，只需依序讀第 <strong>1–5、9–10、11.1–11.2、12–14 節</strong>；下載由另一台有網路的電腦完成。需要會議再讀第 6 節，其他加購讀第 7 節，多機才讀第 8 節及對應升級流程。本例員工裝置只需從允許的公司內網連到 <strong>a1 的 TCP 443</strong>；管理用 SSH 與節點資料埠由 IT 使用。會議另需第 2.5 節的影音 UDP 埠。

## 1. 安裝包、電腦與操作方式

### 1.1 下載器與安裝包的分工

下載器是裝在有網路電腦上的 PyPI 小工具，負責兌換、下載與驗證；安裝包內的 `./teamsync-cluster` 才負責設定及操作機房站點。兩者各自更新，<strong>更新 PyPI 小工具，不會自動更新機房內的 TeamSync。</strong>

本頁說明正式交付安裝包的操作方式。下載時由授權頻道選擇正式發布版；操作時使用該次下載、已驗證的完整 kit，各台須使用相符的版本與架構。既有站升級前先讀第 11 節與文末的「特定舊版升級注意事項」，並保留原版 kit 的隨包文件。

| 工作 | 工具會做什麼 | 使用條件 |
|---|---|---|
| kit 的設定、逐機 `deploy`、檢查、備份、憑證操作 | 本頁列出的介面已存在 | 仍受授權、拓樸與健康檢查限制 |
| 單機入口與升級 | nginx 共用主機網路，80／443 受主機允許清單管制；升級同步外層工具與 kit 身分 | 見 2.5、5.3、11.2；不因此提供多機跨拓樸升級 |
| `site deploy` 一次部署全站 | 從 a1 問答、加入、部署、續作 | 每台須預放同版同架構 kit；需 `--access-file` 與已核對 host key |
| 依角色檢查硬體 | 依第 2.3 節檢查首次安裝最低門檻 | 正式容量仍需依人數與工作負載規劃 |
| 一般多機站跨版 `upgrade` | 先預檢，再於維護時段升級 | 只限同拓樸、相容資料／儲存映像；依 11.3–11.4 確認，不略過拒絕 |
| `deploy --confirm-schema`、叢集 `upgrade --confirm-schema`、單機 `upgrade.sh --confirm-schema` | 接收本次資料更新的核准代碼 | 只接受支援核准的該次 ticket；刪除性或不安全 schema 仍會拒絕 |

第 3.5 節的兌換重試由下載器處理，不需要先在機房安裝產品。

### 1.2 每一步在哪裡做

所有 IP、網站、帳號、檔案位置都是<strong>教學範例或要由 IT 建立的位置</strong>，不是可使用的下載網址或金鑰。`example.com` 要換成貴公司名稱。不要把文字佔位符直接當成真實設定。

| 名稱 | 是哪台 | 工作目錄 |
|---|---|---|
| 下載電腦 | 可連 Internet；本頁命令用 Ubuntu 24.04（Windows 可用 WSL2／虛擬機，見 3.1） | `$HOME/teamsync-work`；`$HOME` 是登入者的家目錄 |
| a1 | 機房第一台 Ubuntu 24.04，範例 IP `192.168.50.11` | `/opt/teamsync`，安裝包外層 |
| 其他機器 | 依 IT 主機表，各有固定 IP | 各台都用 `/opt/teamsync` |
| 傳輸媒體 | IT 掛載的加密隨身碟 | 範例 `/media/transfer`，由 IT 確認實際位置 |
| 備份位置 | 不同主機或不同故障範圍的加密磁碟 | 範例掛在 `/mnt/site-backup`，不是 TeamSync 資料磁碟 |

<strong>terminal（終端機）</strong>是輸入指令的視窗。Ubuntu 桌面可開「終端機」；沒有桌面的伺服器，用 <strong>SSH（加密遠端登入方式）</strong>連線。`operator` 是 IT 建立的管理帳號，請換成自己的帳號。

在管理電腦終端機，從任意目錄登入 a1：

```bash
ssh operator@192.168.50.11
```

成功會進入 a1 的命令列。首次連線要求確認主機身分，先向 IT 核對指紋（代表該機身分的一串數字）再接受。若出現 `REMOTE HOST IDENTIFICATION HAS CHANGED!`，先查明是否換機，不直接略過。

<strong>sudo</strong> 表示以系統管理員權限執行指令；它詢問的是 Linux 管理帳號密碼，不是授權金鑰。輸入密碼時游標不動、沒有星號是正常的。<strong>目錄就是資料夾</strong>，`cd` 是切換目錄。程式碼區塊不含提示符號 `$`，可複製；貼上前先確認是哪台電腦。標為 `text` 的區塊是「預期畫面」，<strong>不用輸入</strong>；範例只節錄關鍵行，實際路徑、數字依現場改變。

## 2. 開始前檢查表與分工

### 2.1 先打勾，再下載

- [ ] 已向合約上的 <strong>TeamSync 業務、部署或支援窗口</strong>取得授權金鑰，確認客戶、版本、架構、有效期、可兌換次數及加購功能。遺失找原窗口，不自行猜測。
- [ ] 下載電腦可連 Internet，可安裝 Python 與 GnuPG；公司網路允許授權服務及回應指定的 HTTPS 下載目的地，清單向 TeamSync 取得。
- [ ] 每台機房機器是 <strong>Ubuntu 24.04</strong>，有 Python <strong>3.10 以上</strong>；24.04 的系統 Python 3.12 符合要求。
- [ ] CPU 架構已確認：`x86_64` 對應 <strong>amd64</strong>；`aarch64`／`arm64` 對應 <strong>arm64</strong>。下載機與目標機不同時明確指定 `--arch`。
- [ ] IT 已提供各台固定內網 IP、網段、閘道、角色、磁碟位置與管理帳號；名稱與 IP 不重複。
- [ ] CPU、RAM（記憶體）、磁碟已按 2.3 準備，另計文件、錄影、歷史檔案與備份成長。
- [ ] 每台正式 VM 的 Docker Engine 與相符 CLI 都是 <strong>25 以上</strong>；kit 會帶自己的映像，但不會替主機升級 Docker。
- [ ] 每台正式 VM 已啟用 <strong>cgroup v2（Linux 資源限制機制）</strong>；可用 `test -f /sys/fs/cgroup/cgroup.controllers && echo cgroup-v2-ready` 預先檢查。
- [ ] 已準備網站名稱及 <strong>DNS（把網站名稱對應到 IP 的通訊錄）</strong>，員工裝置與伺服器都能解析。
- [ ] 已選 <strong>憑證（certificate，讓瀏覽器確認網站身分並加密連線的證明）</strong>：公司內網信任根，或自備正式憑證。
- [ ] IT 已確認 <strong>防火牆（firewall，決定連線能否通過的門禁）</strong>、連接埠與時間同步；可從主控台救援。
- [ ] 已準備完整安裝包的離線保存位置、異機備份空間及密語另存位置。
- [ ] 會議、錄影、Sandbox、Edge Workers 的授權與下載內容已包含所需功能，沒有的先不選。

### 2.2 誰做什麼

| 工作 | 客戶 IT／現場管理員 | TeamSync 部署／支援 |
|---|---|---|
| 授權 | 確認需求，保管金鑰與合約資訊 | 發放／續發授權，確認版本、架構、功能 |
| 主機與磁碟 | Ubuntu、固定 IP、掛載磁碟、管理帳號 | 依角色與使用量協助核算規格 |
| DNS、憑證、防火牆 | 提供名稱與憑證、派送裝置信任、入口轉送 | 說明工具規則及驗收項目 |
| 下載與安裝 | 照步驟操作，記錄成功或拒絕訊息 | 處理授權用量、缺包與程式拒絕 |
| 日常營運 | 檢查狀態與備份，安排更新、還原演練 | 診斷與版本轉換，審查需核准的資料更新 |
| 密碼與復原 | 分別保管網站密碼、加入檔與備份密語 | 不需您把金鑰或私鑰貼到工單 |

### 2.3 硬體底線不是正式容量保證

<strong>≤30 人、不含會議的小站，請聯絡 TeamSync 依文件量與使用方式確認規格；程式與隨包文件沒有專門的「30 人配備保證」。</strong>下方程式門檻只表示能通過安裝檢查，採購仍需容量規劃。

<strong>CPU</strong> 是處理運算的晶片，<strong>vCPU</strong> 是分配的運算核心數；<strong>GiB</strong> 是程式計算記憶體與空間的單位，略大於硬碟標示 GB。<strong>CLI</strong> 是文字命令操作介面。表內磁碟指<strong>可用空間</strong>。

工具對首次安裝依角色檢查如下；這些仍只是通過檢查的最低值，不是正式容量保證：

| 角色／CLI 值 | 平常意思 | vCPU | RAM GiB | 可用磁碟 GiB |
|---|---|---:|---:|---:|
| `entry` | 網站入口 | 2 | 2 | 10 |
| `app` | 執行網站 API 與背景工作 | 4 | 8 | 20 |
| `data` | 資料庫、搜尋、訊息服務 | 4 | 12 | 30 |
| `storage` | Silo 檔案儲存，相容 MinIO | 2 | 4 | 20 |
| `meeting` | Jitsi 會議協調 | 4 | 4 | 15 |
| `media` | JVB，轉送聲音影像 | 2 | 2 | 10 |
| `recorder` | Jibri，錄下會議 | 4 | 8 | 20 |
| `sandbox` | 隔離程式工作 | 4 | 8 | 20 |
| `edge` | Edge Workers 模組 | 4 | 8 | 20 |
| 共用單機主程式，不含會議 | `entry,app,data,storage`、`single` | 4 | 16 | 40 |
| 共用單機，含會議／錄影 | `all-in-one`、`single` | 8 | 24 | 60 |

<strong>API</strong> 是網站功能呼叫後端程式的介面。一般多角色機器取 CPU 最大值、RAM 與磁碟加總；共用單機採表末特別門檻。另檢查 Docker 資料所在檔案系統、各儲存磁碟及有指定的錄影目錄；不要漏掉 `/var/lib/docker`。既有站低於首次安裝門檻會警告並保留資料繼續，不應靠此長期維持不足容量。

隨包 `system/CLUSTER.zh-TW.md` 的正式規劃建議：≤100 人不含會議，<strong>8 vCPU／32 GB／500 GB SSD</strong>；主程式＋Jitsi 雙機，A <strong>12 vCPU／32 GB／500 GB 加錄影空間</strong>，B <strong>16 vCPU／32 GB／250 GB</strong>。SSD 是較快的固態硬碟。這些是規劃建議，不是已測得的人數保證。

錄影目前以<strong>同一個原始物件播放</strong>，沒有第二份播放版本。保留空間按較高的既有高動態量測加 30% 餘裕、向上估 <strong>每錄影小時 3 GB</strong>；每天 2 小時、保留 30 天，僅錄影約 <strong>180 GB 邏輯空間</strong>。另計檔案、舊版本、備份、erasure raw 空間與本機上傳積壓。

<strong>按人數估加購容量（2026-10-27 校正）</strong>：下表是獨立部署的等效資源預算，數字為「台數 × 每台 vCPU／RAM GiB／SSD GB」，已含 30% 餘裕與向上選型。量測 kit 固定於 master `ccac34ce141e94045e5646ecee5a1d484a22ac40`；既有站由支援核對實際配置。主程式與 Jitsi 影音仍按前述 PDF 規格；已有 B／全同機錄影名額可扣抵，不重複採購 C。合併主機須合計容量，故障備援另加。校正 CPU 是 GCP Spot 的 <strong>Intel Ice Lake／Xeon @ 2.60GHz</strong> 與 <strong>Ampere Altra／Neoverse-N1</strong>，不是用 32 vCPU 建置機直接推人數保證。

| 人數 | 錄影（原生每台一槽） | Sandbox（同時工作＋建置） | Edge Workers | Voice |
|---|---|---|---|---|
| ≤50 | 1 × <strong>8／16／200</strong>；1 場 | 1 × <strong>8／16／200</strong>；1 工作＋1 建置 | 1 × <strong>4／8／100</strong>；3 模組、2 requests/s | 授權分包未含；另案核算 |
| ≤100 | 1 × <strong>8／16／200</strong>；1 場 | 1 × <strong>8／16／200</strong>；1 工作＋1 建置 | 1 × <strong>4／8／100</strong>；5 模組、4 requests/s | 授權分包未含；另案核算 |
| ≤300 | 3 × <strong>8／16／200</strong>；3 場 | 1 × <strong>8／16／200</strong>；2 工作＋1 建置 | 1 × <strong>4／8／100</strong>；15 模組、12 requests/s | 授權分包未含；另案核算 |
| ≤1,000 | 10 × <strong>8／16／200</strong>；10 場 | 1 × <strong>16／32／200</strong>；4 工作＋1 建置 | 1 × <strong>4／8／200</strong>；50 模組、40 requests/s | 授權分包未含；另案核算 |

<strong>假設可以改：</strong>尖峰 10% 員工開會、每場最多 10 人且每場錄一份；20% 員工活躍、其中 2% 同時執行一個 standard Sandbox 工作，另有一個建置；每 20 人一個 Edge 模組，活躍使用者每 5 秒呼叫一次。這些是規劃情境，沒有量過四個人數級別的整站壓力。Edge 出貨入口每個來源 IP 為 50 requests/s、burst 100，合計流量須依實際來源位址規劃；增加 CPU 不會改變這個限流。

<strong>不熟悉硬體時：</strong>先數最忙時同時做幾件事，再對照表格；例如 300 人、30 人開會、每場 10 人，就是三個錄影名額。每日錄影時數要把所有會議相加：三場各 2 小時、留 30 天，按 3 GB／小時另備 <strong>540 GB 邏輯物件空間</strong>。工作更重、同時更多或要容忍一台故障，就按使用量與備援另加。完整方法、原生錄影一槽限制、實測工作與原始數據，請在 kit 開啟 `system/addon-sizing.md`；Voice 的獨立 engine 校正不代表本授權分包已包含 Voice。

### 2.4 四種網路：我該選哪一種

設定精靈問「客戶網路類型」時，照 IT 的實際環境選；<strong>下載電腦有網路，不表示機房有網路</strong>。四種都保留每台固定內網 IP，不替您申請外部位址或變更網卡。

| 我是哪一種環境？ | 精靈答案 | 平常話與 IT 要準備的事 |
|---|---|---|
| 機房無 Internet，只讓辦公室內網的人使用 | <strong>`lan-only`</strong> | 純內網，不填外部位址、不設 Internet 轉送。網站名稱走內部 DNS／hosts，憑證用 kit 私有 CA，仍需可用的內網時間來源；詳下方專節 |
| 公司有外部固定 IP，由防火牆把外部連線送進唯一入口 | `nat-entry` | NAT 是由防火牆把外部門牌轉送到內網機器。各台只用內網 IP，外部網站與影音都經入口；IT 提供固定外部 IPv4 及 TCP／UDP 轉送 |
| 入口有兩張網卡，一張接內網、一張接對外區域 | `dual-homed-entry` | 雙網卡入口；DMZ 是公司隔離出來的對外網路區。IT 提供每台入口的內網及 DMZ IPv4，其餘機器留內網；多入口須用既有 `external-lb`，不是浮動內網 IP 會一併接手對外網卡 |
| IT 已替每台另配置可路由位址，不靠同一個 NAT 入口轉影音 | `routed` | 路由是網路設備知道如何抵達各個位址。精靈會逐台問 routable IPv4；這不表示資料庫應對公網開放，仍套角色允許清單。僅供 IT 已有這種配置的原生多機方案 |

`dual-homed-entry`、`routed` 不能套在本頁第 5–6 節的共用單機流程；它只支援 `nat-entry`、`lan-only`。不確定就先讓 IT 按上表確認，不能因為看見「對外」就替所有節點填公網 IP。

#### 沒有 Internet、只用辦公室內網：選 `lan-only`

<strong>位置：機房 a1，`/opt/teamsync`；執行第 5 節的設定問答。</strong>網路題填 `lan-only`、TLS 題填 `1`，網站名稱填 IT 提供的內部名稱；單入口選 `single`。此模式不問外部影音 IP，也不設定外部位址。

| 可以做什麼 | 需要什麼條件／不能做什麼 |
|---|---|
| 辦公室允許的內網裝置登入、聊天、上傳下載 | 各裝置能解析網站名稱、信任 kit 的公開 CA 根，內網服務健康 |
| 使用已授權的內網會議、錄影與本機功能 | 有完整授權功能包、足夠容量，裝置到 JVB 的內網影音埠可達 |
| 使用 AI 對話、文件搜尋等模型功能 | 須由 IT 準備機房可達的<strong>內網模型端點</strong>，並註冊所需聊天、embedding 等模型；在 kit 內開啟 kit 內的 `system/README.zh-TW.md`「離線環境的 AI 模型設定」。此為隨包文件位置，在 PyPI 閱讀時請改在本機 kit 開啟。沒有內網模型就不能把安裝成功當作 AI 已可用 |
| 手機系統推播、平台寄信／外部 email、LINE 等外部通道 | 依賴 Internet 上的推播／郵件／LINE 服務；完全離線時不能送達。若公司另有經 IT 核准、設定完成的內網 SMTP 郵件服務，可另驗收內部寄信，並非預設已可用。網站內聊天與瀏覽器即時連線由內網提供 |
| 在離線機房安裝、維護與備份 | kit 先在別台下載再搬入；備份放內網可達的異機位置 |
| 從辦公室外、家裡或行動網路連線 | <strong>本方案不提供</strong>；沒有對外入口與轉送，外部同事／訪客無法加入網站或會議 |
| 現場直接兌換授權、抓升級包、向公開 CA 申請憑證 | 無 Internet 時不能直接做；在有網路電腦處理，再按本頁搬入相符檔案 |

IT 應準備三件事：

1. <strong>名稱通訊錄：</strong>內部 DNS 將網站名稱指向入口的內網 IP；沒有 DNS 時，IT 在每台需要使用的電腦與伺服器設定 hosts（該機自己的名稱對照檔）。只改 a1 不會讓同事電腦自動知道名稱。Ubuntu／macOS 是 `/etc/hosts`；Windows 是 `C:\Windows\System32\drivers\etc\hosts`（記事本以系統管理員身分開啟，儲存時不加 `.txt`）。加入一行 `192.168.50.11 teamsync.example.com`，換成現場值；手機優先用內部 DNS。
2. <strong>裝置信任：</strong>按 5.5 派送 kit 的公開 CA 根並核對指紋，無需 Internet 簽發。憑證仍有期限，日後按第 10 節維護，不能略過瀏覽器警告。
3. <strong>內部時間：</strong>每台使用機房內可達的 NTP 伺服器。NTP 不必在 Internet 上；IT 將 Ubuntu 的 chrony（時間同步程式）指向它，確認同步後才部署。<strong>只有一台也會檢查同步，沒有「單機略過」選項。</strong>沒有既有內部 NTP 時，請 IT 先提供可達且可靠的時間服務；只手動校時、或只開啟同步開關，不能保證通過。工具接受 `timedatectl show --property=NTPSynchronized --value` 為 `yes`，或 `chronyc tracking` 顯示正常同步、有效層級且偏差小於 1 秒。未同步會阻止部署，`doctor` 也會判不健康；不要為過關偽造狀態或在服務中途跳時。

成功條件是內網裝置可登入、功能驗收與 `doctor` 通過；「離線」不等於可以略過 DNS、TLS 或時間檢查。`lan-only` 是部署的網路規劃值，不代替實體斷網或外圍防火牆；IT 仍須落實機房隔離。

> 現場可用範圍以交付版本與本站驗收紀錄為準。

<strong>實機驗證（2026-10-27）：</strong>在完全斷網的 Ubuntu 24.04 amd64 機器上，以 `lan-only`、TLS `1`（kit 私有 CA）、內網 NTP 完成單機＋會議錄影安裝。辦公室電腦可登入、聊天、上傳／下載檔案、上傳文件後搜尋，兩人會議錄影可播放與跳轉，`status`／`doctor` 通過；整段安裝與使用期間，機房主機<strong>沒有任何對外網址查詢</strong>。
- 下載前先依 3.1 更新小工具，解包會保留網站所需的目錄讀取權限；即使下載環境採嚴格檔案權限（`umask 077`），也不必自行放寬私密檔案權限。
- 安裝包的 Qdrant（向量資料庫）、ONNX Runtime（文件搜尋元件）與錄影用瀏覽器已關閉外部遙測。主機不需要為這些遙測連 Internet；AI、推播、外部郵件等產品功能仍須各自具備可達的服務端點。

### 2.5 連接埠

<strong>port（連接埠）</strong>是同一 IP 上服務的門牌號碼；<strong>TCP</strong> 用於網站等連線，<strong>UDP</strong> 用於影音等資料傳送。

| 從哪裡到哪裡 | 需要的連線 |
|---|---|
| 下載電腦 → Internet | TCP 443：PyPI、授權服務、授權指定的檔案下載；Ubuntu 套件來源依公司政策放行 |
| 員工／外部使用者 → 入口 | TCP 443：網站、API、即時連線與會議信令 |
| 使用者 → 單機入口的 HTTP 轉址 | TCP 80：只轉到 HTTPS；來源限制與 443 相同，直接使用 `https://` 不需先連 80 |
| 外部會議用戶 → 入口 | `nat-entry` 每個 JVB 一個 UDP 埠，預設依序 <strong>10001、10002……</strong>，以計畫為準，入口再轉送至 JVB |
| LAN 會議用戶 → 內網 JVB | 該 JVB 的計畫 UDP 埠；`lan-only` 不建立外部轉送 |
| 管理電腦／管理節點 → 各台 | SSH TCP 22 或 IT 指定埠，限管理來源 |
| 節點彼此 | 依角色允許清單；常見 DATA TCP 3306/33061、5432/8008、2379/2380、6379/26379、6380/26380、6333–6335、5671/25672、8883；儲存 9000/9001、應用 8000/8091、內部入口 9443、節點觀測 9444 等，不對外開放 |
| 節點 → 公司 DNS／時間服務 | DNS 與 NTP（讓時鐘保持一致的服務），依 IT 內網配置 |

<strong>單機入口：</strong>nginx 仍在 kit 的固定映像容器內執行，但使用 `network_mode: host`（共用主機網路）。預設 TCP 80／443 直接由主機接收，不再經 Docker 發布埠的轉送路徑；`sudo ./teamsync-cluster deploy --apply-firewall` 的主機允許清單因此同時管制這兩埠。已設定其他 HTTP／HTTPS 埠時，規則跟隨實際設定，詳 5.3。

單機入口代轉的私有服務只綁 `127.0.0.1`（限本機）：Silo <strong>9000</strong>、MQTT WebSocket <strong>8083</strong>、已啟用的 Edge gateway <strong>9080</strong>、同機 Jitsi HTTPS <strong>8443</strong>；backend <strong>8000</strong>、MySQL <strong>3306</strong>、Infisical <strong>8090</strong> 也維持本機限定。這些是預設埠，不要為了外部使用者把它們直接對外開放；分機 Jitsi 依其 private IP 與角色規則處理。

不需雲端帳號或雲端負載平衡。<strong>單入口選 `single`，沒有 VIP。</strong> VIP 是可由不同入口接手的共用內網位址；只有工具支援且 IT 完成網路、保留位址與隔離條件才選 `vrrp`。有既有硬體流量分配設備才選 `external-lb`，詳第 8 節。

單機只用 `lan-only` 或 `nat-entry`。後者由 IT 把外部連線轉送至入口，需要固定外部 IPv4，其餘機器仍是固定內網 IP。不把資料庫與管理埠對外開放，不把所有機器填成同一 IP。

### 2.6 選憑證

| 選項 | 適用情境 | 準備 |
|---|---|---|
| TLS `1`：內網私有 CA | 公司內網小站 | 工具產生身分；IT 把公開 CA 根安裝到員工裝置 |
| TLS `2`：自備正式／企業憑證 | 已有網站憑證 | `fullchain.pem`（網站與完整中繼憑證鏈）、相符 `private.key`（私鑰）、信任根 PEM 檔 |

<strong>TLS</strong> 是 HTTPS 的加密與身分驗證；<strong>CA</strong> 是簽發憑證的單位，<strong>PEM</strong> 是憑證檔的文字格式。模式 2 須涵蓋網站名稱，首次設定至少剩 30 天；用 IP 連線，憑證也須涵蓋該 IP。工具不代向公開 CA 申請或自動完成續約。

<strong>可以直接用 IP 嗎？</strong>首次設定的網站地址可填固定 IPv4；模式 1 會把入口的內網 IP 與設定的網站地址放入憑證的 SAN（允許的名稱／IP 清單），模式 2 則必須自備涵蓋該 IP 的憑證。若本站原本用 DNS 名稱，日常仍用該名稱登入：改用 IP 即使憑證涵蓋，也不代表網站設定與登入來源已切換。DNS 萬用字元憑證不涵蓋 IP；不要為省掉 hosts 而略過憑證警告。

## 3. 在有網路的電腦下載

### 3.1 安裝小工具

<strong>辦公室只有 Windows 也能準備：</strong>請 IT 提供 <strong>WSL2 的 Ubuntu 24.04</strong>、Ubuntu 24.04 虛擬機，或借用一台可上網的 Ubuntu 電腦；在其 Ubuntu 終端機照下方操作。WSL2／虛擬機的工作目錄放 Linux 家目錄，搬運時保留 Linux 權限。這些是下載環境，機房正式伺服器仍須 Ubuntu 24.04。

`fetch` 本身需要 <strong>Python ≥3.8、可在命令列執行的 `gpg`、HTTPS 連線與足夠磁碟</strong>，不需要 Docker，也不要求下載機與目標機架構相同。macOS 可由 IT 安裝 Python 與 GnuPG 後使用下載器，但下方 `apt-get` 是 Ubuntu 指令；本頁完整流程請使用上述 Ubuntu 環境。原生 Windows 的權限、傳檔及續授權流程不在本頁操作範例內，勿把 Bash 命令直接貼到 PowerShell。

<strong>位置：下載電腦，Ubuntu 24.04，一般管理帳號家目錄。</strong>目的：準備 Python（執行程式的工具）與 GnuPG／`gpg`（驗證簽章、確認來源的工具）。以下準備命令是 Ubuntu／Python 標準工具，不是 kit 子命令。

```bash
cd "$HOME"
mkdir -p "$HOME/teamsync-work"
sudo apt-get update
sudo apt-get install -y python3 python3-venv gnupg
python3 -m venv "$HOME/teamsync-work/.venv"
. "$HOME/teamsync-work/.venv/bin/activate"
python -m pip install --upgrade teamsync-cluster
cd "$HOME/teamsync-work"
teamsync-cluster --version
gpg --version
```

`pip` 安裝 Python 套件；`venv` 建立獨立工作環境，避免修改系統 Python。下載器宣告 Python <strong>3.8 以上</strong>、沒有額外 Python 執行依賴；本教學用 Ubuntu 24.04 的 Python 3.12。完整 kit 工具需要 <strong>3.10 以上</strong>。

成功會看到版本行（以下 `gpg` 省略其實際版本數字）：

```text
teamsync-cluster bootstrap <版本>
```

若 `pip` 找不到套件，先確認公司允許的 PyPI 來源可取得 `teamsync-cluster`；若 Ubuntu 套件來源無法連線，請 IT 放行。離線機房不做這一步。開新終端機後要重新執行 `.` 開頭的環境啟用命令。

### 3.2 隱藏輸入授權金鑰

<strong>位置：下載電腦，`$HOME/teamsync-work`，已啟用 `.venv`。</strong>先和 TeamSync 確認金鑰涵蓋所需功能與目標機的 <strong>amd64</strong> 架構；ARM 選法在下一節。

```bash
cd "$HOME/teamsync-work"
teamsync-cluster fetch --dest ./teamsync-download --arch amd64
```

工具問：

```text
TeamSync license key (hidden):
```

在這裡貼上交付的金鑰，按 Enter。沒有文字顯示是正常的；不要把金鑰寫在指令後面。工具兌換授權，下載主程式與已授權加購包，驗證簽章、每份檔案的 <strong>SHA-256（檔案內容指紋）</strong>及離線授權。

成功範例只節錄關鍵行：

```text
Downloaded: teamsync-base-<版本>-amd64.tar.gz
teamsync-base-<版本>-amd64.tar.gz: OK
License signature: OK
Ready: /home/operator/teamsync-work/teamsync-download/kit
```

看到 `Ready:` 才算下載、檢查與解開完成，不能只看到 `Downloaded:` 就搬走。若顯示 `Install GnuPG (gpg) on this connected machine before redeeming.`，回 3.1 裝好 `gnupg` 再重跑；其他錯誤見 3.5 與第 12 節。

### 3.3 架構、版本與其他金鑰輸入方式

<strong>位置仍是下載電腦的 `$HOME/teamsync-work`。以下為替代用法，選一種，不為了試寫法重複兌換。</strong>

arm64 目標機使用另一個目的目錄，先確認授權包含它：

```bash
teamsync-cluster fetch --dest ./teamsync-download-arm64 --arch arm64
```

`--arch` 指<strong>機房目標機</strong>；省略會依下載電腦自動判斷，跨架構請明寫。本頁下載命令不填產品版本，由金鑰的授權頻道決定；`latest` 頻道會取兌換當時最新的正式發布版。若需固定下載授權允許的某一版，可加 `--version vX.Y.Z`。最外層 `teamsync-cluster --version` 只查看下載器；同張下載收據之後固定同版續傳。

IT 已安全提供只有金鑰一行的檔案 `$HOME/teamsync-work/license-key` 時：

```bash
cd "$HOME/teamsync-work"
chmod 600 ./license-key
teamsync-cluster fetch --license-file ./license-key --dest ./teamsync-download --arch amd64
```

`600`／`0600` 表示只有檔案擁有者可讀寫。不用帶真金鑰的 `echo` 建檔，不放共用磁碟。

自動化可用 <strong>環境變數（只傳給程式的命名資料）</strong> `TEAMSYNC_LICENSE_KEY`。下載電腦的 <strong>Bash 終端機</strong>也可隱藏讀入：

```bash
cd "$HOME/teamsync-work"
read -r -s -p 'TeamSync license key (hidden): ' TEAMSYNC_LICENSE_KEY
printf '\n'
export TEAMSYNC_LICENSE_KEY
teamsync-cluster fetch --dest ./teamsync-download --arch amd64
unset TEAMSYNC_LICENSE_KEY
```

無互動排程由公司密碼管理工具注入變數，或用 `--license-file`。成功結果同 3.2。程式雖接受 `--license`，本頁不示範把值放命令列，以免歷史或程序清單洩漏。

### 3.4 下載後的檔案

<strong>位置：下載電腦，`$HOME/teamsync-work`。</strong>只看名稱，不開啟或貼出私密收據：

```bash
cd "$HOME/teamsync-work"
ls -la ./teamsync-download
ls ./teamsync-download/downloads
ls ./teamsync-download/kit
```

成功結構如下，加購檔只在授權包含時出現：

```text
teamsync-download/
  .teamsync-fetch.json                私密收據，含會到期的下載網址
  downloads/
    SHA256SUMS
    SHA256SUMS.asc
    teamsync-release-key.asc
    安裝指南.pdf
    teamsync-base-<版本>-amd64.tar.gz
    teamsync-addon-jitsi-<版本>-amd64.tar.gz   若有 jitsi 授權
  kit/
    teamsync-cluster
    install.sh
    upgrade.sh
    license.json                     已簽署的離線授權
    安裝指南.pdf
    components/base.json
    system/                          程式、映像與文件
```

同理可能有 `sandbox`、`edge-workers` 包。`tar.gz` 是壓縮封存檔，下載器已解開為 `kit/`，不必再手動解壓。

金鑰本身不寫入目的目錄，收據及安裝後設定仍需保密。保留完整下載目錄與同版 kit，供續傳和日後還原；不可只保存很小的執行檔。

<strong>安裝包多大？</strong>容量隨版本、架構與加購映像改變，沒有固定 GB 數；下載前向 TeamSync 確認本次交付大小。下載磁碟須同時容納壓縮包與解開的 `kit/`，傳輸媒體也要容納要搬的兩份內容。完成後在下載電腦查看實際大小及媒體空間：

```bash
du -sh ./teamsync-download/downloads ./teamsync-download/kit
df -h /media/transfer
```

### 3.5 中斷後續傳

<strong>位置：原下載電腦，原 `$HOME/teamsync-work`。</strong>修復網路後，用<strong>原目的目錄、原版本、原架構</strong>：

```bash
cd "$HOME/teamsync-work"
. ./.venv/bin/activate
teamsync-cluster fetch --dest ./teamsync-download --arch amd64
```

| 情況 | 原始訊息／判斷 | 處理 |
|---|---|---|
| 大檔中斷 | `Download interrupted. Rerun fetch with the same destination to resume.` | 保留收據及 `downloads/*.part`，原命令續傳、再驗證；不重兌換 |
| 按 Ctrl+C | `Stopped. Rerun fetch with the same destination to resume.` | 同上，不換空資料夾 |
| 已有下載在執行 | `Another fetch is active. If it stopped, remove .fetch.lock and retry.` | 等原程序；只有確定已無程序才移除空鎖目錄 |
| 下載網址到期 | `Download window expired. Contact TeamSync support for a new key.` | 支援確認用量後發新金鑰，新目錄下載；舊收據不能延長網址 |

若強制終止留下空鎖，<strong>原下載電腦</strong>確認沒有其他 `fetch` 後：

```bash
cd "$HOME/teamsync-work"
rmdir ./teamsync-download/.fetch.lock
teamsync-cluster fetch --dest ./teamsync-download --arch amd64
```

`rmdir` 只刪空目錄；若不為空或不確定程序是否結束，請 IT 檢查。續傳成功仍要看到 `Ready:`。

下載器會在兌換前保存 `.teamsync-redeem.json` 的請求識別。這與下載的產品 kit 版本無關。若看到：

```text
License response interrupted. Retry in the same destination within 10 minutes; the saved request id will be reused.
```

在 <strong>10 分鐘內</strong>、相同電腦、目錄、金鑰、版本與架構重跑原命令。授權服務也需支援此機制；舊服務不提供相同保證。若出現 `Redemption replay expired` 的雙語訊息，先讓支援查用量，<strong>不要自行刪 `.teamsync-redeem.json` 重兌換</strong>。

## 4. 搬到離線機房

### 4.1 複製到加密媒體

<strong>位置：下載電腦，`$HOME/teamsync-work`。</strong>IT 先確認加密媒體掛在 `/media/transfer`、空間足夠且能保留 Linux 檔案權限：

```bash
cd "$HOME/teamsync-work"
cp -a ./teamsync-download /media/transfer/
ls -la /media/transfer/teamsync-download
```

`cp -a` 保留子目錄與隱藏檔，<strong>也會把含簽名下載網址的私密收據 `.teamsync-fetch.json` 搬上媒體</strong>。機房安裝不需要它；複製完成後，在下載電腦刪除媒體上的這一份，再安全卸除。原下載電腦的收據留在受保護位置，供續傳使用：

```bash
rm -- /media/transfer/teamsync-download/.teamsync-fetch.json
```

若中斷下載留下 `.teamsync-redeem.json`，先回第 3.5 節完成下載，不搬半成品。另一種做法是只複製已完成的 `downloads/` 與 `kit/`，不複製下載目錄外層的隱藏檔。加密媒體仍需妥善保管；一般刪檔不等於安全抹除。若 `No space left on device`，換足夠媒體再複製，不刪 kit 內容湊空間。

### 4.2 放到 a1 固定目錄

<strong>位置：機房 a1，媒體已掛好。</strong>先把下方壓縮包檔名換成本次實際名稱，再驗證搬運後的壓縮包與指南；清單是 `downloads/SHA256SUMS`，不是 `kit/SHA256SUMS`：

```bash
cd /media/transfer/teamsync-download/downloads
ls './teamsync-base-<版本>-amd64.tar.gz' ./安裝指南.pdf ./SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing
```

ARM 站把 `amd64` 換 `arm64`，有加購也先用 `ls` 確認相應壓縮包在場。簽署清單會列出其他架構與未授權功能，所以用 `--ignore-missing`；<strong>它不會替您發現應搬卻漏搬的包</strong>。本次主包、每個已購加購包與指南都須出現 `OK`，命令成功才繼續；`FAILED` 或沒有任何檔案被驗證都應停下重搬。這是對已由 `fetch` 驗過簽章的清單做搬運後內容核對，不取代簽章驗證，也不直接驗證解開後的 `kit/`。

<strong>接著在 a1 家目錄，僅適用全新、未安裝的 `/opt/teamsync`。</strong>確認不是既有站點才複製：

```bash
cd "$HOME"
sudo install -d -m 0755 /opt/teamsync
sudo cp -a /media/transfer/teamsync-download/kit/. /opt/teamsync/
sudo chown -R root:root /opt/teamsync
sudo chmod 0755 /opt/teamsync
cd /opt/teamsync
python3 --version
uname -m
sudo ./teamsync-cluster --version
ls ./teamsync-cluster ./license.json ./components/base.json
```

成功可見 Python 3.10 以上、正確 CPU 名稱、工具版本 <strong>`1.0.0`</strong>及三個檔名。`1.0.0` 是包內工具版本，不能代表產品版號；產品版本看 `components/base.json`、`system/BUILD_INFO.txt`。

<strong>Docker</strong> 把服務放在獨立容器執行；<strong>Compose</strong> 一起啟動多個容器。Ubuntu 24.04 所需工具與離線套件由完整 kit 提供，機房不用 pip、不再兌換金鑰；Docker Engine、相符 CLI（25 以上）與 cgroup v2 仍由 IT 先準備，kit 不會替主機升級它們。缺包就重搬完整授權 kit，不從網路另拉映像。

若 `Permission denied` 或檔案不見，核對媒體與複製結果。下載器若說 `Kit paths must be owned by you or root and must not be group/world writable or symlinks.`，改用管理員持有、不可供群組／所有人寫入、無符號連結的正式目錄，不用 `/tmp`。

多機每台重複此準備，架構須符合本機。新版本放另一個目錄，例如 `/opt/teamsync-next`，<strong>不覆蓋正在運作的 `/opt/teamsync`</strong>。

## 5. 範例一：小辦公室單機

### 5.1 開始設定

本例：一台 a1，固定 IP `192.168.50.11`，網站 `teamsync.example.com`，公司內網使用、不含會議。IT 已把網站名稱在公司 DNS 指向 a1，按第 4 節放好 kit。名稱與 IP 換成現場實際值。

<strong>位置：a1，`/opt/teamsync`。</strong>目的：逐題建立本站設定與身分。

```bash
cd /opt/teamsync
sudo ./teamsync-cluster config
```

### 5.2 問答逐題走

每題先中文說明，再英文輸入提示；方括號是 Enter 採用的建議值。<strong>不要每題都按 Enter</strong>：角色可能預設 `storage`，網路預設 `nat-entry`，都不是本例答案。

表內是畫面問題的關鍵文字，後附的說明與預設值由工具產生；只有適用題目才出現。

| 順序／畫面文字 | 本例輸入 | 原因與下一步 |
|---|---|---|
| 「新建叢集或加入既有叢集？new / join」 | `new` | 第一台建立本站；叢集就是共用身分的一組機器，單機也有站點身分 |
| 「要啟用哪些已授權的附加功能？逗號多選」 | `none`；無加購授權時不問 | 本例只裝主程式，不因授權有功能就全開 |
| 「這台機器要部署什麼？已授權角色」 | <strong>`entry,app,data,storage`</strong> | 同機負責入口、應用、資料與檔案，不能只接受 `storage` |
| 「選擇部署方案」 | `single` | 只用一台 |
| 「叢集名稱（小寫英數與連字號）」 | `office` | 本站標記，建立後保留 |
| 「客戶網路類型：nat-entry / dual-homed-entry / lan-only / routed」 | <strong>`lan-only`</strong> | 純內網，別沿用預設 `nat-entry` |
| 「所有節點使用的 private IPv4 網段」 | `192.168.50.0/24` | `/24` 是位址範圍，必須使用 IT 提供值 |
| 「同事連線的網站 IP 或 DNS」 | `teamsync.example.com` | 不加 `https://`、路徑或埠號 |
| 「TLS 模式：1 內網私有 CA；2 正式憑證（fullchain）」 | `1` | 工具產生內網憑證，IT 稍後派送公開信任根 |
| 「入口前端：vrrp / external-lb / single」 | `single` | 一個入口，不需浮動 IP |
| 「a1 的 IT 指派固定 private IP」 | `192.168.50.11` | 必須已設在作業系統上，建議值不符要改正 |
| 「a1 第 1 顆已掛載的磁碟路徑」 | `/mnt/teamsync/drive1`，或 IT 的實際規劃位置 | 單機儲存有下述特別說明；不要誤認填了路徑就搬移資料 |
| 「a1 第 2 顆已掛載的磁碟路徑」 | `/mnt/teamsync/drive2`，或 IT 的實際規劃位置 | 工具不格式化磁碟，原生 storage 要先由 IT 掛載 |
| 「這台機器在清單中的名稱」 | `a1`，可自動辨識而不問 | 選目前正在操作的這台 |
| 「公司名稱」 | 貴公司的名稱，例如「測試科技股份有限公司」 | 可用中文，1–32 字；單機預設 `TeamSync`，多機預設沿用叢集名稱 |
| 「管理員帳號」 | 負責網站的登入帳號，例如 `opsadmin` | 預設 `admin`，3–36 字，只用英數與 `. _ ! # -`；這是登入帳號，與電子郵件分開 |
| 「管理員電子郵件」 | 您負責網站的信箱 | `admin@example.com` 只是範例，要換成自己的 |
| 「管理員密碼」及重複確認 | 建議直接按 Enter 自動產生；也可自行輸入 | 自訂密碼須為 3–36 字，需輸入兩次且不顯示；請用密碼管理工具產生長隨機密碼 |
| 「以上計畫正確並建立設定？yes / back / no」 | 核對全表後 <strong>`yes`</strong> | 預設 `no`；`back` 重答，`no` 不建立 |
| 「管理密語」及重複確認 | 用密碼管理工具產生並保存的密語 | 用至少 24 個隨機英數／符號最容易符合規則；兩次一致、隱藏輸入 |

這些公司與管理員資料會在安裝任何服務前檢查；若欄位不符，畫面會用中英文點名，先修正再重跑。電子郵件依產品的規則檢查，不能使用 `.invalid`、`.local` 或 `.test` 這類保留網域；不需連外查詢郵件伺服器。公司顯示名稱與叢集識別名稱是不同欄位，中文公司名不會改變既有網址的產生方式。管理員密碼與「管理密語」也不同：前者登入網站，後者保護加入檔。

<strong>IT 已備好設定檔、要無互動部署：</strong>在原本的站點 JSON／YAML 內加入下列 `services.all-in-one` 區塊；這個名稱同時適用單機與多機，不代表要把多機改成單機。其餘網路、節點與授權欄位仍須完整提供。

```json
{
  "services": {
    "all-in-one": {
      "company_name": "測試科技股份有限公司",
      "admin_username": "opsadmin",
      "admin_email": "ops@example.com",
      "admin_password_file": "/root/teamsync-admin-password"
    }
  }
}
```

`company_name`、`admin_username` 省略時使用表中的預設值，`admin_email` 要填管理員的有效信箱。`admin_password_file` 指向 IT 私下準備的檔案：只有一行密碼，不含換行或控制字元，檔尾可有一個一般換行；權限必須為 `0600`，不可是符號連結。建議使用絕對路徑，相對路徑以 kit 的 `system/` 為基準。<strong>單機每次 deploy／upgrade 都會重新讀取 IT 提供的這個檔案，請妥善保留原檔與路徑，不要在初次安裝後刪除。</strong>密碼本身不能寫進 JSON／YAML，也不能放在命令列。省略整個 `admin_password_file` 欄位就會自動產生密碼；自訂密碼只會進入既有的受保護密鑰與 `0600` 密碼檔，部署輸出不會顯示密碼。

IT 安全備妥完整 `/root/site.json` 及保護加入檔的 `/root/site-passphrase`（`0600`）後，在 <strong>a1 `/opt/teamsync`</strong>執行：

```bash
sudo ./teamsync-cluster config --config /root/site.json --node a1 --yes --passphrase-file /root/site-passphrase
```

接著照 5.3 部署，不會再詢問公司或帳號。已有站點重新設定、部署或升級時，會保留原公司與管理員密碼；若新設定不同，工具會提示到網站管理介面改名或變更密碼，不能靠重跑安裝器重設帳號。

<strong>單機磁碟說明：</strong>這個組合交給既有單機部署流程，資料實際放在 Docker 持久儲存卷（容器重建後仍保留資料的空間）。問答的 `drives` 是規劃欄位，<strong>不會把單機資料自動搬到該路徑</strong>；本例保留規劃值也不代表已掛載磁碟。IT 必須確認 Docker 資料磁碟的實際容量。原生多機 `storage` 才使用這些獨立掛載點；不能把填了兩條路徑當作已有磁碟備援。

<strong>只有一顆硬碟可以嗎？</strong>本例單機可以；不要因為精靈問兩條路徑，就購買兩碟或把同一碟的兩個資料夾當備援。單機不使用這兩個規劃目錄存資料，也不要求它們已掛載；工具會連同這些路徑所在檔案系統檢查可用空間，路徑不存在時查其既有上層。實際資料與容量仍以 Docker 的儲存位置為準。<strong>原生多機 storage 則不同：每個路徑部署前都要存在，且是按計畫掛載的獨立磁碟；單純 `mkdir` 不能通過掛載檢查。</strong>

若選 TLS `2`，在 TLS 題後多三題，檔案都在 <strong>a1</strong>，由 IT 安全備妥：

| 題目 | 範例路徑 |
|---|---|
| 「正式憑證 fullchain 檔案路徑」 | `/root/teamsync-tls/fullchain.pem` |
| 「TLS 私鑰路徑（0600）」 | `/root/teamsync-tls/private.key` |
| 「信任根憑證檔案路徑」 | 公開 CA 可用 `/etc/ssl/certs/ca-certificates.crt`，企業 CA 用 IT 提供的 root PEM |

若網路選 `nat-entry`，入口題後會問「影音外部固定 IPv4（由 IT 提供；網站可另用 DNS）」。<strong>即使不裝會議，這版也問</strong>；填 IT 的入口外部 IPv4，不填 DNS。不需外部連線就返回改 `lan-only`。

成功畫面：

```text
已建立唯一的加密加入檔：/opt/teamsync/teamsync.join
Created one encrypted join file: /opt/teamsync/teamsync.join
本機角色已設定：a1；請執行 sudo ./teamsync-cluster deploy
Node a1 configured; run sudo ./teamsync-cluster deploy
```

<strong>加入檔（join file）</strong>是加密站點設定的交接檔，用剛才的<strong>管理密語</strong>開啟，和網站管理員密碼不同。長度規則是 <strong>16–1024 bytes</strong>；只用英數／符號時，一個字元就是一個 byte，建議用至少 <strong>24 個隨機字元</strong>，不要用短中文句子猜長度。最新加入檔與密語分開保存，密語另留公司核准的離線副本，不能只存在 a1。<strong>遺失密語就無法開啟該加入檔，TeamSync 也無法替您解密</strong>；保留運作中的站點與管理備份，找支援評估後續，不刪設定重新建站。

若 `兩次密語不一致 / Passphrases do not match`，重跑同一設定、核對輸入。若 `Existing configuration differs; refusing rebootstrap`，此處已有不同設定，保留原目錄與身分，不刪 `cluster/` 重建。

### 5.3 部署與防火牆

<strong>位置：a1，`/opt/teamsync`。</strong>目的：安裝離線工具、載入<strong>映像（image，容器要執行的固定程式包）</strong>並啟動服務。準備完成後，單機先預留 <strong>1–2 小時</strong>；這含載入與檢查的排程建議，實際依磁碟、映像大小及功能而變，不是程式保證的倒數時間。

經 SSH 操作時，請 IT <strong>在斷網前先備妥 `tmux`</strong>（保留遠端工作畫面的工具；不能假設 kit 已附帶）。在 a1 先開一個工作畫面，再執行部署：

```bash
tmux new -s teamsync-install
cd /opt/teamsync
sudo ./teamsync-cluster deploy --apply-firewall
```

`--apply-firewall` 套用產出的主機允許清單，並設為開機持續套用；公司外圍防火牆仍由 IT 設定。若須 IT 先審閱，先不加旗標，程式列出規則檔與套用命令。產物為 `cluster/firewall-allowlist.sh` 與 `cluster/firewall-allowlist.json`。

<strong>本例 a1（`lan-only`、不含會議）新增的主機 INPUT（主機接收連線）規則如下；單機 nginx 使用 host network，網站 80／443 都受這份規則管制：</strong>

| 來源／埠 | 套用後的行為 |
|---|---|
| IPv4 已建立及相關連線、本機 loopback | 先允許 |
| 設定的 private 網段，本例 `192.168.50.0/24` → 主機 TCP <strong>80／443</strong> | 允許 HTTP 轉址及 HTTPS；其他外部 IPv4 來源的新連線拒絕 |
| 本站 Docker bridge（容器私有網路）→ TCP <strong>80／443</strong> | 依本站實際 bridge 介面及來源網段允許容器回呼；不以此放行外部網卡流量 |
| 同一 private 網段 → TCP <strong>9444</strong> | 允許節點時間觀測（仍須憑證驗證）；其他 IPv4 來源的新連線到此埠拒絕 |
| IPv6 → 主機 TCP 80／443／9444 | INPUT 除本機 loopback 外拒絕；本站計畫使用 IPv4 |
| SSH（通常 TCP <strong>22</strong>）及其他未列管的埠 | 沿用主機既有防火牆政策；工具沒有新增 SSH 放行規則，也沒有把所有其他埠一律封閉 |

<strong>nginx 正常執行，不表示所有 Internet 來源都可連入。</strong>本例 `lan-only` 只允許設定的 private 網段存取網站；未核准來源連 80／443 被拒絕是預期行為。IT 應分別從核准與未核准來源驗證，並維持公司外圍防火牆政策；員工直接開 `https://` 網址只需 443。Silo、MQTT WS、Edge gateway、同機 Jitsi HTTPS 及其他第 2.5 節的私有上游只綁本機，不直接對外提供。

其他計畫的規則會不同：`nat-entry`／`dual-homed-entry` 的入口網站埠（共用單機預設 80／443，原生多機為 443）與計畫媒體 relay UDP，在未設定可信代理來源時允許所有 IPv4；有可信代理時限 private 網段加列出的代理網段。原生／分機 JVB 的 UDP 規則在 `lan-only`／`nat-entry`／`dual-homed-entry` 限 private 網段，`routed` 則允許所有 IPv4。<strong>第 6 節共用單機的 `lan-only` 影音 UDP 不由這份入口 allowlist 新增限制</strong>，IT 仍須依計畫以既有主機／外圍政策限制來源。資料服務依角色規則限制來源；實際每台的完整埠與來源以其 JSON／腳本及容器網路設定為準，不把第 2.5 節所有埠一律打開。

<strong>先確認主控台救援，再套用。</strong>雖然一般 IPv4 已建立的 SSH 會保留，SSH 使用了受限制的非標準埠、IPv6 或與既有規則衝突時，仍可能斷線或無法重新登入；不要只靠目前這一條 SSH。保留機房螢幕鍵盤／虛擬機管理主控台，套用後先開第二條 SSH 測試再關原視窗。若被鎖在外面，從主控台請 IT 在 INPUT 最前面只重新放行<strong>管理電腦的實際來源 IP 與 SSH 埠</strong>；以下假設來源 `192.168.50.100`、埠 22，須換成現場值：

```bash
sudo iptables -I INPUT 1 -s 192.168.50.100/32 -p tcp --dport 22 -j ACCEPT
```

IPv6 SSH 需由 IT 用 `ip6tables` 放行對應 IPv6 來源；外圍防火牆也要允許同一管理來源。這是暫時救援規則，連回後由 IT 修正並保存正式政策；不要清空所有規則或改成全網開放。工具有持續套用服務，單靠重開機不保證恢復。

成功的最後關鍵行：

```text
本機部署步驟完成；請用 status 確認後續節點
Local deployment steps complete; use status to check remaining nodes
```

單機也顯示這句固定文字。若 SSH 掉線，重新登入 <strong>a1</strong>，先回原工作畫面：

```bash
tmux attach -t teamsync-install
```

部署若仍在跑就繼續等；不要另開第二個部署。若沒用 tmux，或原程序已結束，確認沒有部署仍在執行、修復原因後，在原台、原目錄重跑同一 `deploy --apply-firewall`，完成且健康的步驟會略過。若 `Docker 無法連線`，依第 12 節啟動；缺檔、簽章或架構不符，就搬完整同版 kit，不跳過驗證。

### 5.4 健康檢查

<strong>位置：a1，`/opt/teamsync`。</strong>`status` 看各服務；`doctor` 加查主機前置條件、時間、憑證並給修復建議。

```bash
cd /opt/teamsync
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

成功畫面關鍵行：

```text
叢集正常
Cluster healthy
a1 (192.168.50.11)：正常
a1 (192.168.50.11): healthy
```

若 `Cluster needs attention; use the fixes below`，依畫面點名的機器處理。「部署完成」不代表所有檢查通過，`healthy=false` 是不健康，不直接交付。

<strong>離線站通常會看到什麼？</strong>工具沒有「連不到公網就例行警告」這一項；內部 DNS、時間、憑證、主機與服務都正常時，離線站也應健康。常見需要處理的是：內部名稱無法解析、NTP 未同步、節點時間探針不可達、憑證快到期／已到期，以及磁碟、Docker 或服務異常。憑證距到期 60／30／7 天會提示；不要把時間同步失敗或 `healthy=false` 當作離線站可忽略的正常現象。`doctor` 也不代表外部推播／郵件／AI 已可用，仍須按 2.4 驗收所需服務。

### 5.5 信任憑證與第一次登入

<strong>位置：a1，`/opt/teamsync`，接著使用者電腦。</strong>模式 `1` 先讓 IT 取得<strong>公開 CA 根</strong>；加密媒體已掛載：

```bash
cd /opt/teamsync
sudo install -m 0644 ./cluster/ca.crt /media/transfer/teamsync-ca.crt
sudo openssl x509 -in ./cluster/ca.crt -noout -subject -enddate -fingerprint -sha256
```

成功在 <strong>a1 畫面</strong>列出憑證身分、到期日與 <strong>SHA-256 指紋</strong>。IT 直接從這個畫面讀出，或用另一可信管道交給同事；同事比對收到的憑證，不能只相信與檔案放在一起的指紋文字。只忽略顯示上的冒號、空格與大小寫，數字須完全一致。

每種裝置都按三步做；公司已用 GPO／Intune／MDM 統一派送時，由 IT 完成相同步驟與驗收。選單名稱會隨系統版本略有不同：

| 裝置 | 1. 核對來源與指紋 | 2. 安裝公開根 | 3. 驗收 |
|---|---|---|---|
| Windows 10／11 | 從 IT 取得 `teamsync-ca.crt`；依下方 `certutil` 算 SHA-256，與 a1 畫面逐字比對 | Win+R → `certmgr.msc` →「信任的根憑證授權單位」→「憑證」→右鍵「所有工作／匯入」，選此 CA。這是目前使用者；全機派送由 IT 用 `certlm.msc`／公司政策處理 | 重啟瀏覽器，用同一網站名稱登入；仍有警告就停下找 IT |
| macOS |「鑰匙圈存取」匯入 IT 的 CA 至「系統」後，開啟憑證詳細資料，比對 SHA-256 指紋，未核對前不設信任 | 核對相符後，雙擊該 CA →「信任」→「使用此憑證時：永遠信任」，依提示輸入管理員授權 | 重啟瀏覽器，用同一名稱登入、上傳下載 |
| iPhone／iPad | 從 IT 可信來源取得 CA 描述檔，檢視憑證詳細資料，與 a1 比對 SHA-256；若畫面無法顯示，請 IT 先完成核對與受管派送 |「設定／一般／VPN 與裝置管理」安裝描述檔；再到「一般／關於本機／憑證信任設定」開啟該根的完全信任 | Safari 用同一名稱登入；公司限制手動安裝時改由 MDM 派送 |
| Android | 取得 IT 的 CA，在憑證詳細資料比對 SHA-256；系統不顯示時請 IT 核對並受管派送 |「設定／安全性與隱私／更多安全性設定／加密與憑證／安裝憑證／CA 憑證」選檔，依裝置提示確認 | 瀏覽器用同一名稱登入；原生 App 可能不接受使用者 CA，須企業派送或改用模式 2 |
| Firefox（有自己的憑證庫時） | 先請 IT 用下方 `openssl` 或 Windows 命令核對收到的 CA，與 a1 讀出的 SHA-256 比對 |「設定／隱私權與安全性／憑證／檢視憑證」→「憑證機構／Authorities」匯入此 CA，勾選信任它識別網站；企業已派送信任政策則由 IT 確認 | 重啟 Firefox，以同一名稱登入，確認無憑證警告 |

Windows 可在放有 `teamsync-ca.crt` 的資料夾開 PowerShell，用系統 `certutil` 將 PEM 轉成 DER，再算<strong>憑證本身</strong>的 SHA-256；輸出的 `teamsync-ca.cer` 若已存在，先由 IT 查明，不覆蓋別人的檔：

```powershell
certutil -decode .\teamsync-ca.crt .\teamsync-ca.cer
certutil -hashfile .\teamsync-ca.cer SHA256
```

此值應與 a1 的 `openssl ... -fingerprint -sha256` 相同。直接對文字 `.crt` 算檔案雜湊會不同；Windows 憑證視窗常見的 SHA-1「指紋」也不是這裡要比的 SHA-256。其他桌面可請 IT 用 `openssl x509 -in teamsync-ca.crt -noout -fingerprint -sha256` 核對。

只傳公開 CA，不傳私鑰、`cluster/admin.json`、`cluster/secrets.json` 或加入檔。若瀏覽器仍說「連線不是私人連線」，查 DNS、名稱與裝置信任，不以略過警告驗收。

在 <strong>a1 私人主控台</strong>查看初始密碼，先關螢幕分享、錄製及終端機留存；不截圖或送支援。`less` 只看檔案，按 `q` 離開：

<strong>下列預設密碼檔的查看／刪除步驟，只適用沒有提供 `admin_password_file` 的單機安裝。</strong>若由 IT 自備密碼檔，工具不會建立 `.teamsync-deploy-state/admin-password`；請使用 IT 保管的原檔，並持續保留它供後續單機部署與升級讀取，不執行下列刪除步驟。

```bash
cd /opt/teamsync
sudo stat -c '%a %U:%G %n' /opt/teamsync/system/.teamsync-deploy-state/admin-password
```

權限應是 <strong>`600 root:root`</strong>（本例以 sudo 安裝）；若群組或其他人可讀，先請 IT 修正擁有者，並執行 `sudo chmod 600 /opt/teamsync/system/.teamsync-deploy-state/admin-password`，再查看內容。

```bash
sudo less /opt/teamsync/system/.teamsync-deploy-state/admin-password
```

<strong>接著在使用者電腦瀏覽器</strong>開 IT 的網站，例如佔位網址 `https://teamsync.example.com/static/web`。使用設定時選的管理員帳號（省略時為 `admin`）；自訂密碼用您選的密碼，自動產生的密碼依部署摘要指定的私人檔案讀取。多機站的初始密碼位置是 `cluster/admin-password`。若登入畫面需公司識別，使用安裝結果的本站資訊。管理員 email 與登入帳號分開。首次登入後換自己的密碼、安全保管並確認新密碼能登入，再回 <strong>a1</strong> 刪除初始密碼檔：

```bash
sudo rm -- /opt/teamsync/system/.teamsync-deploy-state/admin-password
```

重新部署不重設已有帳號；單機 `deploy` 的前置檢查仍要求有這個 0600 密碼檔。日後確實要重跑部署時，由 IT 在私人環境按支援流程重新提供目前管理員密碼，作業完成再刪。保留 `cluster/` 與復原金鑰，不為清掉初始密碼而刪除站點設定。

成功驗收：正常登入、測試聊天、上傳及下載一個不含機密的檔案，再完成第 9 節第一次備份。<strong>這種由 `teamsync-cluster` 建立的單機也用第 9 節的 `backup`／`restore`，不改跑舊的儲存卷備份。</strong> <strong>AI（人工智慧）</strong>對話另需適用模型服務與金鑰；離線站須用事先規劃的可達服務，安裝成功不代表已取得雲端 AI。設定參閱 `system/README.zh-TW.md`「離線環境的 AI 模型設定」。

## 6. 範例二：單機加會議錄影

這是<strong>另一個全新站點</strong>，不是對已安裝站點再次做 `new`。既有站加購先取得同版包與支援的啟用流程，不刪設定重建。

### 6.1 授權與容量

<strong>位置：下載電腦，`$HOME/teamsync-work`。</strong>先取含 `jitsi` 的金鑰。Jitsi 是會議服務，JVB 轉送影音，Jibri 錄影。第 3 節的 `fetch` 自動取該授權的加購包，不另外指定加購下載旗標。

成功多出 `downloads/teamsync-addon-jitsi-<版本>-amd64.tar.gz`，已合併解開在同一 `kit/`。若「授權未包含 jitsi」，取得新授權再做，不修改 `license.json` 開通。

完整 kit 依第 4 節搬到全新 a1，按 2.3 的會議門檻另留錄影空間。單機停機時網站、會議、錄影一起停；較多會議的公司可採第 8 節分機。

### 6.2 問答差異

<strong>位置：全新 a1，`/opt/teamsync`。</strong>

```bash
cd /opt/teamsync
sudo ./teamsync-cluster config
```

第 5 節改答：

| 題目 | 答案 | 效果 |
|---|---|---|
| 「要啟用哪些已授權的附加功能？」 | `jitsi` | 啟用會議授權 |
| 「這台機器要部署什麼？」 | `all-in-one` | 全同機，自動用 `single`，不另問方案 |
| 網路與 TLS | 內網用 `lan-only`、TLS `1`；要外部加入才用 `nat-entry` | 外部模式由 IT 提供固定外部 IPv4，轉送 TCP 443 與計畫 UDP 埠 |
| 「啟用自動錄影？Enter 預設開啟（手動錄影按鈕固定隱藏）」 | `on` 或 Enter | 自動錄影；不要錄才答 `off` |
| a1 IP、磁碟、管理員、確認、密語 | 按第 5 節 | 也會詢問兩個磁碟規劃路徑，單機儲存說明相同 |

成功同樣產生加入檔與部署提示。若「請只選畫面列出的已授權功能」，填實際列出的 `jitsi`，不填行銷名稱或未購功能。

### 6.3 安裝與錄影驗收

<strong>位置：a1，`/opt/teamsync`。</strong>

```bash
cd /opt/teamsync
sudo ./teamsync-cluster deploy --apply-firewall
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

應看到 `Cluster healthy`。完成 5.5 的信任與登入，從兩個裝置加入一場測試會議，驗雙向聲音影像；結束後等待錄影封存，在網站播放並拖曳。不能只看容器啟動就當錄影成功。

此單機建立<strong>一個同時錄影名額</strong>，手動按鈕固定隱藏，自動錄影依會議流程啟動。容量或名額不足就減少同時錄影場數或規劃分機。外部會議無影音，先請 IT 查計畫 UDP 與入口轉送，不開放所有資料埠。

## 7. Sandbox 與 Edge Workers

<strong>Sandbox</strong> 是隔離執行程式工作的功能；<strong>Edge Workers</strong> 執行站點模組程式，名稱不代表必須使用外部雲端。只用授權列出的功能與同版本功能包。

### 7.1 全新單機

<strong>位置：全新 a1，`/opt/teamsync`。</strong>先按第 5 節只部署 `teamsync-base`，再依下列位置使用授權的 standalone setup（單機啟用腳本）。加購包須和主包放在同一個 kit 根目錄；下載到檔案還不算啟用。若 cluster `config` 拒絕某項功能，按畫面指引與隨包文件處理，不修改設定繞過檢查。

Sandbox 的單機位置是 a1 以外的<strong>專用主機</strong>；Edge Workers 的單機位置是 a1。只有完整授權 add-on、同版 kit、Infisical KMS（密鑰服務初始化）與 Docker 都準備好才操作。把完整同版 kit 放到該專用主機的 `/opt/teamsync`，在<strong>專用 Sandbox 主機</strong>先做唯讀檢查，再由管理員套用：

```bash
cd /opt/teamsync
sudo ./scripts/sandbox/sandbox-doctor.sh
sudo ./scripts/setup-sandbox-onprem.sh --apply
sudo ./scripts/sandbox/sandbox-doctor.sh
```

完成 Sandbox 後回到<strong>a1</strong>，Edge Workers 使用同樣的唯讀／套用順序：

```bash
cd /opt/teamsync
sudo ./scripts/setup-edge-workers-onprem.sh --doctor
sudo ./scripts/setup-edge-workers-onprem.sh --apply
sudo ./scripts/setup-edge-workers-onprem.sh --doctor
```

成功要看到各自 doctor 的健康結果，再驗收實際工作／模組；下載到 add-on tarball 不等於功能已啟用。若畫面說缺少 adapter、license 或 add-on tarball，保留原訊息，找支援補齊同版授權與 kit，不修改 `cluster.json`。

### 7.2 多機與備援規劃

<strong>HA（高可用）</strong>表示同層有不同機器接手，仍需足夠健康副本，不代表不中斷。多機加購先請 TeamSync 支援確認交付包可用的部署方式、各台角色與復原計畫，再按隨包文件操作；不要把單機腳本直接當成整站 HA 安裝器。

先依 2.3 計算最忙時的 Sandbox 工作數、同時建置數、Edge 模組數與流量，再另留故障備援。Sandbox 使用專用主機，不與資料節點同機；封閉機房的工作不開 Internet 出口，變更出口或隔離方式先由 IT 核准。

若「授權未包含 sandbox」或「授權未包含 edge-workers」，取得新授權並下載同版完整包；若缺少啟用介面，保留拒絕訊息交支援，不自行宣告已支援。細節查 kit 內的 `system/README.zh-TW.md` 相應章節。

## 8. 範例三：多機站與增減機器

### 8.1 架構 A–D 與角色

<strong>A–D 是本頁閱讀標籤，不是 CLI 選項</strong>；CLI 是「用文字命令操作的介面」。真正精靈值在方案欄，勿把架構 D 與 `data` 的簡稱 D 混淆。

| 架構 | 方案 | 每台工作 | 適用與限制 |
|---|---|---|---|
| A：主程式單機 | `single` | a1=`entry,app,data,storage` | 第 5 節，機器壞則停站 |
| B：含會議全同機 | `single` | a1=`all-in-one` | 第 6 節，一個同時錄影名額，故障全停 |
| C：分機 | `A+B`；更細分 `A+B+C`／`A+B+V+C` | a1 主程式；雙機 node2=`meeting,media,recorder`；四機再分 node2=`meeting`、node3=`media`、node4=`recorder` | 分散工作，單台層仍無備援 |
| D：各層副本 | `full-ha` | 入口、應用、DATA、storage；選會議再加組與錄影 | 較多機器、需接手與容量，仍安排維護停機 |

其他精靈值 `A+E+B`、`A+E+B+V+C` 為應用分離方案；`storage-ha` <strong>只有儲存群，不是完整網站</strong>。首次部署依本頁範例擇一，不自行混搭。

本例 C：a1 `192.168.50.11` 主程式，node2 `192.168.50.12` 會議／影音／錄影，各在 `/opt/teamsync`；另有異機備份空間。授權含 jitsi，網站僅 a1 作入口。

### 8.2 雙機逐步安裝

<strong>第一步，a1 `/opt/teamsync`：</strong>選 `new`、加購 `jitsi`、角色 `entry,app,data,storage`、方案 `A+B`，其餘依第 5–6 節，逐台填 a1 與 node2 固定 IP：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster config
sudo ./teamsync-cluster deploy --apply-firewall
sudo cp -p -- ./teamsync.join ./teamsync.join.before-a1-export
sudo chmod 600 ./teamsync.join.before-a1-export
sudo ./teamsync-cluster join --source ./teamsync.join --export ./teamsync.join
```

先保存原加入檔，再執行末行；末行隱藏問原管理密語，將應用建立的配對更新至交接檔，才交給 node2。<strong>`--export ./teamsync.join` 會更新同一檔案，不要讓它覆寫唯一副本。</strong>本例備份名稱每次要換未使用的新名稱；確認更新成功後，將最新管理副本安全另存，舊檔只作故障查核，不再拿舊世代加入新機。不要省略更新加入檔。

<strong>第二步，a1 `/opt/teamsync` 傳給 node2：</strong>IT 已驗證 SSH 身分、兩台有同版 kit。先傳一般管理員家目錄，避免寫 `/opt` 無權限：

```bash
sudo scp ./teamsync.join operator@192.168.50.12:~/teamsync.join
```

成功顯示傳輸完成。若 `Permission denied (publickey)`，請 IT 修正 <strong>sudo 所用身分</strong>的金鑰與已驗證 host key，或改核准的加密媒體，不關閉身分檢查。

<strong>第三步，node2 家目錄再進 `/opt/teamsync`：</strong>

```bash
sudo install -m 0600 "$HOME/teamsync.join" /opt/teamsync/teamsync.join
cd /opt/teamsync
sudo ./teamsync-cluster config --join ./teamsync.join --node node2
sudo ./teamsync-cluster deploy --apply-firewall
sudo cp -p -- ./teamsync.join ./teamsync.join.before-node2-export
sudo chmod 600 ./teamsync.join.before-node2-export
sudo ./teamsync-cluster join --source ./teamsync.join --export ./teamsync.join
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

輸入原管理密語，成功有 `Node node2 configured; run sudo ./teamsync-cluster deploy`。問「刪除此機已匯入的加密加入檔？」時，本例答 `no`，稍後仍要更新交接。

<strong>第四步，node2 `/opt/teamsync` 把最新交接送回 a1：</strong>

```bash
sudo scp ./teamsync.join operator@192.168.50.11:~/teamsync.join.from-node2
```

<strong>換回 a1 家目錄</strong>，保存最新管理副本，再檢查：

```bash
sudo cp -p -- /opt/teamsync/teamsync.join /opt/teamsync/teamsync.join.before-node2-return
sudo chmod 600 /opt/teamsync/teamsync.join.before-node2-return
sudo install -m 0600 "$HOME/teamsync.join.from-node2" /opt/teamsync/teamsync.join
cd /opt/teamsync
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

若四機拆出 node3 影音與 node4 錄影，先把 node2 最新交接傳給各台，再用自己的 `--node node3`／`--node node4` 加入與部署，不拿最初未配對的檔。成功還需實際登入、聊天、檔案、兩裝置會議與錄影播放。會議機沒有完整 DATA 監測密鑰，<strong>全群 DATA 檢查回 a1</strong>，不把資料庫密鑰複製給會議機。

第 8.4、8.6 節凡更新同一加入檔，也先按這個方式另存 0600 副本，名稱不可與既有備份相同。原生 HA 第一台 app 的初始密碼在 `/opt/teamsync/cluster/admin-password`；按 5.5 先用 `sudo stat -c '%a %U:%G %n' /opt/teamsync/cluster/admin-password` 核對 0600／擁有者，私人查看、登入改密碼並驗證後，用 `sudo rm -- /opt/teamsync/cluster/admin-password` 刪除。

若 `Deploy a1, refresh join --export, then join this E`，表示交接太早；回已完成的上游更新再傳，不每台各做 `new`。

### 8.3 完整 HA 逐題規劃

<strong>位置：全新管理 a1，`/opt/teamsync`。</strong>執行 `sudo ./teamsync-cluster config`，初始角色 `entry,app`、方案 `full-ha`，按需要選授權功能。追加題：

| 問題 | 本例規劃答案 | 用途 |
|---|---|---|
| 「尖峰同時幾場會議？」 | `2`，有 jitsi 才問 | 最忙時場數 |
| 「每場最多幾人？」 | `25` | 影音估算，不是效能保證 |
| 「入口 nginx（G）要幾台？」 | `2` | 網站入口 |
| 「應用節點（E）要幾台？」 | `2` | API 與工作 |
| 「資料節點（D）要幾台？3 / 5 / 7」 | `3` | 多數決避免雙主，不能選 2 |
| 「物件儲存（Silo，相容 MinIO）要幾台？」 | `4` | 四台儲存 |
| 「每台 Silo 要幾顆磁碟？」 | `2` | 數量相同的獨立掛載磁碟 |
| 「每顆磁碟預計容量（GiB）？」 | `500`，依 IT 實際規格 | 只估算，不格式化 |
| 「會議組要幾組？」 | `2`，有 jitsi 才問 | HA 至少兩組 |
| 「每個會議組要幾台影音伺服器（JVB）？0＝和會議主機裝在同一台」 | 小站 `0` | 與會議同機 |
| 「每個會議組要幾台錄影機？」 | 每組 `1`，依同時錄影量調整 | 每台一場，不保證組故障後仍錄滿尖峰 |
| 「小站要合併角色、節省主機嗎？yes / no」 | `yes` | 入口＋應用、DATA＋部分儲存合併；副本仍在不同機器 |

本例產生 a1/a2（入口＋應用）、d1–d3（資料＋儲存）、s4（第四台儲存）、b1/b2（各自會議組含影音／錄影），共 8 台。<strong>照畫面實際節點名稱</strong>，不要把 s4 自改 d4。沒選 jitsi 就不問會議、不建 b1/b2。每台仍須填固定 IP、儲存機的已掛載路徑，最後管理員、確認與密語同第 5 節。

入口至少兩台的選擇：

| 值 | IT 必須完成 |
|---|---|
| `vrrp` | 同一第二層網路（可直接交接位址），保留未占用 VIP，允許 VRRP／GARP 接手訊號並能隔離失控舊入口，不是所有虛擬機都適用 |
| `external-lb` | 既有公司流量分配設備，填 IP／DNS、可信來源 IP 範圍，影音按計畫轉送 |

VRRP 虛擬機入口另需暫停時仍前進的 PTP 時鐘及硬體 watchdog（讓失控舊入口停下的監督裝置）；KVM 檢查 `ptp_kvm`，其他平台由 IT 備妥。條件不足就拒絕，不用假設定略過，改既有 `external-lb` 或重新規劃。

### 8.4 HA 逐機順序

每台先放同版完整 kit。a1 建計畫後，照 8.2 傳加入檔，<strong>每台 `/opt/teamsync`</strong>用自己的 `config --join ./teamsync.join --node 該台名稱` 加入。

1. 在 d1/d2/d3 各自終端機同時啟動 `sudo ./teamsync-cluster deploy --apply-firewall`，讓 DATA 形成多數；s4 也部署儲存。先起的一台若等待逾時，其他台就緒後原命令重跑。
2. a1 `/opt/teamsync` 執行 `deploy --apply-firewall`；完成後 `join --source ./teamsync.join --export ./teamsync.join`，最新檔交 a2。
3. a2 用最新檔加入與部署；b1/b2 依計畫部署，各會議組的新交接給同組獨立影音／錄影機。沒有獨立下游則省略。
4. Edge、Sandbox 的前置服務健康後部署。回 a1 做全群檢查，各台做本機 `doctor`，再驗收產品。

<strong>quorum</strong> 是多數決所需的健康副本數。不足應停止寫入，不能強建另一群。「可服務但不健康」仍是降級，不接著維護下一台。

### 8.5 全站自動部署

全站自動部署由<strong>第一台 a1 `/opt/teamsync`</strong> 執行：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster site deploy --access-file /root/site-access.json --apply-firewall
```

一次問答後自動加入、部署及更新交接。每台仍須<strong>預放完整同版、符合本機架構 kit</strong>、固定 IP、已掛載磁碟、SSH 金鑰及已核對 host key；它不遠端下載 kit。

同一次問答也會詢問 5.2 的公司名稱、管理員帳號、電子郵件及隱藏密碼；多機的 `company_name` 預設為叢集名稱，自訂值會套用於第一間公司。無互動時在同一份設定檔使用上述四個 `services.all-in-one` 欄位，只需在規劃機提供密碼檔，加入檔會加密交接所需密鑰。

`/root/site-access.json` 是 IT 建立、權限 `0600` 的管理連線表，不含登入密碼。例如一台遠端機器：

```json
{
  "a2": {
    "user": "operator",
    "kit": "/opt/teamsync",
    "port": 22,
    "identity_file": "/root/.ssh/site-ops",
    "sudo": true
  }
}
```

每台遠端都要列，名稱與計畫相同。`identity_file` 是 <strong>a1 上</strong>的 SSH 私鑰，`sudo: true` 會執行 `sudo -n`，須 IT 允許該受控帳號免密碼執行必要管理命令。<strong>免密碼 sudo 表示拿到該帳號／金鑰的人可取得所授予的系統管理權；若是 `NOPASSWD: ALL`，等同可接管整台。</strong>請用專用維運帳號、限制 SSH 來源為管理節點、保護私鑰並記錄用途；sudo 權限與有效時間由 IT 依實際子命令審核，不把全體員工加入免密碼管理。只為部署臨時開放的權限完成後移除；若每日多機備份仍需要，保留經核准的最小維運權限，不能撤掉後卻期待排程繼續成功。無法提供這些條件就用逐機流程。

不能只靠暫時 SSH agent、不停用 host key 驗證。此格式同樣供已發布版多機備份、憑證、節點變更使用。

成功有 `Site complete:`、健康台數、join 世代。中斷後在 <strong>a1 `/opt/teamsync`</strong>重跑原命令，也可：

```bash
sudo ./teamsync-cluster site deploy --access-file /root/site-access.json --apply-firewall --resume
```

保留原 kit、計畫、密語、`cluster/state/site-deploy.json`，不刪記錄重建身分。詳 kit 附帶的 `system/CLUSTER-SITE.md`。

### 8.6 增加／移除機器

`node add/remove` <strong>只限 full-ha 管理 app 節點</strong>，不是單機變 HA 的入口。可新增獨立 app、media（JVB）或完整 Silo <strong>pool（一次完整增加的儲存組）</strong>；可移除排空後的獨立 app／JVB。DATA 3/5/7 成員、共用角色機器與原有儲存組不可任意增減。

<strong>位置：管理 a1，`/opt/teamsync`。</strong>IT 備妥新機相同 kit 與固定 IP，從現行 `cluster/cluster.json` 複製出 `/root/site-desired.json`，只改允許的新增／移除項，保留站點身分、版號、舊機 IP、角色與磁碟，更新連線表；移除過程舊機仍需可達。先預覽：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster node add --config /root/site-desired.json --source ./teamsync.join \
  --export ./teamsync.join --access-file /root/site-access.json --dry-run
```

預覽列 `added`、`removed`、`generation`（計畫版本序號）及新影音路由，確認後在 <strong>同台同目錄</strong>：

```bash
sudo ./teamsync-cluster node add --config /root/site-desired.json --source ./teamsync.join \
  --export ./teamsync.join --access-file /root/site-access.json
```

輸入原交接密語，成功收據含 `"complete": true`。新增 JVB 先讓 IT 放行分配的新入口 UDP；Silo 必須符合完整 pool，不只塞進一台。

移除用<strong>另一份已核對的縮減計畫</strong>，仍在 <strong>a1 `/opt/teamsync`</strong>：

```bash
sudo ./teamsync-cluster node remove --config /root/site-desired.json --source ./teamsync.join \
  --export ./teamsync.join --access-file /root/site-access.json --dry-run
sudo ./teamsync-cluster node remove --config /root/site-desired.json --source ./teamsync.join \
  --export ./teamsync.join --access-file /root/site-access.json
```

先排空會議／連線才停服務。若 `JVB still has conferences and was retained; resume after they finish`，等會議結束後<strong>原命令加 `--resume`</strong>，不先關機。完成保存最新加入檔、檢查健康，再讓 IT 退役機器。

## 客戶自有雲端 VM 安裝

這一章說明把 TeamSync 安裝在<strong>客戶自己的 AWS、Google Cloud 或 Azure 帳號</strong>裡的虛擬機（VM）。它使用與機房相同的正式交付 kit、`teamsync-cluster` 安裝器與備份／升級命令；資料庫、向量搜尋、佇列、Silo 物件儲存仍在客戶管理的 VM 上，不改成雲端託管資料庫或託管物件儲存。雲端只提供網路、VM、區域、磁碟、負載平衡與備份位置。

<strong>雲端的核心規則：</strong>所有 TeamSync VM 放在同一個 region（區域）內的私有 VPC／VNet（雲端私有網路），每台使用 IT／雲端管理員配置的固定 private IP（私有 IP），不配置 public IP。唯一可有公開位址的是雲端負載平衡器（LB，替多台入口分配流量的設備）。管理員透過 Session Manager、IAP 或 Bastion 進入 VM；不為方便而開放公網 SSH。安裝器不呼叫 AWS API、雲端 metadata，也不會替您建立網路或 IP。

### 雲端應有的樣子

下圖上半部是<strong>最完整的高可用</strong>（`teamsync-base` 加全部 add-on，每一層標出來自哪個套件）；下方<strong>紫色虛線框是單機版</strong>：a1 一台以 `all-in-one` 執行 `teamsync-base` 的全部服務，會議與 Sandbox 各一台，Edge 加在 a1。

![TeamSync 雲端部署架構：上半部為最完整高可用（teamsync-base 與全部 add-on），紫色虛線框為單機版](https://bucket.scfg.io/teamsync-cluster/2026-10-28/cloud-architecture-v2.png)

看不到圖片（例如離線機房）時，用下面兩張文字圖，內容相同。

下面是<strong>完整 full-ha</strong>的示意；單機只保留 a1（以及授權的 b1／專用 add-on 主機），不需要建立 D 多數決或三個 AZ。

```text
使用者／會議訪客
       │ 公開 DNS（網址）
       ▼
雲端負載平衡器：TCP 443；每個 JVB 一個 UDP 10000+i
       │ 只轉到入口 VM 的 private IP
       ▼
VPC／VNet 私有子網（每台 VM 固定 private IP、沒有 public IP）
  G 入口：nginx（至少兩台 HA）
  E 應用：API、worker、身分／密鑰服務
  D 資料：MySQL、Postgres、Redis、Qdrant、訊息／佇列
  S 儲存：Silo 與錄影／檔案
  Jitsi、Edge、Sandbox：依授權放在專用 VM

資料節點 D1／D2／D3 分在同一 region 的三個 AZ，彼此 private RTT（網路來回延遲）≤ 2 ms。
```

單機版（同一個 VPC／VNet，前面同樣放負載平衡器，或以安全群組只開 443／UDP）：

```text
雲端負載平衡器（或安全群組只開 TCP 443、UDP 10000）
       │
       ▼
a1  teamsync-base（all-in-one，一台）
    nginx · API · worker · MySQL · Redis · Qdrant · Silo
    Mosquitto（MQTT）· ElasticMQ（佇列）· Infisical＋Postgres（密鑰）
    ＋ Edge（teamsync-addon-edge-workers）可加在這台
       │ /jitsi/ 與影音               │ 指派 Sandbox 工作
       ▼                              ▼
b1  teamsync-addon-jitsi          Sandbox 主機  teamsync-addon-sandbox
    信令 · JVB · 錄影 jibri           專用一台，不與 a1 同機
    （小站也可與 a1 同機）

每種服務各一份；a1 故障時服務停止，以備份還原。
```

雲端 LB 必須同時支援 TCP 443 與計畫列出的 UDP 媒體埠；JVB 的埠以安裝器印出的計畫為準，不能自行把所有 UDP 埠開給 Internet。資料庫、Silo、broker（訊息服務）、Docker 管理埠與 SSH 只接受計畫中的 private peers，規則細節沿用第 2.5 節的角色 allowlist（允許清單）。

### 先準備帳號、網路與 VM

1. 選一個 region，建立私有 VPC／VNet 與 private subnet。<strong>單機</strong>可放在一個 AZ、使用一台 VM 的雲端區塊碟與 Docker 持久卷；<strong>full-ha</strong> 才需要至少三個 AZ 的 private subnet，並把 D 資料節點分散到三個 AZ。給每台 VM 一個永久名稱、固定 private IP、角色、AZ、磁碟與管理通道；不要依賴 DHCP，也不要讓資料節點跨 region。
2. 建立雲端 LB。對外站點讓 DNS 指向 LB；只給公司 VPN／專線使用時，使用內部 LB。LB 的 target／backend 只填入口 VM 的 private IP。安全群組／防火牆讓 LB 進入入口的 TCP 443，以及按計畫轉送的 UDP 10000+i；其他服務只允許 VPC／VNet private 流量。
3. 每台 VM 使用 Ubuntu 24.04、目標原生架構（amd64 或 arm64）、Python 3.10 以上、Docker 25 以上與 cgroup v2。full-ha 的原生 D／Silo 主機要先掛載每顆獨立資料碟且各台磁碟數相同；單機依 2.3 使用 VM 區塊碟與 Docker 持久卷。安裝器只檢查，不格式化。
4. 只開啟一種管理通道：AWS Systems Manager Session Manager、Google Cloud IAP TCP forwarding 或 Azure Bastion。若管理通道還沒通，先修復它；不要改成把 `22/tcp` 開到 `0.0.0.0/0`。

雲端服務名稱可以這樣對照：

| 用途 | AWS | Google Cloud | Azure |
|---|---|---|---|
| 私有網路 | VPC、private subnet | VPC、subnet | VNet、subnet |
| TCP／UDP 負載平衡 | Network Load Balancer | External passthrough Network Load Balancer | Azure Load Balancer（Standard） |
| 防火牆 | Security Group | VPC firewall rules | Network Security Group（NSG） |
| DNS | Route 53 | Cloud DNS | Azure DNS |
| 雲端時間來源 | Amazon Time Sync `169.254.169.123` | `metadata.google.internal` | 主機時間來源（PTP） |
| 管理通道 | Systems Manager Session Manager | IAP TCP forwarding | Azure Bastion |
| SSD 區塊儲存 | EBS gp3 | Persistent Disk SSD／Hyperdisk | Premium SSD v2 |
| 異地備份位置 | 另一 region 的 S3 | 另一 region 的 Cloud Storage | 另一 region 的 Blob Storage |

### 用什麼 VM 規格

以下是與第 2.3 節容量規劃對齊的<strong>等級範例</strong>，不是雲端供應商的效能保證。可換成同一架構、同一 vCPU／RAM 等級的較新型號；正式環境使用隨需或預留 VM，<strong>不要使用 Spot／preemptible（可被回收）VM</strong>。

| 需求 | 用途 | AWS | Google Cloud | Azure |
|---|---|---|---|---|
| 8 vCPU／16 GB | JVB、錄影機 | `c6i.2xlarge` | `n2-custom-8-16384` | `F8s v2` |
| 8 vCPU／32 GB | 單機 TeamSync、≤300 人的應用 | `m6i.2xlarge` | `n2-standard-8` | `D8s v5` |
| 16 vCPU／32 GB | 單機視訊會議 | `c6i.4xlarge` | `n2-custom-16-32768` | `F16s v2` |
| 16 vCPU／64 GB | ≤300 人資料節點、≤1,000 人應用 | `m6i.4xlarge` | `n2-standard-16` | `D16s v5` |
| 32 vCPU／128 GB | ≥1,000 人資料節點 | `m6i.8xlarge` | `n2-standard-32` | `D32s v5` |

ARM VM 可以使用同規格替代品，但整個站與所有 Sandbox runtime 的 CPU 架構要一致。跨 AZ 會有額外流量費用；資料節點的同步延遲仍必須 ≤2 ms，不能為了省費用把 D 節點跨 region。

### 先驗證時間與私有網路

在<strong>每台 VM</strong>透過核准的管理通道執行：

```bash
hostname
ip -br addr
timedatectl show --property=NTPSynchronized --value
chronyc tracking
```

預期 `timedatectl` 印出 `yes`；`chronyc tracking` 應有 `Reference ID`、有效 `Stratum`，且 `System time` 的偏差小於 1 秒。`ip -br addr` 會列出 loopback、Docker bridge、可能的 link-local 介面；要核對的是雲端主要 NIC 沒有 public IP，且 TeamSync 計畫使用的 private IP 出現在正確介面。時間未同步時先修 cloud image／chrony 指向上表的雲端時間服務，再重跑；不要用手動校時或偽造 `yes` 繞過部署。

在每個 D 節點互測其他 D 節點的 private IP：

```bash
ping -c 5 -i 0.2 10.20.10.12
```

把位址換成現場的 D2／D3 private IP；輸出的 `rtt min/avg/max` 中 `avg` 應不超過 <strong>2 ms</strong>。若 `Destination Host Unreachable`，先查 AZ 路由、private subnet、security group／firewall 與固定 IP，再重跑 `config`；不要在 TeamSync 設定裡填 public IP。

### 在 VPC／VNet 外下載，再搬入 VM

下載電腦仍依第 3 節使用授權金鑰，由授權頻道決定下載版本：

```bash
cd "$HOME/teamsync-work"
. ./.venv/bin/activate
teamsync-cluster fetch --dest ./teamsync-download --arch amd64
```

若目標 VM 是 arm64，將 `--arch amd64` 改成 `--arch arm64`。下載電腦通常看不到 VPC／VNet 的 private IP；先用公司核准的加密傳輸方式，把完整 `teamsync-download/kit/` 暫存到核准的管理跳板機／傳輸服務，再從該跳板機放到<strong>每台</strong> VM 的 `/opt/teamsync`。不要只傳 `teamsync-cluster`，也不要在 VM 內用 `pip` 再兌換一次。以下命令在已完成暫存的管理跳板機執行，<strong>僅適用全新、未安裝的 `/opt/teamsync`</strong>，並依第 4.2 節設為 root 擁有；替換 private IP 與使用者：

```bash
sudo scp -rp ./teamsync-download/kit operator@10.20.10.11:/tmp/teamsync-kit
ssh operator@10.20.10.11 'sudo install -d -m 0755 /opt/teamsync && sudo cp -a /tmp/teamsync-kit/. /opt/teamsync/ && sudo chown -R root:root /opt/teamsync && sudo chmod 0755 /opt/teamsync'
```

預期每台 `/opt/teamsync` 都有相同版本的 `teamsync-cluster`、`components/base.json`、`license.json` 與授權的 add-on 檔。若供應商的 Session Manager／IAP 不提供 `scp`，用同一條核准的檔案傳輸通道；不要為了複製 kit 開公網 SSH。

### 設定問答：雲端要回答什麼

在第一台 a1 開始：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster config
```

1. <strong>單機</strong>選 `single`；完整 HA 選 `full-ha`。full-ha 的最低規劃是 G／`entry` 至少 2 台、E／`app` 至少 2 台、D／`data` 選 3、5 或 7 台的奇數；S／`storage` 使用規劃器（planner）產生的有效節點與等數量獨立磁碟（至少 3 台，PDF 標準配置常用 4 台）。選 `jitsi` 時 meeting group 至少 2 組。D 節點分三個 AZ；單機不需要為了 full-ha 的多數決建立三個 AZ。
2. 網路題的原文是「<strong>客戶網路類型：`nat-entry` / `dual-homed-entry` / `lan-only` / `routed`</strong>」。普通 standalone／split adapter 只支援 `nat-entry` 與 `lan-only`：
   - Internet 使用者經雲端 LB 進入：選 <strong>`nat-entry`</strong>，在「影音外部固定 IPv4」填 LB 的固定 public IPv4（必須是數字 IP，不是 DNS）。
   - 只讓 VPN／專線內部使用：選 <strong>`lan-only`</strong>，不填外部影音位址，網站 DNS 指向內部 LB。
   - 不要把雲端 VPC 誤當 `dual-homed-entry` 或 `routed`；這兩種是原生角色方案，普通單機／分機組合不支援。
3. 多入口或即使只有一台入口但前面使用雲端 LB，入口前端題原文是「<strong>入口前端：`vrrp` / `external-lb` / `single`</strong>」，選 <strong>`external-lb`</strong>。雲端跨 AZ 沒有可讓 keepalived 交接的同一個 L2 VIP，不能選 `vrrp`。單入口沒有 LB 的純內網測試才選 `single`。
4. 接著回答「<strong>客戶既有 LB 的 IP 或 DNS</strong>」：填 LB 的 private IP 或可由每台 VM 解析的內部 DNS 名稱；網站題填員工使用的 DNS 名稱。下一題「<strong>LB 的來源 IP/CIDR（逗號分隔，可留空）</strong>」只填實際 LB／proxy 的來源網段，不能填 `0.0.0.0/0`；這些值會決定可信任的 `X-Forwarded-For`。
5. 每台節點題都填雲端管理員事先分配的固定 private IP、永久節點名稱、AZ／failure domain。full-ha 的 D／Silo 節點再填已掛載的獨立資料碟路徑；單機使用 VM 區塊碟與 Docker 持久卷，不要為問答中的規劃路徑假造第二顆磁碟。資料碟路徑必須先存在；安裝器不會建立雲端磁碟，也不會格式化。

若畫面顯示「<strong>雙網卡 HA 入口使用客戶 LB；LAN VIP 無法接手另一台的 DMZ IP。 / Dual-homed HA entry uses your LB; a LAN VIP cannot take over another host's DMZ address.</strong>」，接受它並選 `external-lb`。若畫面問 PTP／watchdog，代表您選了 `vrrp`；在雲端改回 `external-lb`，不以假裝置略過。

### 部署與驗收

單機（含單機會議）在 a1：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster site deploy --apply-firewall
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

多機 HA 在 a1：每台遠端 VM 先放同版同架構 kit，建立 `/root/site-access.json`（權限 `0600`，格式見第 8.5 節），確認 host key，再執行：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster site deploy --access-file /root/site-access.json --apply-firewall
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

若 IT／雲端管理員要先審核規則，先省略 `--apply-firewall`，閱讀工具產生的 allowlist 後由核准流程套用。成功畫面包含類似：

```text
全站完成：8 台健康，沿用 0 步，join 世代 1 / Site complete: 8 healthy hosts, 0 saved steps reused, join generation 1
Cluster healthy
```

`8` 與世代數字會依計畫改變。驗收不只看容器：用公司 DNS 登入、測試聊天、上傳下載檔案、兩台裝置加入會議、播放錄影，再從 a1／D 節點執行 `status`／`doctor`。Meeting VM 沒有完整 DATA monitoring key，不要把資料庫密鑰複製過去。

### 雲端備份、升級與回復

先在另一個 region 準備客戶帳號持有、加密且可還原的備份位置。TeamSync `backup` 命令實際支援的是 VM 上的掛載目錄或核准的 SSH target；它不直接呼叫 S3、Cloud Storage 或 Blob API。若要使用雲端物件儲存，請由 IT／雲端管理員把受控備份空間掛載或以核准流程複製到異地，再讓 TeamSync 寫入；這個差異要記在復原演練裡。

在 a1 先確認備份磁碟真的掛載，再做完整組：

```bash
cd /opt/teamsync
findmnt --mountpoint /mnt/site-backup
sudo ./teamsync-cluster backup --target /mnt/site-backup/first
```

預期 `findmnt` 顯示雲端區塊碟的 mount；備份完成會有 `COMPLETE`、`manifest.json` 與 `recovery.json`。不要把備份目標放 kit、Docker 資料碟或同一個故障域；第 9 節的異地／SSH 流程與密語保存規則仍適用。

<strong>單機升級：</strong>依第 11.2 節用新 kit 外層的 `upgrade.sh`，指向現場的舊 `system/` 目錄：

```bash
cd /opt/teamsync
sudo /opt/teamsync-next/upgrade.sh --install-dir /opt/teamsync/system
```

先完成異機完整備份；這會停寫、重建容器並停站，沒有零停機承諾。單機使用 `docker-compose-dist.yaml` 的既有 Silo，不要把 cluster-only 的資料映像 lock 手動套進去。

<strong>多機升級：</strong>先依 11.3–11.4 確認相同拓樸與資料／儲存映像相容，使用維護時段的 cluster `upgrade`，先預檢再套用。此命令會封鎖寫入、停止派工、完成備份並逐服務逐機更新，<strong>零停機不提供</strong>：

```bash
cd /opt/teamsync
sudo /opt/teamsync-next/teamsync-cluster upgrade \
  --state-dir /opt/teamsync/cluster --kit /opt/teamsync-next \
  --dry-run --access-file /root/site-access.json

sudo /opt/teamsync-next/teamsync-cluster upgrade \
  --state-dir /opt/teamsync/cluster --kit /opt/teamsync-next \
  --backup-target /mnt/site-backup/before-upgrade --maintenance \
  --access-file /root/site-access.json
```

舊站另核對文末的「特定舊版升級注意事項」。預檢拒絕時先保留原 kit、完整備份與訊息，由支援確認轉換方式，不修改驗證資料繞過。

### 雲端常見拒絕與修法

| 實際訊息 | 修法 |
|---|---|
| `external-lb 需要入口與 LB 位址 / external-lb needs entry hosts and an LB address` | 回到問答確認至少一台節點有 `entry` 角色；填能由 VM 解析的 LB IP／DNS，檢查 LB target 是否指向 private IP。 |
| `影音位址不能使用 DNS，請輸入 IPv4。 / Media address must be a literal IPv4, not DNS.` | `nat-entry` 的影音欄填 LB 固定 public IPv4；網站名稱仍可填 DNS。沒有固定 UDP 位址就先請雲端管理員建立支援的 LB。 |
| `Peer ... is unreachable; power it on and fix its static IP and LAN/VLAN, then rerun deploy` | 用 `ip -br addr` 核對 private IP，檢查三個 AZ 的路由與安全群組；不要改成 public IP。 |
| `Insufficient RAM; fix the allocation, then rerun deploy` | 依第 2.3 節或本章 VM 表調大該角色；重新確認 cgroup limit，再重跑原 `deploy`。 |
| `cgroup is too old; enable cgroup v2, reboot, then rerun deploy` | 使用 Ubuntu 24.04 的 cgroup v2 映像，按雲端維護流程重開後確認 `/sys/fs/cgroup/cgroup.controllers` 存在。 |
| `Docker is too old; ask IT to upgrade Docker to 25 or later with its matching CLI` | 在 VM 映像升級 Docker engine 與 CLI 至 25 以上；不要讓安裝器連 Internet 拉映像，kit 內的映像才是來源。 |
| `changes a datastore image without proven identical engine/on-disk format` | 資料映像尚未證明引擎與磁碟格式相同；保留資料與備份，找支援確認遷移或復原計畫。 |

雲端交付目前沒有 EC2 secondary-IP／IAM 的客戶專用步驟，也沒有雲端 metadata 自動發現；不要從這份指南自行發明。TURN／TCP fallback、不能轉 UDP 的 LB、跨 region 的資料節點與 Spot／preemptible production 也不在本頁的支援路徑內。

## 9. 每日檢查、備份與還原

<strong>先辨別安裝入口：</strong>本頁第 5–8 節由 `teamsync-cluster config/deploy` 建立的站，<strong>包含一台 a1 的 `single`、單機會議、分機與 HA</strong>，都使用本節的 `./teamsync-cluster backup`／`restore`。單機資料雖放在 Docker 儲存卷，備份器仍會辨識並匯出其資料與設定；還原也有對應單機流程。工具會移除舊式備份 cron，首次完整備份後才建立本節的 timer。

若您是先前只用外層 `install.sh` 安裝、沒有 `cluster/cluster.json`／`cluster/node.json` 的舊站，請改依 <strong>`system/RECOVERY.md`</strong> 的 `scripts/backup.sh`／`scripts/restore.sh` 及異機保存流程，先請支援確認；不要為套用本節而在舊資料上 `config new`。兩種備份格式與還原入口不能互換。

### 9.1 每天看一次

<strong>位置：單機 a1 或多機管理 a1，`/opt/teamsync`。</strong>

```bash
cd /opt/teamsync
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
sudo systemctl list-timers 'teamsync-backup-*'
```

成功是 `Cluster healthy`，本頁已設定備份的單機／多機站都應有下次計時器時間；沒有就先做 9.2。備份失敗時，仍在同台同目錄查看記錄：

```bash
sudo journalctl -u 'teamsync-backup-*' --since today
```

`systemctl` 查看 Ubuntu 背景服務／排程，`journalctl` 查看服務記錄。初次未設備份時沒有 timer 正常，不代表已有每日保護。

### 9.2 第一次備份與每日排程

<strong>位置：管理 a1，`/opt/teamsync`。</strong>備份另存資料與復原設定，以防主機毀損；同一資料磁碟上的副本不能防主機或磁碟一起壞。

IT 先將不同故障範圍的加密備份磁碟掛在 `/mnt/site-backup`，工具<strong>不代掛載、加密，也不確認磁碟已加密</strong>。準備方式：

1. 請 IT 用 Ubuntu「磁碟」等系統工具，在<strong>已確認可清空的備份磁碟</strong>建立 LUKS 加密檔案系統，設定獨立解鎖密碼並離線另存。建立／格式化會清空所選分割區，已有資料先另存；已有加密磁碟只需解鎖，不重新格式化。
2. 每次使用前先解鎖，再由 IT 掛載至 `/mnt/site-backup`（Ubuntu「磁碟」可在該檔案系統的齒輪選單編輯掛載選項、指定掛載點），確認可寫且有足夠空間。只有空資料夾不算掛載；一台伺服器內的同一顆資料碟也不算異機備份。需每天手動解鎖者，把它列入值班工作。
3. 每次手動備份前執行下方檢查。每日排程也要由 IT 在該備份 service 加上掛載條件（例如 `[Unit]` 的 `ConditionPathIsMountPoint=/mnt/site-backup`），測試未掛載時會跳過；工具預設 timer <strong>沒有</strong>這個保護。重新開機後也要確認解鎖、掛載及排程。

<strong>位置：a1，先確認備份磁碟真的掛上。</strong>

```bash
findmnt --mountpoint /mnt/site-backup
df -h /mnt/site-backup
```

`findmnt` 必須成功列出<strong>目標正是 `/mnt/site-backup` 的預期備份裝置</strong>（LUKS 通常是 `/dev/mapper/...`）；沒有輸出、裝置不符就停下，不能接著執行備份。`df` 顯示有空間仍不足以證明是備份碟，未掛載時寫入會填滿系統磁碟。解鎖密碼保護整顆備份碟，下面的復原密語則保護備份設定，兩者都要另存。

<strong>確認掛載後，單機 a1 `/opt/teamsync`：</strong>

```bash
cd /opt/teamsync
sudo ./teamsync-cluster backup --target /mnt/site-backup/first
```

多機在同一 a1 加管理連線表：

```bash
sudo ./teamsync-cluster backup --target /mnt/site-backup/first --access-file /root/site-access.json
```

選符合本站的一條，不當成兩份新備份重複執行。首次隱藏問：

```text
復原密語：16–1024 bytes；請離線另存 / Recovery passphrase: 16–1024 bytes; keep it offline separately
Recovery passphrase:
再次輸入 / Repeat recovery passphrase:
```

這個<strong>復原密語</strong>開啟備份的加密設定，和網站密碼、授權金鑰不同；是否與加入檔密語相同依公司政策，但要知道各自用途並另存。沒有密語，支援也不能解開。

成功關鍵行（實際中間還有英文與進度）：

```text
已啟用每日 03:30 線上備份，保留最近 30 份；服務不中止。請另存復原密語。
線上備份 COMPLETE：/mnt/site-backup/first；應用未停寫、服務未停止。
```

採<strong>主機本地時間</strong>，有最多約五分鐘隨機延後。手動 `first` 之外，每日另存同一父目錄，名字類似 `site-站點識別-時間`；預設保留最近 <strong>30 份排程命名的完整組</strong>，不是把所有手動備份在 30 天後刪除。

<strong>`--retention N` 會刪除舊備份，不只是顯示保存天數。</strong>每次新備份成功發布後（包含手動備份），工具在同一父目錄找出同站點、能以該密語驗證、有 `COMPLETE` 且名稱符合 `site-本站識別-*` 的完整組，從新到舊保留 N 份，刪除超出的舊組；SSH 目標也會在遠端新組發布後清理。手動命名的 `first`／`policy-change` 不符合該命名前綴，不在這項清理範圍。N 是<strong>份數</strong>、允許 1–365；降低數字可能在這次成功備份後就刪掉較舊的排程組，先另外保存依法規／公司政策必須保留的版本。

改成每日 02:00、保留 14 份，在 <strong>a1 `/opt/teamsync`</strong>，用新的空目錄：

```bash
sudo ./teamsync-cluster backup --target /mnt/site-backup/policy-change --schedule-at 02:00 --retention 14
```

多機加 `--access-file /root/site-access.json`。只做一次可加 `--no-schedule`，<strong>不會移除既有排程</strong>。無人值守可用 `--yes --passphrase-file /root/site-recovery-key`，該檔由 IT 安全提供、權限 `0600`，不把密語值放命令列。

### 9.3 放在遠端備份伺服器

<strong>位置：管理 a1，`/opt/teamsync`。</strong>IT 先備妥備份伺服器帳號、可寫目錄、SSH 金鑰、已驗證 host key。以下是佔位的 SSH 傳檔位置，<strong>不是下載網址</strong>：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster backup --target ssh://backup@backup.example.com/srv/teamsync/first \
  --staging /mnt/encrypted-staging/first --access-file /root/site-access.json
```

單機可省略 `--access-file`。`--staging` 是本機加密磁碟上的暫存目錄，也需足夠空間；先按 9.2 用 `findmnt --mountpoint /mnt/encrypted-staging` 確認掛載，遠端磁碟也請備份伺服器管理員確認已解鎖、掛載。工具要求傳入 `--staging`，不替您驗證加密狀態。成功遠端有 `COMPLETE`；若 `SSH target requires an encrypted --staging directory`，補上 IT 已掛載的暫存位置。遠端舊組刪除規則同 9.2。

### 9.4 確認備份可用

<strong>位置：a1 終端機，備份已掛載，任意目錄可用絕對路徑查看：</strong>

```bash
ls /mnt/site-backup/first/COMPLETE /mnt/site-backup/first/manifest.json /mnt/site-backup/first/recovery.json
```

三個檔案要存在。`manifest.json` 是驗證清單，`recovery.json` 是加密復原資料；沒有 `COMPLETE` 的部分匯出不能當完整組。仍要定期實際還原，不能只看檔名。

備份收資料庫、搜尋快照、檔案／錄影物件、設定、授權及加密金鑰等；執行中程式記憶體、未封存錄影尾段、未持久保存的即時訊息不保證復原。各資料服務在不同時間取快照，<strong>不是全站同一瞬間</strong>；備份工具不做連續交易日誌回放或任意時間點還原，可恢復範圍以最後完整快照與實際演練為準。

平日線上備份不停服務、不加 `--maintenance`。失敗保留上一完整組，修正空間、權限、連線及健康後，原命令加 `--resume`；不把部分組改名假裝完成。

### 9.5 全站毀損後還原

<strong>先由 IT 關閉、隔離所有舊機器與入口，防止舊站突然恢復寫入。</strong>新替換機使用原計畫、固定 IP、架構與相同絕對目錄，每台放<strong>備份當時完全相同版本的完整 kit</strong>。不先 `config` 建另一站、另一公司或新金鑰身分。

<strong>只有一台的小站：</strong>關閉原 a1，準備一台空的新 Ubuntu 24.04，沿用原 a1 名稱、固定 IP、CPU 架構與 `/opt/teamsync` 路徑，放入同版完整 kit，再執行下面相同的 `--scope site` 流程；此處「全站」就是那一台，<strong>不需要購買 HA 多台主機，也不加 `--access-file`</strong>。若只能修復原硬體，先請 IT 保全原碟並準備乾淨的替換系統與資料空間，不把備份直接灌到仍運作的站。舊 `install.sh` 站的備份則走 `RECOVERY.md` 的 cold-host restore，不能用這個命令。

<strong>位置：新管理 a1，`/opt/teamsync`。</strong>IT 將一份完整組掛載或完整複製到 `/mnt/recovery/site-backup`；如從備份碟讀取，先用 `findmnt --mountpoint` 核對它的實際掛載點。備妥離線復原密語，多機備妥新機連線表。先預覽、不寫入：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster restore --backup /mnt/recovery/site-backup --node a1 --scope site --plan
```

輸入備份復原密語，成功預覽含 `"same_plan_same_kit": true`、`"fencing_required": true` 及順序。確認都是新替換機、舊站已隔離後：

```bash
sudo ./teamsync-cluster restore --backup /mnt/recovery/site-backup --node a1 --scope site --fenced
```

多機加 `--access-file /root/site-access.json`。讀清楚再次確認後答 `yes`。`--fenced` 是您已隔離舊站的聲明，<strong>不會替您關閉舊機器</strong>。

成功：

```text
全站復原完成；請登入核對聊天、檔案、錄影與模組資料。額外物件會保留。
Site restored; verify sign-in, chat, files, recording playback and module data. Extra objects are retained.
```

重新 `status`、`doctor`，實際登入、讀回聊天、下載檔案、查詢原文件與播放舊錄影，確認掛載與備份排程恢復才開放。密語或驗證失敗就停，找完整同一份備份及正確密語，不略過驗證。

只壞一台 HA 機器、其他副本還在時，使用原生重新加入／修復，<strong>不把全站快照灌進存活群</strong>。細節按 `system/CLUSTER.zh-TW.md` 與支援的替換計畫。

## 10. 憑證與授權續期

### 10.1 內部憑證快到期

<strong>位置：管理 a1，`/opt/teamsync`。</strong>`doctor` 列剩餘天數，60／30／7 天有警告；到期後 HTTPS 可能失敗。先排維護時段，確認節點健康與時間同步，保留最新加入檔、管理密語。

先預覽，再更新內部憑證：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster cert renew --source ./teamsync.join --plan
sudo ./teamsync-cluster cert renew --source ./teamsync.join
```

多機兩行加 `--access-file /root/site-access.json`。成功收據有 `"action": "renew"`、`"healthy": true`；未到續期範圍會說 `憑證尚未進入續期範圍 / No internal certificate is due for renewal`，是正常的。不代公開憑證商續約，不隱式換信任根。

### 10.2 匯入已續約的正式網站憑證

僅適用原站 <strong>TLS `2`</strong>。IT 先向憑證商／企業 CA 續約，將新 fullchain、私鑰、信任根安全放在 <strong>a1 `/root/teamsync-tls`</strong>。<strong>操作位置：a1 `/opt/teamsync`。</strong>

```bash
cd /opt/teamsync
sudo chmod 600 /root/teamsync-tls/private.key
sudo ./teamsync-cluster cert import --source ./teamsync.join \
  --certificate /root/teamsync-tls/fullchain.pem --key /root/teamsync-tls/private.key \
  --trust /root/teamsync-tls/root.pem --plan
sudo ./teamsync-cluster cert import --source ./teamsync.join \
  --certificate /root/teamsync-tls/fullchain.pem --key /root/teamsync-tls/private.key \
  --trust /root/teamsync-tls/root.pem
```

`root.pem` 是 IT 的信任根，公開 CA 也可依現場改系統信任根。多機兩行加 `--access-file`。預覽先查現場與順序，實際套用才驗匯入內容。成功有 `"action": "import"`、`"healthy": true`，還要用使用者裝置登入、開會與播錄影；保管更新加入檔。

中斷<strong>重跑原命令</strong>，保留相同 source/export 路徑，不另外加續作旗標。若 `cert import requires TLS mode 2`，原站是私有 CA，不能直接切信任模式，先找支援安排。

### 10.3 只續授權、不更新程式

授權有效期與下載網址有效期不同。續約先向 TeamSync 取得<strong>新金鑰</strong>。

<strong>位置：有網路下載電腦，`$HOME/teamsync-work`。</strong>本機要有與現場相同版本、架構的已驗證 kit，執行檔、`components/base.json`、`license.json` 未修改：

```bash
cd "$HOME/teamsync-work"
. ./.venv/bin/activate
teamsync-cluster fetch --license-only --kit ./teamsync-download/kit
```

隱藏提示輸入新金鑰；也可加 `--license-file ./renewal-key`，由 IT 安全提供、權限 `0600`。成功：

```text
License renewed: <版本>
```

只更新這份 kit 的 `license.json`，不下載映像、不變產品版本；必須相符版本／架構，不能用它升級。

離線站將新 `license.json` 安全放到傳輸媒體，再在 <strong>a1 `/opt/teamsync`</strong>：

```bash
cd /opt/teamsync
sudo install -m 0600 /media/transfer/license.json ./license.json
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

多機逐台更新相符授權再檢查，異架構涵蓋範圍先問支援，不改簽署內容或借用別站授權。

到期後 `status`、`doctor` 仍可診斷且警告；有效期內留下授權部署記錄的<strong>完全相同配置</strong>可修復。新安裝、新設定、新功能先續約。本頁說的是安裝工具行為，不承諾到期後可任意改配置或所有產品功能永不受影響。

## 11. 升級、停機與回復舊版

### 11.1 先辨別流程

升級不重新建立站點。先確認支援的「目前版 → 目標版」、有效授權、可用備份及已通知的停機時段。下載電腦取得目標版，搬至各台<strong>新目錄</strong> `/opt/teamsync-next`，不能蓋住 `/opt/teamsync`。

| 現場 | 入口與限制 |
|---|---|
| 主程式單機，共用單機部署流程 | 新包外層 `upgrade.sh` 指向舊 `system/` |
| 獨立會議／錄影機，或 Sandbox／Edge Workers 舊單機 | 一鍵升級有限制，按新包 `system/MANUAL-UPGRADE.md` 與支援計畫 |
| 原生 `full-ha` 多機 | 先做 11.3 的預檢，符合條件再用 11.4 的維護時段升級；舊站另核對文末注意事項 |

### 11.2 單機 `upgrade.sh`

<strong>位置：既有 a1，`/opt/teamsync`。</strong>新包放 `/opt/teamsync-next`，舊設定在 `/opt/teamsync/system`；新舊 kit 均依第 4.2 節使用 root-owned（root 擁有）的正式目錄，部署與升級都用 `sudo`。從一般使用者擁有的資料夾安裝、再用 `sudo` 部署，不是後續升級支援的配置；請遵循第 4.2 節。本頁 `teamsync-cluster` 單機先完成第 9.2 節的異機 <strong>`./teamsync-cluster backup`</strong>，核對 `COMPLETE` 與復原密語；若是舊 `install.sh` 站，先依 `system/RECOVERY.md` 備份及異機保存。兩種還原入口不同。之後才用新包入口：

```bash
cd /opt/teamsync
sudo /opt/teamsync-next/upgrade.sh --install-dir /opt/teamsync/system
```

`--install-dir` 是<strong>舊設定目錄</strong>，不是新包。程式詢問是否為正確安裝，確認後檢查、保存回復點與備份，再更新程式、資料結構及健康。會有停寫、容器重建與停站，安排維護窗口，不在開會時操作。

升級也會更新 `/opt/teamsync/teamsync-cluster`、加購功能的驗證資料及叢集 `kit` 身分（版本與完整 image-lock 雜湊），再用更新後的外層工具執行 `doctor`。內容相同的唯讀隨包資源可沿用；`BUILD_INFO.txt` 與 `images.tar.gz` 仍須可寫。錄影器設定更新會等後端 `/healthz` 就緒。

成功關鍵行形如：

```text
升級完成 / Update complete: <版本> → <版本>
```

箭頭左側是升級前、右側是升級後的版號。回到 `/opt/teamsync` 執行 `sudo ./teamsync-cluster doctor`，預期 `Cluster healthy`；用原網址登入並驗聊天、文件、已啟用功能與舊錄影播放。共用單機程式更新不代表已完成多機計畫的跨版轉換；若仍回報 kit 身分不符，保留診斷交支援，不手改標記。

資料結構 <strong>schema（資料庫欄位儲存規則）</strong>可能需支援核准，會看到：

```text
這次資料更新需要維護人員核准，尚未套用；請將下列計畫交給維護人員 / Support must approve this data update; it has not been applied. Share this plan with support:
```

程式列計畫與本次 <strong>ticket（作業識別碼）</strong>，嘗試回舊程式維持服務。把去除機密的計畫、版本及記錄送支援；<strong>支援審查核准後</strong>用畫面完整重跑命令。例如仍在 <strong>a1 `/opt/teamsync`</strong>，把文字佔位換成該次代碼：

```bash
sudo /opt/teamsync-next/upgrade.sh --install-dir /opt/teamsync/system --confirm-schema '本次畫面提供的核准代碼'
```

它不是授權金鑰，也不是看到就自行批准；不能拿舊 ticket 批准另一計畫。刪資料的更新會被拒絕，選項不能繞過。

回舊程式優先用完成畫面的 `Undo` 命令；標準入口在 <strong>a1 `/opt/teamsync/system`</strong>：

```bash
cd /opt/teamsync/system
sudo bash scripts/upgrade.sh --rollback
```

用本次升級程式保存的回復點，回程式不刪資料；它不取代第 9 節的異機完整備份。已新增資料結構不倒回、資料庫軟體不保證降版。若整台毀損，本頁的 cluster 單機仍按 <strong>9.5 用原版 kit 與 cluster 完整備份還原</strong>；舊 `install.sh` 站才按 `RECOVERY.md`。健康仍不正常找支援，不反覆改映像或刪資料。

回復點也包含外層 CLI、加購驗證資料與舊 `kit` 身分；回滾時還原未被後續修改的項目，保留其他叢集設定。若升級後有人再修改過相關檔案或身分，先交支援核對，不強制覆蓋。

### 11.3 多機升級預檢

<strong>位置：管理 a1，`/opt/teamsync`。</strong>各台放好目標 kit 後，用新包工具預檢，明確指向現有站點的狀態目錄：

```bash
cd /opt/teamsync
sudo /opt/teamsync-next/teamsync-cluster upgrade --state-dir /opt/teamsync/cluster \
  --kit /opt/teamsync-next --dry-run --access-file /root/site-access.json
```

`--dry-run` 是預覽，不停服務，成功 JSON 含 `"mutated": false`、`"zero_downtime_promised": false`。預檢會核對各台新包、服務清單與資料映像身分；通過不代表可更換拓樸，也不保證零停機。

若回報資料映像、引擎或磁碟格式不相容，先保留原 kit 與完整備份，交由支援確認遷移或復原計畫；舊站另查文末注意事項。<strong>不要覆蓋已簽章執行檔或修改 image lock（映像身分清單）騙過檢查。</strong>單機採 11.2 的流程。

### 11.4 多機維護時段升級

只有 TeamSync 確認來源與目標的<strong>拓樸（每台負責什麼、彼此如何相連）</strong>、角色、功能、服務清單相同，資料／儲存映像身分相容，才能使用。先完成 11.3 的預檢，再安排維護；未通過的轉換不能靠加旗標放行。

<strong>位置：原管理 a1，`/opt/teamsync`。</strong>每台放目標版在 `/opt/teamsync-next`，用新工具、明確指向舊狀態目錄：

```bash
cd /opt/teamsync
sudo /opt/teamsync-next/teamsync-cluster upgrade --state-dir /opt/teamsync/cluster \
  --kit /opt/teamsync-next --dry-run --access-file /root/site-access.json
```

預檢通過、版本組合經支援確認後，等錄影封存、停止外部直接寫入與派工、備妥加密異機備份掛載，在<strong>同台同目錄</strong>：

```bash
sudo /opt/teamsync-next/teamsync-cluster upgrade --state-dir /opt/teamsync/cluster \
  --kit /opt/teamsync-next --backup-target /mnt/site-backup/before-upgrade --maintenance \
  --access-file /root/site-access.json
```

`--maintenance` 進入維護，先完整備份，再逐服務逐機更新及驗健康。<strong>會封鎖使用者寫入並中斷會議，不承諾零停機。</strong>停機依備份量、載入、健康檢查，按本站演練留窗口。

成功有 `Cross-version serial upgrade complete`；每台再 `status`、`doctor`，讀回聊天、檔案、舊錄影、新錄影。資料庫、搜尋、儲存、訊息資料服務映像變更可能仍拒絕，不能靠多加旗標處理。

中斷保留原目標 kit、協調機、備份位置與密語，修原因後在 <strong>a1 `/opt/teamsync`</strong>：

```bash
sudo /opt/teamsync-next/teamsync-cluster upgrade --state-dir /opt/teamsync/cluster \
  --kit /opt/teamsync-next --backup-target /mnt/site-backup/before-upgrade --maintenance \
  --access-file /root/site-access.json --resume
```

若等 schema 核准，支援批准後在<strong>原續作命令</strong>加 `--confirm-schema '本次畫面提供的核准代碼'`；若暫停的是新安裝 `deploy`，原 deploy 也可加該選項。這兩個入口都支援這個核准欄位；只接受畫面顯示、且由支援核准的該次 ticket。

不刪維護標記或改 `cluster/state/maintenance.json` 解除限制。服務更新前失敗，新工具嘗試恢復本次暫停服務；服務已變更後則保留維護、完整備份與續作記錄。

### 11.5 叢集回復舊版

叢集升級沒有對存活資料庫直接降版的選項。按 9.5，<strong>隔離所有舊機與入口，用全新替換機、升級前原版 kit 及完整備份復原</strong>。

<strong>位置：新替換 a1，`/opt/teamsync`，已放原版 kit。</strong>掛入維護記錄的實際 `backup_target` 完整組，以下為本例：

```bash
cd /opt/teamsync
sudo ./teamsync-cluster restore --backup /mnt/site-backup/before-upgrade --node a1 --scope site --plan
sudo ./teamsync-cluster restore --backup /mnt/site-backup/before-upgrade --node a1 --scope site \
  --fenced --access-file /root/site-access.json
```

用當時備份密語。復原、產品驗收後才開放；回到備份時間點，之後已收到成功回應的寫入需另對帳。要保留新寫入先評估原升級 `--resume`，不直接覆寫。

## 12. 常見拒絕訊息

下表為程式實際訊息或其中一段；IP、路徑、角色依現場變化。修正後在<strong>原機器、原目錄</strong>重跑，不重新建立站點。

| 訊息 | 在哪台、如何處理 |
|---|---|
| `License is invalid or unavailable. Contact TeamSync support.` | 下載電腦：支援查金鑰、版本、效期與用量，不在工單貼金鑰 |
| `Too many attempts. Wait one minute` | 下載電腦：等一分鐘，在原目錄重試，不快速重兌換 |
| `Use --license-file or TEAMSYNC_LICENSE_KEY when no interactive terminal is available.` | 下載電腦：用 3.3 的檔案／環境變數 |
| `Download window expired. Contact TeamSync support for a new key.` | 下載電腦：找支援發新金鑰，舊網址不延長 |
| `Release signature verification failed. Do not install.`／`Checksum failed for` | 下載電腦：停止安裝、保留目錄，重跑下載驗證；仍失敗交支援，不略過簽章 |
| `此版僅支援 Ubuntu 24.04（amd64 / arm64）` | 該機器：新的 Ubuntu 24.04＋同架構包；既有站先備份安排遷移，不降級系統函式庫 |
| `Kit architecture ... does not match host` | 該機器：按 `uname -m` 重取正確架構 |
| `Missing kit file; copy the complete licensed kit and retry` | 該機器：完整同版 kit 重搬，不只複製執行檔 |
| `授權未包含`／`Your license does not include` | 管理 a1：取消未購功能，或取得新授權與包 |
| `Insufficient RAM; fix the allocation, then rerun deploy` | 該機器：增加實際可用 RAM，CPU／disk 同理；依角色門檻見 2.3 |
| `DNS cannot resolve` | 該機器及使用者裝置：IT 修公司 DNS，伺服器自己有 hosts 記錄不代表其他裝置能解析 |
| `Peer ... is unreachable; power it on and fix its static IP and LAN/VLAN, then rerun deploy` | 點名機器：開機、查固定 IP、網路分區與規則 |
| `Port ... is already used by another process; stop or reconfigure it, then rerun deploy` | 該機器：IT 查既有服務，不直接停不認識的資料庫或另一套 TeamSync |
| `Docker is unavailable; run sudo systemctl start docker, then rerun deploy` | 該機器：在 `/opt/teamsync` 用下方啟動命令 |
| `cgroup is too old; enable cgroup v2, reboot, then rerun deploy` | 該機器：IT 查 Ubuntu 資源管理設定、安排重開，不在業務中途自行重開 |
| `Mount all Silo drives first; this tool never formats disks` | 原生 storage：IT 先掛每顆計畫磁碟，建立同名空目錄不算掛載 |
| `Existing configuration differs; refusing rebootstrap` | 該機器：保留原身分，查是否拿錯站點設定，不刪 `cluster/` |
| `Passphrases do not match`／`Passphrase file must have mode 0600` | 管理機：兩次密語一致，或修檔案權限，不印內容 |
| `Backup target cannot be inside kit/data drives` | a1：改異機掛載或 SSH 目標，不放 kit 或資料碟 |
| `Online snapshots restore a whole site; use native rejoin/heal for one lost member` | 管理機：單台 HA 故障用重新加入／修復，不全站覆寫存活群 |
| `Repair nodes and NTP before renewal` | a1：先修點名機器健康與時鐘再續憑證 |
| `JVB still has conferences and was retained; resume after they finish` | a1：等會議結束，原 `node remove` 加 `--resume`，不先斷電 |
| `changes a datastore image without proven identical engine/on-disk format` | a1：資料映像尚未證明引擎／磁碟格式相同，找支援確認遷移或復原計畫，不改驗證資訊 |

Docker 未啟動的修復，<strong>位置：點名的該機器，`/opt/teamsync`</strong>：

```bash
cd /opt/teamsync
sudo systemctl start docker
sudo ./teamsync-cluster deploy --apply-firewall
sudo ./teamsync-cluster doctor
```

成功回 `Cluster healthy`。還有錯誤就按第 14 節收診斷；若畫面指私有 `/tmp/teamsync-step-...log`，由管理員本機看並去除機密，再提供必要片段，不整份公開。

## 13. 常見問題 FAQ

<strong>1. 完全沒裝過，要先申請什麼？</strong>找合約上的 TeamSync 業務／部署窗口拿授權金鑰，IT 備妥 Ubuntu 24.04、固定 IP、網站與備份位置，照第 2 節打勾。

<strong>2. 金鑰忘了、遺失或用過怎麼辦？</strong>找原窗口，以客戶名稱、合約、非機密錯誤查詢，不公開原金鑰。

<strong>3. 有公開安裝包下載頁嗎？</strong>沒有。PyPI 只有下載器，產品包依金鑰取得，不依舊文件猜下載網址。

<strong>4. 下載中斷，要再耗一次授權嗎？</strong>有 `.teamsync-fetch.json` 就原目錄續傳；兌換回應還未保存時依下載器與服務版本處理，見 3.5。不確定先讓支援查用量。

<strong>5. 機房完全無 Internet 能裝嗎？</strong>可以，另一台下載驗證後搬入，設定選 <strong>`lan-only`</strong>；用內部 DNS／hosts、kit 私有 CA、內部 NTP。辦公室外無法連入，不能呼叫只在 Internet 的 AI／第三方服務，詳 2.4。

<strong>6. 能用 Mac 或 Windows 嗎？</strong>正式目標伺服器只支援 Ubuntu 24.04 amd64／arm64。Windows 辦公室可用 WSL2／Ubuntu 虛擬機下載，macOS 下載所需工具與限制見 3.1；員工可用受支援的瀏覽器裝置。

<strong>7. Intel、AMD、ARM 選哪個？</strong>目標機 `uname -m` 為 `x86_64` 選 amd64，`aarch64`／`arm64` 選 arm64，不能依下載機猜。

<strong>8. 金鑰／sudo 密碼輸入沒有字，是壞了嗎？</strong>正常，輸入後 Enter。金鑰、Linux 密碼、網站密碼與復原密語不同。

<strong>9. 安裝後用什麼登入？</strong>預設 `admin`；單機初始密碼 `system/.teamsync-deploy-state/admin-password`，原生 HA 第一台 app 為 `cluster/admin-password`。先核對 0600 權限，只在私人畫面看，登入改密碼並測試後依 5.5／8.2 刪除該檔。

<strong>10. 網站憑證警告可直接略過嗎？</strong>驗收前由 IT 裝公開 CA 根、核對名稱；模式 2 查 fullchain 與效期，不把略過當正常。

<strong>11. 怎麼備份？</strong>本頁 cluster 單機／多機都在管理 a1 依 9.2 `backup --target`；先核對加密碟已掛載，首次成功預設每日 03:30、保留最近 30 份排程命名完整組，成功發布新備份後會刪超額舊組。舊 `install.sh` 站走 `RECOVERY.md`。密語另存，定期還原驗證。

<strong>12. 忘記備份密語，TeamSync 能解嗎？</strong>不能。依公司政策另存、測試，不只存在可能壞掉的主機。

<strong>13. 升級就是再裝最新包嗎？</strong>先備份、確認支援版間轉換，單機與多機入口不同，見第 11 節。不覆蓋運作目錄、不重建公司身分。

<strong>14. 舊多機站一定能直接升到最新嗎？</strong>先做 11.3 預檢並核對文末的「特定舊版升級注意事項」；支援確認轉換方式後才安排維護，不以下載成功當成升級相容。

<strong>15. 授權到期會刪資料嗎？</strong>工具到期流程沒有刪資料這一步。可診斷、修復符合原記錄的同配置；新裝／變更先續約，仍主動續約與備份。

<strong>16. 離線現場怎麼續約？</strong>有網路電腦以新金鑰 `fetch --license-only --kit ...`，相符 `license.json` 搬回各台，不需重抓全部映像。

<strong>17. 憑證快到期？</strong>內部用 `cert renew`，模式 2 網站先向簽發單位續約，再 `cert import`；和授權續約是兩件事。

<strong>18. 加一台只要 join？</strong>join 只加入計畫既有機器；新增須完整計畫與 8.6 支援的角色。不能直接把單機變 HA。

<strong>19. 會議沒有錄影按鈕，沒裝好嗎？</strong>本流程隱藏手動按鈕，自動錄影依設定；實際結束一場並播放驗收，同時錄影要足夠名額與容量。

<strong>20. 重新開機要再兌換授權？</strong>不需，日常用離線授權及既有設定。服務沒恢復先 `status`／`doctor`，保留原身分修復。

<strong>21. `site deploy` 不認得？</strong>先確認使用的是正式交付 kit 根目錄的 `teamsync-cluster`，不要把 PyPI bootstrap 當成 kit 執行檔。舊 kit 照當時隨包文件操作；需要更新時按第 11 節安排。

<strong>22. 出事找誰，要寄整包？</strong>IT 先查主機、DNS、磁碟、網路，再找合約支援。不寄整個 kit、資料庫、`prod.env`、加入檔或金鑰，見下一節。

<strong>23. 網站可用，doctor 卻說 kit 不同？</strong>先保留完整訊息，核對文末的「特定舊版升級注意事項」；正式安裝目錄與擁有者須符合 4.2，不直接修改 `cluster.json` 或 image lock。

<strong>24. nginx 正常，為什麼 Internet 仍連不到 80／443？</strong>單機入口使用 host network，`deploy --apply-firewall` 的允許清單會管制兩埠；本頁 `lan-only` 範例只允許 private 網段，其他外部來源被拒絕是預期行為。請 IT 核對 5.3 的來源規則、網路類型及公司外圍防火牆；需要對外服務時依 2.4 規劃 `nat-entry`、固定外部 IP 與轉送，再從核准來源驗收，不把私有上游埠對外打開。

## 14. 尋求協助

走合約上的 TeamSync 部署／支援窗口，提供客戶名稱、時間與時區、哪台／角色、產品版號與架構、想做什麼、不含秘密的原始指令與拒絕訊息、影響範圍及已做的修復。版本可查看 `components/base.json`、`system/BUILD_INFO.txt`，不需送授權內容。

<strong>位置：問題機器，`/opt/teamsync`，多機另在管理 a1 收一次。</strong>先保存私人診斷檔供本機審閱：

```bash
cd /opt/teamsync
umask 077
sudo ./teamsync-cluster doctor --json > "$HOME/teamsync-doctor.json"
sudo ./teamsync-cluster status --json > "$HOME/teamsync-status.json"
```

JSON 是機器與人都能讀的結構化文字；不健康可能以非零狀態結束，仍可有 `healthy`、節點與建議。若載入前就拒絕，檔可能空，提供終端機非機密訊息。審閱去除密碼、權杖、下載網址後，用核准管道提供必要資料。

<strong>絕不貼出：</strong>授權金鑰、`.teamsync-fetch.json` 簽名下載網址、網站密碼、管理／復原密語、SSH／TLS／CA 私鑰、`teamsync.join`、`cluster/admin.json`、`cluster/secrets.json`、`prod.env` 或完整備份。截圖也先遮蔽。

以下文件都<strong>在 kit 內</strong>，路徑相對 `/opt/teamsync`，不需要私人程式庫：

| 隨附路徑 | 內容 |
|---|---|
| `安裝指南.pdf` | 圖文安裝操作 |
| `system/README.zh-TW.md`／`system/README.md` | 功能與既有單機操作 |
| `system/CLUSTER.zh-TW.md`／`system/CLUSTER.md` | 角色部署、TLS、備份、還原及限制，依手中版本可用功能為準 |
| `system/INSTALL.md` | 單機及分機安裝背景 |
| `system/MANUAL-UPGRADE.md` | 一鍵升級不適用時的流程 |
| `system/RECOVERY.md` | <strong>舊 `install.sh` 安裝入口</strong>的 `backup.sh`／`restore.sh`、異機保存與 cold-host restore；本頁用 cluster 工具建的單機／分機／HA 走第 9 節與 CLUSTER 指南，備份格式不互換 |
| `system/CLUSTER-SITE.md` | kit 附帶的全站部署與續作 |

## 15. 名詞表

| 名詞 | 平常話 |
|---|---|
| on-prem／地端 | 服務在客戶機房 |
| bootstrap／下載器 | PyPI 小工具，先取授權包 |
| license key／授權金鑰 | 兌換碼，只安全輸入 |
| offline license | 已簽署 `license.json`，現場離線驗證 |
| kit／安裝包 | 程式、依賴、映像、文件與授權完整組合 |
| terminal／終端機 | 輸入、查看指令的視窗 |
| directory／目錄 | 資料夾，絕對路徑從 `/` 開始，相對路徑從目前位置開始 |
| sudo／SSH | 管理員執行／加密遠端登入；host key 是機器身分 |
| node／role | 一台機器／該機負責的工作 |
| cluster／site | 共用身分的一組機器，單機也有站點 |
| entry／nginx | 接收、轉送使用者連線的網站入口 |
| private IP／DNS | 內網位址／網站名稱對應 IP 的通訊錄 |
| firewall／allowlist | 防火牆門禁／允許來源與服務的規則 |
| certificate／TLS／HTTPS | 憑證身分／加密驗證／採用它的網站連線 |
| CA／fullchain／PEM | 簽發信任來源／網站及中繼證明鏈／憑證文字格式 |
| amd64／arm64 | 兩種目標 CPU 架構，須符合本機 |
| Python／pip／venv | 執行工具／安裝 Python 套件／獨立工作環境 |
| Docker／container／image／Compose | 執行工具／隔離服務／固定程式包／協調多容器 |
| API／CLI | 網站功能呼叫程式的介面／文字命令操作介面 |
| HA／quorum | 多機接手設計／安全服務所需健康多數 |
| VIP／VRRP／external-lb | 共用可接手 IP／內網交接機制／既有流量分配設備 |
| Silo／MinIO／pool | 檔案儲存服務／相容介面／一次完整新增的儲存組 |
| Jitsi／JVB／Jibri | 會議服務／影音轉送／錄影 |
| Sandbox／Edge Workers | 隔離程式工作／站點模組執行功能 |
| join file／管理密語 | 加密交接檔／開啟它的密語，非網站密碼 |
| recovery passphrase | 開備份加密設定的密語，離線另存 |
| SHA-256／簽章 | 檔案指紋／來源及未被更改的驗證 |
| schema／ticket | 資料儲存規則／某次計畫識別碼 |
| dry-run／maintenance／resume | 預覽／維護停寫／原記錄續作 |
| rollback／restore | 回舊程式／完整備份重建資料及設定，效果不同 |

## 特定舊版升級注意事項

- 部署問答及設定檔可自訂公司名稱、管理員帳號與密碼；既有站升級保留原公司與帳號，改名或改密碼請使用管理介面。
- 如果單機網站可用，但在 `/opt/teamsync` 執行 `sudo ./teamsync-cluster doctor` 以代碼 2 結束，顯示 `版本或映像 lock 不同`：先依 11.2 備份並升級到最新正式交付版，同步外層工具、加購驗證資料與完整 kit 身分，再跑 `doctor`。仍不符就交支援，不手改 `cluster.json` 或 image lock。
- 如果 `components/base.json` 的版號是 <strong>v5.28.0</strong>，而且本站是多機部署：不能直接用 cluster `upgrade` 升到 <strong>v5.29.0 資料映像基準版</strong>，也不能略過資料相容檢查直升後續版。保留舊 kit 與完整備份，請支援提供已驗證的資料遷移或全新替換機復原方案；後續維護升級仍受 11.3–11.4 的相容條件限制。單機走 11.2，不走這個多機資料映像流程。

## English quick reference

Use the current signed, officially delivered kit. The PyPI bootstrap downloads and verifies it; the kit's executable configures and operates the site. Updating the bootstrap does not upgrade an installed site. No public kit download page exists. Ask your TeamSync contract contact for a key; never put keys, private URLs or passwords in tickets.

<strong>Connected Ubuntu download computer, `$HOME/teamsync-work`:</strong> Python >=3.8 and GnuPG. Prepare the venv as in section 3:

```bash
cd "$HOME/teamsync-work"
. ./.venv/bin/activate
python -m pip install --upgrade teamsync-cluster
teamsync-cluster fetch --dest ./teamsync-download --arch amd64
```

Use the hidden prompt, `--license-file` or `TEAMSYNC_LICENSE_KEY`. Select arm64 for ARM targets. Omitting the product version lets the license channel choose the release; the `latest` channel selects the latest published release at redemption. Keep the complete destination private and reuse it to resume the same release; interrupted redemption handling is in section 3.5. Expiring download links cannot be extended by replaying a receipt.

<strong>Offline target, `/opt/teamsync`:</strong> Ubuntu 24.04, Python >=3.10, native amd64/arm64 kit, fixed private IPs. A disconnected office-only site selects <strong>`lan-only`</strong>, kit private CA, internal DNS/hosts and internal NTP; outside-office access and Internet-only services are unavailable. Other network types: `nat-entry` forwards through the entry, `dual-homed-entry` uses a second entry NIC, `routed` requires IT-provided routed addresses. See section 2.4. Base-only: roles `entry,app,data,storage`, profile `single`. Licensed meetings on one host: select `jitsi`, role `all-in-one`.

```bash
cd /opt/teamsync
sudo ./teamsync-cluster config
sudo ./teamsync-cluster deploy --apply-firewall
sudo ./teamsync-cluster status
sudo ./teamsync-cluster doctor
```

Expected: `Cluster healthy`, including offline sites with working local DNS and synchronized time. Trust the public site CA or supply an authoritative fullchain. Open your website's `/static/web`, default username `admin`; check 0600 permissions and view the initial password privately (single host `system/.teamsync-deploy-state/admin-password`, native HA first app `cluster/admin-password`). After changing the password and verifying sign-in, delete that initial password file (sections 5.5 and 8.2). Review exact firewall scope and console recovery in section 5.3 before applying it; use tmux for SSH deployments.

Single-host nginx remains a pinned container and uses <strong>host networking</strong>. The host allowlist applied by `sudo ./teamsync-cluster deploy --apply-firewall` covers both TCP 80 and 443, including saved port overrides. In `lan-only`, outside sources are rejected even while nginx runs; site-owned Docker bridge callbacks remain allowed. Silo 9000, MQTT WS 8083, Edge gateway 9080 and same-host Jitsi HTTPS 8443 bind only to loopback. IT still owns the perimeter firewall and any public forwarding (sections 2.5 and 5.3).

<strong>Administrator a1, `/opt/teamsync`:</strong> mount encrypted off-host backup storage first. Multi-host operations need a verified SSH access map via `--access-file`.

```bash
cd /opt/teamsync
findmnt --mountpoint /mnt/site-backup
```

Proceed only if `findmnt` confirms the expected encrypted backup device, then:

```bash
sudo ./teamsync-cluster backup --target /mnt/site-backup/first
sudo ./teamsync-cluster cert renew --source ./teamsync.join --plan
```

Sites created by this guide's cluster tool, including a single machine, use cluster `backup`/`restore`; legacy `install.sh` sites use the separate `system/RECOVERY.md` workflow. First successful cluster backup enables daily online backup at 03:30 local time; publishing a new backup prunes excess old same-site scheduled-name complete sets (default 30). Keep the recovery passphrase separately. Restore only onto fresh, same-plan, same-kit replacements after fencing all old hosts (section 9.5); a single-machine site needs one replacement a1. Renew supplied website certificates with `cert import`; no ACME automation.

<strong>Connected download computer, `$HOME/teamsync-work`:</strong> new key, existing version, no archive downloads:

```bash
cd "$HOME/teamsync-work"
. ./.venv/bin/activate
teamsync-cluster fetch --license-only --kit ./teamsync-download/kit
```

Transfer only the matching renewed `license.json` to offline kits. Expiry permits diagnostics and exact previously authorized deployment repair; new configuration/add-ons require renewal.

<strong>Single-host upgrades:</strong> keep root-owned kits at `/opt/teamsync` and `/opt/teamsync-next` as in section 4.2, back up first, then run `sudo /opt/teamsync-next/upgrade.sh --install-dir /opt/teamsync/system` from `/opt/teamsync`. Installing from a user-owned folder and deploying with sudo is unsupported for later upgrades. The upgrade also updates the outer CLI, add-on authority data and sealed kit identity (version plus full image-lock hash); rollback restores these if they have not subsequently changed. Identical read-only bundle resources can be reused (version/image files still need write access), and recorder refresh waits for backend `/healthz`. Rerun `doctor` and verify the product. Support must review before `--confirm-schema`; legacy upgrade symptoms are collected in the preceding upgrade-notes section.

<strong>Multi-host upgrades:</strong> qualified same-topology `upgrade --maintenance` requires compatible data/storage image identities, unchanged roles and service inventory, and a successful preflight. Maintenance causes downtime; `--resume` continues the original operation. Cluster rollback restores the old kit plus complete pre-upgrade backup onto fenced fresh replacements. Read section 11 and the preceding upgrade-notes section before acting.
