Langkau ke kandungan

Jalankan pelayan tanpa kepala

Jalankan cc_server pada mesin yang sentiasa hidup, kemudian sambung kepadanya dari desktop, pelayar atau telefon anda. Pelayan ini ialah binari natif Dart tulen — tiada enjin Flutter — jadi ia berjalan tanpa kepala pada macOS, Linux atau Windows. Ia memiliki pangkalan data, menjalankan ejen dan membuat setiap panggilan API luaran; klien hanya memaparkan.

Setiap keluaran menerbitkan tindanan pengehosan sendiri bagi empat imej GHCR — bahagian belakang, dua klien nipis statik dan geganti penggandingan pilihan — berserta imej cc-server-demo yang berasingan untuk hos demo awam. Pemasangan pengehosan sendiri tidak memerlukan semakan keluar sumber. Sematkan tag versi (ghcr.io/samuelalev/<image>:v0.0.1-rc.1) atau ikut latest.

Imej Apanya Menerbitkan
ghcr.io/samuelalev/cc-server Bahagian belakang: pangkalan data, ejen, MCP, webhook -p 9030:9030
ghcr.io/samuelalev/cc-webapp Klien web (nginx statik) -p 8080:8080
ghcr.io/samuelalev/cc-remote PWA pendamping telefon (nginx statik) -p 8081:8080
ghcr.io/samuelalev/cc-signaling-server Geganti penggandingan WebRTC (pilihan) -p 8788:8788

Keseluruhan tindanan sebagai fail 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:

Perkara yang wajar diketahui sebelum anda mendedahkan mana-mana daripada ini melebihi loopback:

  • Imej cc-server membawa CC_SERVER_INSECURE=1 (ia mesti mengikat 0.0.0.0 untuk menerima trafik port yang diterbitkan), yang hanya selamat di belakang proksi songsang penamat TLS — Caddy, Traefik, nginx atau Cloudflare Tunnel — pada rangkaian yang dipercayai. Untuk menamatkan TLS dalam proses sebagai gantinya, lekapkan sijil dan tetapkan CC_SERVER_TLS_CERT / CC_SERVER_TLS_KEY (kemudian nyahset CC_SERVER_INSECURE). Semuanya boleh ditimpa dengan docker run -e … atau blok environment: compose.

  • /data ialah satu-satunya keadaan. Pangkalan data SQLite, rahsia peranti berganding, model yang dimuat turun dan audio mesyuarat semuanya tinggal di dalam volum itu — sandarkannya dan kontena itu menjadi boleh buang.

  • Gandingkan klien dari dalam imej sebelum sambungan pertama, iaitu padanan kontena bagi langkah 3:

    Tetingkap terminal
    docker run --rm -it -v cc_data:/data \
    --entrypoint /app/bin/cc_server ghcr.io/samuelalev/cc-server:latest pair
  • Dua imej klien itu ialah hos nginx statik — tiada apa untuk dikonfigurasikan pada masa jalan; borang sambungan setiap klien menerima URL pelayan, id peranti dan kunci penggandingan anda. Geganti isyarat juga hanya memerlukan portnya (SIGNALING_HOST / SIGNALING_PORT boleh ditimpa); ia tanpa keadaan, tidak menyimpan rahsia dan merupakan pilihan terakhir — telefon menggunakan loopback, LAN, tailnet atau laluan wss:// terus apabila salah satunya boleh dicapai, dan hanya berpaling kepada geganti apabila tiada satu pun. Langkau ia jika klien anda sentiasa mencapai pelayan secara terus.

Selebihnya panduan ini membina pelayan daripada sumber; bendera dan tingkah laku yang diliputinya ialah yang sama yang disuapkan oleh pemboleh ubah persekitaran imej itu.

  • Dart SDK. Repo ini menyematkan SDK-nya dengan fvm, jadi awali setiap perintah dengan fvm.
  • Repositori ini telah disemak keluar.
  • Rantaian alat natif yang diperlukan oleh skrip penyediaan — Rust/cargo, serta meson, ninja, pkg-config, git dan pengkompil C++. Setiap skrip binaan menamakan apa yang tidak dapat ditemuinya dan cara memasangnya.
  • Hos yang boleh dicapai: loopback untuk kegunaan setempat, atau alamat LAN/awam dengan TLS untuk klien jauh.

Natif itu diperlukan — tiada modus terdegradasi. Binanya daripada akar repositori sebelum apa-apa yang lain:

Tetingkap terminal
scripts/natives/build_natives.sh

Ini membina rift, fff, tree-sitter berserta tatabahasanya, aec, lame, ccpty, cc_watcher, cc_inference dan natif SAML ke dalam build/natives/. Cangkuk binaan cc_server memancarkan semula apa sahaja yang disediakan di situ ke dalam bundel, jadi melangkau langkah ini sama ada menggagalkan binaan terus atau — dengan pintu keluar di bawah — menghasilkan binari yang pemeriksaan prabotnya enggan dimulakan dan menamakan pustaka yang hilang.

Tetingkap terminal
cd apps/cc_server
fvm dart build cli

Bundel itu membawa libsqlite3 dan natif yang disediakan di sisi binari — tiada SQLite sistem dan tiada enjin Flutter diperlukan. Boleh laku itu terletak di ./build/cli/<os_arch>/bundle/bin/cc_server.

Langkah 3: Gandingkan klien sebelum permulaan pertama

Bahagian bertajuk “Langkah 3: Gandingkan klien sebelum permulaan pertama”

Direktori data yang baharu tiada peranti berganding dan tiada kunci pra-kongsi, jadi gesaan kunci penggandingan sesuatu klien belum boleh dipenuhi lagi. Tempa satu dengan subperintah pair. Ia menulis global.db dan secrets.json secara terus; pelayan yang sudah menyajikan dir data itu akan mengambil peranti baharu itu tanpa permulaan semula:

Tetingkap terminal
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030

Ia mencetak tiga nilai untuk ditampal ke dalam borang sambungan klien:

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

Bendera yang berguna: --device (lalai web-client; id itu juga memilih tingkat peranti — desktop, ios, android, apa-apa yang lain ialah klien web), --label (lalai kepada nama platform ditambah nama hos mesin ini), --host (hos yang dicetak dalam URL, kerana loopback tidak boleh dicapai dari mesin lain) dan --client-url. Menjalankan pair semula memutar kunci peranti itu dan menggugurkan sesi langsungnya. Penggandingan tidak pernah mencipta ruang kerja: pengenalan klien yang menyambung menamakan dan mencipta ruang kerja pertama.

Dengan --client-url ia juga mencetak kod QR yang boleh diimbas dari terminal dan membuka klien web itu dengan isian yang sudah lengkap:

Tetingkap terminal
./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

Kelayakan yang ditempa oleh cc_server pair tiada tempoh tamat; yang ditempa dalam aplikasi sentiasa tamat tempoh selepas 30 hari. Tarik balik peranti yang ditempa melalui CLI daripada Tetapan → Anda → Peranti anda apabila anda sudah selesai dengannya.

Pada loopback — lalai dan semua yang anda perlukan untuk klien pada mesin yang sama:

Tetingkap terminal
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030

Untuk mencapainya dari mesin lain, ikat setiap antara muka. Ikatan bukan loopback tanpa TLS ditolak pada permulaan (Refusing to bind non-loopback address … without TLS), jadi sediakan sijil:

Tetingkap terminal
./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

Atau tamatkan TLS dalam proksi songsang pada rangkaian persendirian yang dipercayai dan pilih ikatan teks biasa di belakangnya:

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

--insecure diabaikan apabila --tls-cert dan --tls-key kedua-duanya ditetapkan — TLS sentiasa menang. Pelayan mengiklankan keadaan teks biasa itu sebagai insecure: true dalam GET /healthz dan klien memberi lencana tidak selamat pada sambungan sedemikian.

Pelayan berjalan sehingga SIGINT/SIGTERM, kemudian menutup dengan bersih.

Arahkan klien kepada URL pelayan dan kunci penggandingan daripada langkah 3:

  • Aplikasi desktop: pada skrin larian pertama (Bagaimana Control Center patut berjalan?) isi medan sambungan dan bukan Jalankan dalam apl ini, atau tambah pelayan itu kemudian di Tetapan → Pelayan → Sambungan & status. Lihat Sambung ke pelayan jauh.
  • Klien web: buka app.usectrl.dev (atau salinan binaan web anda sendiri) dan masukkan URL pelayan, id peranti dan kunci penggandingan.
  • Telefon: gandingkan aplikasi Remote daripada klien yang sedang berjalan — lihat Gandingkan peranti.

Untuk menyegerakkan kalendar ruang kerja tanpa GUI, gunakan aliran kod peranti:

Tetingkap terminal
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>

Ia mencetak kod dan URL untuk diluluskan pada peranti lain, menyimpan token penyegaran di sisi pelayan dan keluar. Binaan daripada sumber tidak menyertakan klien Google, jadi pemboleh ubah persekitaran id dan rahsia itu diperlukan — tiada bendera --google-client-id. Lihat Sambungkan Google Calendar.

Bendera yang digunakan di atas ialah yang diperlukan oleh persediaan pertama. Permukaan lengkapnya — 23 pasangan bendera dan pemboleh ubah persekitaran, empat subperintah serta susun atur direktori data — ada dalam rujukan CLI cc_server.

Empat yang paling mungkin anda perlukan:

Bendera Lalai Maksud
--data-dir dir data aplikasi setiap pengguna OS Pangkalan data, rahsia, model dan media cache
--port 9030 Port TCP (0 = efemeral)
--bind loopback loopback, atau any untuk setiap antara muka (memerlukan TLS atau --insecure)
--public-url diterbitkan daripada ikatan URL RPC yang diiklankan kepada klien berganding. Tetapkan ini secara eksplisit di belakang proksi, NAT atau terowong

Dir data lalai ialah ~/Library/Application Support/control-center pada macOS, %APPDATA%\control-center pada Windows dan $XDG_DATA_HOME/control-center (atau ~/.local/share/control-center) di tempat lain. .cc_server yang relatif kepada cwd hanya digunakan apabila tiada direktori home atau data aplikasi dapat diselesaikan.

cc_server ialah keseluruhan permukaan produk, bukan subset: laluan data repo-RPC dan langganannya, titik akhir alat MCP pada POST /mcp dan GET /sse pada port yang sama, webhook masuk, proksi media dan fon, panggil balik daftar masuk tunggal, protokol pajakan armada, pengambilan RSS di sisi pelayan pada jadual 30 minit dan carian vektor (sambungan sqlite_vector didaftarkan sebagai sambungan auto global proses, merosot kepada carian teks penuh hanya di tempat sambungan itu tidak tersedia).

Penghantar itu tanpa keadaan: tiada pengikatan ruang kerja bagi setiap sesi. Setiap panggilan berlingkup ruang kerja membawa workspace_id sendiri dan akses ditentukan oleh keahlian dan peranan ruang kerja pemanggil — bukan dengan memegang kunci penggandingan.

Dua perkara yang wajar diketahui sebelum anda mendedahkan port itu melebihi loopback:

  • MCP gagal secara tertutup di luar hos. Permukaan MCP tanpa token hanya menjawab loopback. Mengikat any tidak meluaskannya — permintaan dari luar hos ditolak dengan “MCP requires a bearer token to answer non-loopback clients” sehingga anda mengkonfigurasikan satu (mcp.setToken, atau Tetapan → Pelayan → Pelayan MCP).
  • GET /healthz tidak disahkan secara reka bentuk, dengan CORS kad bebas dan menerbitkan id, nama, cap jari identiti serta versi binaan pelayan. Klien memerlukan cap jari itu untuk menyematkan pelayan, jadi ini memang disengajakan — tetapi ia bermakna mana-mana cc_server yang boleh dicapai mendedahkan sebanyak itu kepada sesiapa yang bertanya.