執行無介面伺服器
在一部長期開機的機器上執行 cc_server,然後從你的桌面、瀏覽器或手機連接它。這部伺服器是純 Dart 原生二進位檔——不含 Flutter 引擎——因此可在 macOS、Linux 或 Windows 上無介面執行。它擁有資料庫、執行代理,並發出所有對外 API 呼叫;用戶端只負責呈現。
用 Docker 執行(預建映像)
標題為「用 Docker 執行(預建映像)」的章節每個版本都會發佈一套自託管技術堆疊,共四個 GHCR 映像——後端、兩個靜態精簡用戶端以及可選的配對中繼——另加一個供公開示範主機使用的獨立 cc-server-demo 映像。自託管安裝無須檢出原始碼。請固定版本標籤(ghcr.io/samuelalev/<image>:v0.0.1-rc.1),或跟隨 latest。
| 映像 | 它是甚麼 | 發佈連接埠 |
|---|---|---|
ghcr.io/samuelalev/cc-server |
後端:資料庫、代理、MCP、webhook | -p 9030:9030 |
ghcr.io/samuelalev/cc-webapp |
網頁用戶端(靜態 nginx) | -p 8080:8080 |
ghcr.io/samuelalev/cc-remote |
手機夥伴 PWA(靜態 nginx) | -p 8081:8080 |
ghcr.io/samuelalev/cc-signaling-server |
WebRTC 配對中繼(可選) | -p 8788:8788 |
整個技術堆疊的 compose 檔案如下:
services: server: image: ghcr.io/samuelalev/cc-server:latest ports: ["9030:9030"] volumes: ["cc_data:/data"] restart: unless-stopped web: image: ghcr.io/samuelalev/cc-webapp:latest ports: ["8080:8080"] restart: unless-stopped remote: image: ghcr.io/samuelalev/cc-remote:latest ports: ["8081:8080"] restart: unless-stopped signaling: image: ghcr.io/samuelalev/cc-signaling-server:latest ports: ["8788:8788"] restart: unless-stopped
volumes: cc_data:在把這一切暴露到回送以外的任何地方之前,有幾件值得知道的事:
-
cc-server映像隨附CC_SERVER_INSECURE=1(它必須繫結0.0.0.0才能接收已發佈連接埠的流量),這只有在可信網絡上、位於終止 TLS 的反向代理——Caddy、Traefik、nginx 或 Cloudflare Tunnel——之後才安全。若改為在行程內終止 TLS,請掛載憑證並設定CC_SERVER_TLS_CERT/CC_SERVER_TLS_KEY(然後取消設定CC_SERVER_INSECURE)。這一切都可用docker run -e …或 compose 的environment:區塊覆寫。 -
/data是唯一的狀態。 SQLite 資料庫、已配對裝置的密鑰、 下載的模型與會議音訊全都存放在這個磁碟區內——備份它,容器就變得可以隨時丟棄。 -
在首次連接之前,從映像內部配對用戶端,這相當於容器版的第 3 步:
終端視窗 docker run --rm -it -v cc_data:/data \--entrypoint /app/bin/cc_server ghcr.io/samuelalev/cc-server:latest pair -
兩個用戶端映像都是靜態 nginx 主機——執行時無須設定任何東西;每個用戶端的連接表單接受你的伺服器 URL、裝置 ID 與配對金鑰。訊號中繼同樣只需要它的連接埠 (
SIGNALING_HOST/SIGNALING_PORT可覆寫);它是無狀態的、不持有任何密鑰,而且是一條後備途徑——手機在可觸達時會使用回送、LAN、tailnet 或 直接的wss://路徑,只有在全部不可用之時才退回中繼。如果你的用戶端一律能直接觸達伺服器,就略過它。
本指南其餘部分會從原始碼建置伺服器;它所涵蓋的旗標與行為,與映像的環境變數所餵給的是同一批。
先決條件
標題為「先決條件」的章節- Dart SDK。此程式庫以 fvm 固定其 SDK,因此每條指令都要加上
fvm前置詞。 - 檢出此程式庫。
- 暫存腳本所需的原生工具鏈——Rust/
cargo,加上meson、ninja、pkg-config、git以及一個 C++ 編譯器。每個建置腳本都會指出它找不到甚麼,以及該如何安裝。 - 一個可觸達的主機:本機使用時用回送,或供遠端用戶端使用時用帶 TLS 的 LAN/公開位址。
第 1 步:暫存原生程式庫
標題為「第 1 步:暫存原生程式庫」的章節原生程式庫是必需的——沒有降級模式。請在做任何其他事之前,從程式庫根目錄建置它們:
scripts/natives/build_natives.sh這會把 rift、fff、tree-sitter 及其文法、aec、lame、
ccpty、cc_watcher、cc_inference 以及 SAML 原生程式庫建置到
build/natives/。cc_server 建置
掛鉤會把暫存在那裏的東西重新輸出到套件組合中,因此略過此步驟,要麼直接令建置失敗,要麼——配合下方的逃生出口——產生一個二進位檔,其啟動前檢查會拒絕啟動並指出缺少的程式庫。
第 2 步:建置二進位檔
標題為「第 2 步:建置二進位檔」的章節cd apps/cc_serverfvm dart build cli套件組合會隨二進位檔一併帶上 libsqlite3 與已暫存的原生程式庫——無需系統 SQLite,也無需 Flutter 引擎。可執行檔會落在
./build/cli/<os_arch>/bundle/bin/cc_server。
第 3 步:在首次啟動前配對用戶端
標題為「第 3 步:在首次啟動前配對用戶端」的章節全新的資料目錄沒有任何已配對裝置,也沒有預先共用金鑰,因此用戶端的
配對金鑰提示暫時無法滿足。請用 pair 子指令產生一組。它會直接寫入 global.db 與 secrets.json;一個已在提供該資料目錄服務的伺服器,無須重新啟動就會接收這個新裝置:
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030它會印出三個值,讓你貼到用戶端的連接表單:
Connect a thin client (paste into its connect form): Server ws://localhost:9030/rpc Device id web-client Pairing key <a freshly generated key>實用旗標:--device(預設 web-client;這個 id 同時決定裝置層級——desktop、ios、android,其他一律是網頁用戶端)、--label
(預設為平台名稱加上本機的主機名稱)、--host(要印在 URL 中的主機,因為回送無法從另一部機器觸達)以及
--client-url。重新執行 pair 會輪替該裝置的金鑰,並丟棄其現行工作階段。配對從不建立工作區:連接的用戶端會在其新手導引中為第一個工作區命名並建立它。
帶 --client-url 時,它也會印出一個可在終端掃描的 QR 碼,開啟已填好資料的網頁用戶端:
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030 \ --bind any --host 192.168.1.42 --client-url https://app.usectrl.dev由 cc_server pair 簽發的憑證沒有到期時間;在應用程式中簽發的憑證則一律在 30 天後到期。用完之後,請從
設定 → 你 → 你的裝置 撤銷這個由 CLI 簽發的裝置。
第 4 步:啟動伺服器
標題為「第 4 步:啟動伺服器」的章節在回送上——這是預設,也是同一部機器上的用戶端所需的全部:
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030若要從另一部機器觸達它,請繫結所有網絡介面。沒有 TLS 的非回送繫結
會在啟動時被拒絕(Refusing to bind non-loopback address … without TLS),因此請提供憑證:
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \ --bind any --tls-cert /path/fullchain.pem --tls-key /path/privkey.pem \ --public-url wss://server.example:9030/rpc或者,在可信私人網絡上於反向代理中終止 TLS,並在其後選用明文繫結:
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \ --bind any --insecure --public-url wss://server.example/rpc當 --tls-cert 與 --tls-key 兩者都設定時,--insecure 會被忽略——TLS
一律勝出。伺服器會在 GET /healthz 中把明文狀態公佈為 insecure: true,而用戶端會把這類連線標示為不安全。
伺服器會一直執行到收到 SIGINT/SIGTERM,然後乾淨地關閉。
第 5 步:連接用戶端
標題為「第 5 步:連接用戶端」的章節把用戶端指向第 3 步取得的伺服器 URL 與配對金鑰:
- 桌面應用程式:在首次執行畫面(Control Center 應如何執行?)填寫連接欄位,而不要選在此應用程式內執行;或稍後在 設定 → 伺服器 → 連接與狀態 加入這部伺服器。參見連接遠端伺服器。
- 網頁用戶端:開啟 app.usectrl.dev(或你自己的網頁組建複本),然後輸入伺服器 URL、裝置 ID 與配對金鑰。
- 手機:從執行中的用戶端配對 Remote 應用程式——參見配對裝置。
第 6 步:連接 Google Calendar(可選)
標題為「第 6 步:連接 Google Calendar(可選)」的章節若要在沒有圖形介面的情況下同步某個工作區的日曆,請使用裝置碼流程:
GOOGLE_OAUTH_CLIENT_ID=<id> GOOGLE_OAUTH_CLIENT_SECRET=<secret> \ ./build/cli/<os_arch>/bundle/bin/cc_server calendar connect \ --data-dir ./data --workspace <workspace-id>它會印出一組代碼與一個 URL,讓你在另一部裝置上批准,然後在伺服器端儲存重新整理權杖並結束。原始碼建置不會隨附任何 Google 用戶端,因此必須提供 id 與 secret 環境變數——沒有 --google-client-id
這個旗標。參見連接 Google Calendar。
上方用到的旗標,就是首次設定所需的那些。完整的介面——23
組旗標與環境變數配對、四個子指令,以及資料目錄的佈局——都在 cc_server CLI 參考 中。
你最可能需要的那四個:
| 旗標 | 預設值 | 含義 |
|---|---|---|
--data-dir |
作業系統的每位使用者應用程式資料目錄 | 資料庫、密鑰、模型與快取媒體 |
--port |
9030 |
TCP 連接埠(0 = 臨時) |
--bind |
loopback |
loopback,或 any 表示所有網絡介面(需要 TLS 或 --insecure) |
--public-url |
由繫結推導 | 向已配對用戶端公佈的 RPC URL。在代理、NAT 或通道後方時,請明確設定它 |
預設資料目錄在 macOS 上是 ~/Library/Application Support/control-center,
在 Windows 上是 %APPDATA%\control-center,其他地方則是 $XDG_DATA_HOME/control-center(否則為
~/.local/share/control-center)。只有在無法解析出家目錄或應用程式資料目錄時,才會使用相對於 cwd 的 .cc_server。
伺服器提供哪些服務
標題為「伺服器提供哪些服務」的章節cc_server 是完整的產品介面,而不是其中一部分:repo-RPC 資料路徑
與訂閱、位於同一個連接埠上的 POST /mcp 與 GET /sse MCP 工具端點、入站 webhook、媒體與字型代理、單一登入
回呼、機群租約協定、按 30 分鐘排程進行的伺服器端 RSS 擷取,以及向量搜尋(sqlite_vector 擴充功能會註冊為
行程全域的自動擴充功能,只在該擴充功能無法使用的地方降級為全文搜尋)。
派發器是無狀態的:沒有按工作階段的工作區繫結。
每個工作區範圍的呼叫都帶有自己的 workspace_id,而存取權取決於
呼叫者的工作區成員身分與角色——而不是取決於是否持有配對金鑰。
在把連接埠暴露到回送以外之前,有兩件事要知道:
- MCP 在主機之外失效即拒絕。 沒有權杖的 MCP 介面只回應回送。繫結
any不會放寬這一點——在你設定一個之前(mcp.setToken,或 設定 → 伺服器 → MCP 伺服器),來自主機之外的請求會被以 “MCP requires a bearer token to answer non-loopback clients” 拒絕。 GET /healthz在設計上未經驗證,它帶萬用字元 CORS,並公佈伺服器的 id、名稱、身分指紋與建置版本。用戶端需要該指紋來固定伺服器,因此這是刻意的——但這確實意味著任何可觸達的cc_server都會向任何查問者披露這麼多。