Tovább a tartalomhoz

Headless szerver futtatása

Futtassa a cc_server-t egy folyamatosan bekapcsolt gépen, majd csatlakozzon hozzá az asztali gépéről, egy böngészőből vagy a telefonjáról. A szerver egy tisztán Dartban írt natív bináris — Flutter-motor nélkül —, ezért headless módon fut macOS-en, Linuxon és Windowson. Övé az adatbázis, ő futtatja az ügynököket, és ő tesz meg minden külső API-hívást; a kliensek csak megjelenítenek.

Futtatás Dockerben (előre felépített image-ek)

Szekció neve “Futtatás Dockerben (előre felépített image-ek)”

Minden kiadás közzétesz egy saját üzemeltetésű stacket négy GHCR-image-ből — a háttérszolgáltatást, a két statikus vékonyklienst és az opcionális párosítási relét —, valamint egy külön cc-server-demo image-et a nyilvános demóhoszthoz. A saját üzemeltetésű telepítéshez nem kell kicheckolni a forráskódot. Rögzítsen egy verziócímkét (ghcr.io/samuelalev/<image>:v0.0.1-rc.1), vagy használja a latest címkét.

Image Mi ez Publikál
ghcr.io/samuelalev/cc-server A háttérszolgáltatás: adatbázis, ügynökök, MCP, webhookok -p 9030:9030
ghcr.io/samuelalev/cc-webapp A webes kliens (statikus nginx) -p 8080:8080
ghcr.io/samuelalev/cc-remote A telefonos társalkalmazás PWA-ja (statikus nginx) -p 8081:8080
ghcr.io/samuelalev/cc-signaling-server A WebRTC-párosítási relé (opcionális) -p 8788:8788

A teljes stack egy compose-fájlban:

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:

Néhány dolog, amit érdemes tudni, mielőtt mindezt a loopbacken túlra nyitná:

  • A cc-server image CC_SERVER_INSECURE=1 beállítással indul (a 0.0.0.0-ra kell kötnie, hogy fogadhassa a publikált portra érkező forgalmat), ami csak megbízható hálózaton, TLS-t lezáró fordított proxy — Caddy, Traefik, nginx vagy Cloudflare Tunnel — mögött biztonságos. Ha inkább a folyamaton belül zárná le a TLS-t, csatoljon be egy tanúsítványt, és állítsa be a CC_SERVER_TLS_CERT / CC_SERVER_TLS_KEY értékét (majd törölje a CC_SERVER_INSECURE-t). Minden felülírható a docker run -e … paranccsal vagy a compose environment: blokkjával.

  • A /data az egyetlen állapot. Az SQLite-adatbázisok, a párosított eszközök titkai, a letöltött modellek és a megbeszélések hanganyaga mind a kötetben élnek — készítsen róla biztonsági mentést, és a konténer eldobhatóvá válik.

  • Párosítson egy klienst az image-en belülről az első csatlakozás előtt; ez a konténeres megfelelője a 3. lépésnek:

    Terminál
    docker run --rm -it -v cc_data:/data \
    --entrypoint /app/bin/cc_server ghcr.io/samuelalev/cc-server:latest pair
  • A két kliensimage statikus nginx-hoszt — futásidőben semmit sem kell beállítani; az egyes kliensek csatlakozási űrlapja a szerver URL-t, az eszköz-ID-t és a párosítási kulcsot kéri. A jelzőrelé szintén csak a portját igényli (SIGNALING_HOST / SIGNALING_PORT felülírható); állapotmentes, nem tárol titkokat, és csak tartalék — a telefon loopbacket, LAN-t, tailnetet vagy közvetlen wss:// útvonalat használ, ha valamelyik elérhető, és csak akkor esik vissza a relére, ha egyik sem az. Hagyja ki, ha a kliensei mindig közvetlenül érik el a szervert.

Az útmutató többi része forrásból építi fel a szervert; az itt tárgyalt kapcsolók és viselkedés ugyanazok, amelyeket az image környezeti változói táplálnak.

  • A Dart SDK. Ez a repó az fvm eszközzel rögzíti az SDK-verzióját, ezért minden parancs elé írja oda az fvm-et.
  • Ez a repó kicheckolva.
  • Az a natív eszközkészlet, amelyre az előkészítő szkriptnek szüksége van — Rust/cargo, valamint meson, ninja, pkg-config, git és egy C++-fordító. Minden buildszkript megnevezi, mit nem talál, és hogyan kell telepíteni.
  • Egy elérhető hoszt: loopback a helyi használathoz, vagy TLS-sel védett LAN-/nyilvános cím a távoli kliensekhez.

1. lépés: A natív könyvtárak előkészítése

Szekció neve “1. lépés: A natív könyvtárak előkészítése”

A natív komponensek kötelezőek — nincs csökkentett mód. Minden más előtt építse fel őket a repó gyökeréből:

Terminál
scripts/natives/build_natives.sh

Ez felépíti a rift, fff, a tree-sitter és nyelvtanai, az aec, a lame, a ccpty, a cc_watcher, a cc_inference és a SAML natív komponenst a build/natives/ könyvtárba. A cc_server buildhook újrakibocsátja a bundle-be mindazt, ami ott elő van készítve, így ha kihagyja ezt a lépést, a build vagy egyenesen meghiúsul, vagy — az alábbi kiskapuval — egy olyan bináris születik, amelynek indítás előtti ellenőrzése megtagadja az indulást, és megnevezi a hiányzó könyvtárat.

Terminál
cd apps/cc_server
fvm dart build cli

A bundle a bináris mellett szállítja a libsqlite3-at és az előkészített natív komponenseket — nincs szükség rendszerszintű SQLite-ra és Flutter-motorra. A futtatható fájl a ./build/cli/<os_arch>/bundle/bin/cc_server helyre kerül.

3. lépés: Kliens párosítása az első indítás előtt

Szekció neve “3. lépés: Kliens párosítása az első indítás előtt”

Egy friss adatkönyvtárban nincs párosított eszköz és nincs előre megosztott kulcs, ezért egy kliens párosításikulcs-kérése még nem teljesíthető. Hozzon létre egyet a pair alparanccsal. Ez közvetlenül megírja a global.db és a secrets.json fájlt; egy már futó szerver, amely ugyanazt az adatkönyvtárat szolgálja ki, újraindítás nélkül felveszi az új eszközt:

Terminál
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030

Három értéket ír ki, amelyeket beilleszthet egy kliens csatlakozási űrlapjába:

Connect a thin client (paste into its connect form):
Server ws://localhost:9030/rpc
Device id web-client
Pairing key <a freshly generated key>

Hasznos kapcsolók: --device (alapértelmezés: web-client; az azonosító az eszközszintet is meghatározza — desktop, ios, android, bármi más webes kliens), --label (alapértelmezésben a platform neve plusz e gép hosztneve), --host (az URL-be írandó hoszt, mivel a loopback egy másik gépről nem érhető el) és --client-url. A pair újbóli futtatása lecseréli az adott eszköz kulcsát, és eldobja annak élő munkameneteit. A párosítás soha nem hoz létre munkaterületet: a csatlakozó kliens bevezető folyamata nevezi el és hozza létre az elsőt.

A --client-url kapcsolóval ezen kívül egy terminálból beolvasható QR-kódot is kiír, amely a már kitöltött webes klienst nyitja meg:

Terminál
./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

A cc_server pair által kiállított hitelesítő adat soha nem jár le; az alkalmazásban kiállított viszont mindig 30 nap után lejár. Ha végzett egy CLI-vel kiállított eszközzel, vonja vissza a Beállítások → Ön → Az Ön eszközei alatt.

A loopbacken — ez az alapértelmezés, és minden, amire egy ugyanazon a gépen futó klienshez szükség van:

Terminál
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030

Ahhoz, hogy egy másik gépről elérje, kössön minden hálózati interfészre. A nem loopback címre irányuló, TLS nélküli bind indításkor elutasításra kerül (Refusing to bind non-loopback address … without TLS), ezért adjon meg egy tanúsítványt:

Terminál
./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

Vagy zárja le a TLS-t egy fordított proxyban egy megbízható magánhálózaton, és válassza a mögötte futó, sima szöveges bindet:

Terminál
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \
--bind any --insecure --public-url wss://server.example/rpc

A --insecure figyelmen kívül marad, ha a --tls-cert és a --tls-key is be van állítva — a TLS mindig nyer. A szerver a GET /healthz válaszban insecure: true értékkel jelzi a sima szöveges állapotot, és az ilyen kapcsolatot a kliensek nem biztonságosként jelölik meg.

A szerver a SIGINT/SIGTERM jelig fut, majd tisztán leáll.

Irányítson egy klienst a 3. lépésben kapott szerver URL-re és párosítási kulcsra:

  • Asztali alkalmazás: az első indítás képernyőjén (Hogyan fusson a Control Center?) a Futtatás ebben az alkalmazásban helyett töltse ki a csatlakozási mezőket, vagy később vegye fel a szervert a Beállítások → Szerver → Kapcsolat és állapot alatt. Lásd: Csatlakozás távoli szerverhez.
  • Webes kliens: nyissa meg az app.usectrl.dev címet (vagy a webes build saját példányát), és adja meg a szerver URL-t, az eszköz-ID-t és a párosítási kulcsot.
  • Telefon: párosítsa a Remote alkalmazást egy futó kliensből — lásd: Eszköz párosítása.

6. lépés: Google Calendar csatlakoztatása (opcionális)

Szekció neve “6. lépés: Google Calendar csatlakoztatása (opcionális)”

Ha egy munkaterület naptárát grafikus felület nélkül szeretné szinkronizálni, használja az eszközkódos folyamatot:

Terminál
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>

Kiír egy kódot és egy URL-t, amelyet egy másik eszközön hagyhat jóvá, a refresh tokent szerveroldalon tárolja, majd kilép. Egy forrásból készült build nem tartalmaz Google-klienst, ezért az id és a secret környezeti változó kötelező — nincs --google-client-id kapcsoló. Lásd: Google Calendar csatlakoztatása.

A fent használt kapcsolók azok, amelyekre egy első beállításhoz szükség van. A teljes felület — 23 kapcsoló- és környezetiváltozó-pár, a négy alparancs és az adatkönyvtár felépítése — a cc_server CLI-referenciában található.

A négy, amelyre a legnagyobb valószínűséggel szüksége lesz:

Kapcsoló Alapértelmezés Jelentés
--data-dir az operációs rendszer felhasználónkénti alkalmazásadat-könyvtára Adatbázisok, titkok, modellek és gyorsítótárazott média
--port 9030 TCP-port (0 = ideiglenes)
--bind loopback loopback, vagy any minden interfészhez (TLS-t vagy --insecure-t igényel)
--public-url a bind értékéből származtatva A párosított klienseknek hirdetett RPC URL. Proxy, NAT vagy alagút mögött állítsa be kifejezetten

Az alapértelmezett adatkönyvtár macOS-en ~/Library/Application Support/control-center, Windowson %APPDATA%\control-center, másutt pedig $XDG_DATA_HOME/control-center (ha ez nincs, ~/.local/share/control-center). A munkakönyvtárhoz viszonyított .cc_server csak akkor használatos, ha sem otthoni, sem alkalmazásadat-könyvtár nem oldható fel.

A cc_server a teljes termékfelület, nem annak egy részhalmaza: a repo-RPC adatútvonal és a feliratkozások, az MCP-eszközvégpont a POST /mcp és a GET /sse címen ugyanazon a porton, a bejövő webhookok, a média- és fontproxyk, az egyszeri bejelentkezés visszahívásai, a flotta bérleti protokollja, a szerveroldali RSS-lekérés 30 perces ütemezéssel, valamint a vektoros keresés (a sqlite_vector kiterjesztés folyamatglobális automatikus kiterjesztésként van regisztrálva, és csak ott esik vissza teljes szöveges keresésre, ahol a kiterjesztés nem érhető el).

A diszpécser állapotmentes: nincs munkamenetenkénti munkaterület-kötés. Minden munkaterület-hatókörű hívás a saját workspace_id-jét hordozza, és a hozzáférést a hívó munkaterületi tagsága és szerepe dönti el — nem a párosítási kulcs birtoklása.

Két dolgot érdemes tudni, mielőtt a portot a loopbacken túlra nyitná:

  • Az MCP a hoszton kívül zártan hiúsul meg. A token nélküli MCP-felület csak a loopbackre válaszol. Az any bind ezt nem tágítja ki — a hoszton kívüli kérést a „MCP requires a bearer token to answer non-loopback clients” üzenettel utasítja el, amíg be nem állít egy tokent (mcp.setToken, vagy Beállítások → Szerver → MCP-szerverek).
  • A GET /healthz szándékosan hitelesítés nélküli, helyettesítő karakteres CORS-szal, és közzéteszi a szerver azonosítóját, nevét, identitás-ujjlenyomatát és buildverzióját. A klienseknek szükségük van az ujjlenyomatra a szerver rögzítéséhez, tehát ez szándékos — de azt is jelenti, hogy bármely elérhető cc_server ennyit felfed bárkinek, aki kérdezi.