執行無介面伺服器
在一台持續開機的機器上執行 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>它會印出一組代碼與一個網址,讓你在另一台裝置上核准;它會把重新整理權杖存放
在伺服器端,然後結束。原始碼建置不會隨附 Google 用戶端,因此 id 與密鑰這兩個
環境變數是必要的——沒有 --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)。
只有在無法解析出任何家目錄或應用程式資料目錄時,才會使用相對於目前工作目錄的
.cc_server。
伺服器提供哪些服務
標題為「伺服器提供哪些服務」的章節cc_server 是整個產品介面,而不是其中一部分:儲存庫 RPC 資料路徑與訂閱、
位於同一連接埠上 POST /mcp 與 GET /sse 的 MCP 工具端點、傳入的 webhook、
媒體與字型代理、單一登入回呼、機群租約協定、每 30 分鐘排程的伺服器端 RSS
抓取,以及向量搜尋(sqlite_vector 擴充功能會註冊為行程全域的自動擴充功能,
只有在該擴充功能無法使用時才降級為全文搜尋)。
派送器是無狀態的:沒有逐工作區的工作階段繫結。
每一項以工作區為範圍的呼叫都攜帶自己的 workspace_id,存取權由呼叫者的工作區
成員資格與角色決定——而不是持有配對金鑰。
在你把連接埠開放至回送以外的範圍之前,有兩件事要知道:
- MCP 在主機外會失效即關閉。 沒有權杖的 MCP 介面只回應回送。繫結
any並不會擴大範圍——來自主機外的請求會遭到拒絕,並附上「MCP requires a bearer token to answer non-loopback clients」,直到你設定一個權杖(mcp.setToken,或 設定 → 伺服器 → MCP 伺服器)。 GET /healthz依設計不需驗證,具有萬用字元 CORS,並會公布伺服器的 id、名稱、身分指紋與建置版本。用戶端需要指紋才能釘選伺服器,因此這是刻意的——但這也確實表示任何可觸達的cc_server都會向任何詢問的人揭露這麼多資訊。