Server Configuration
This document is a startup and configuration guide for the server, focusing on answering three questions:
- How to start it (local / cloud / desktop forms)
- Whether a public network is required (Conclusion: the server itself does not need it; only the REST API needs it when required)
- How to configure cloud access (connect to the Rust gateway to enable remote management)
Prerequisites
| Item | Requirement |
|---|---|
| Node.js | ≥ 18.17 (20+ recommended) |
| Model API Key | OpenAI-compatible endpoint (DeepSeek / OpenAI / Ollama / custom) |
| (Optional) Cloud account | Self-hosted Rust gateway + Hub, or use a managed service |
| (Optional) QQ Open Platform bot | Register at q.qq.com |
# 获取代码并安装依赖
pnpm install
# 交互式配置(推荐):LLM 必配,QQ/邮件可选、可跳过
bash scripts/configure-server.sh
# 或手动:复制模板后填写
# cp .env.example .envEnvironment Variables Overview
Write to .env in the project root (or export before startup):
| Variable | Description | Default |
|---|---|---|
DATA_DIR | Data/tenant root directory | ./.zqagent_data |
PORT | REST listening port | 8787 |
HOST | Listening address (set to 0.0.0.0 for public deployment) | 127.0.0.1 |
WORKSPACE | Agent workspace directory | Current directory |
APPROVAL_TIMEOUT_SECONDS | Approval/question pending timeout | 900 |
MAX_ITERATIONS | Maximum iterations per turn | 800 |
OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_REASONING_EFFORT | Model configuration (if OPENAI_MODEL is unset, no model is specified and you need to select it in the console) | — |
TENANT_ID / TENANT_API_KEY / MODEL | Demo tenant automatically created on first startup | demo / Randomly generated on first startup / Default model |
SECRET_KEY | Master key for encrypting notification credentials and similar data | Automatically generated |
FLEET_TOKEN / FLEET_SECRET / FLEET_GATEWAY_URL | Cloud access (usually automatically written to fleet.json when linking with a registration code) | — |
QQ_BOT_APP_ID / QQ_BOT_APP_SECRET / QQ_BOT_SANDBOX | QQ bot (enabled after configuration) | — |
CONTEXT_WINDOW / COMPACTION_THRESHOLD_PCT / COMPACTION_CAP_TOKENS | Long-conversation compaction parameters | Automatic |
Once
SECRET_KEYis set, it is recommended to keep it fixed for the long term: it is used to encrypt tenant signing keys and notification channel credentials. Changing it will invalidate the keys and credentials of old tenants.
Three Deployment Forms
Local / Intranet Operation (Most Recommended, No Public Internet Required)
# 最小可运行(先确认能启动、能对话)
pnpm run server
# 日志:
# zqagent server 监听 http://127.0.0.1:8787
# 已创建演示租户: id=demo apiKey=zk_xxxx(随机生成) model=...
# 完整远程控制(配好 .env 后):
# FLEET_GATEWAY_URL=wss://gw.example.com/ws
# QQ_BOT_APP_ID=... QQ_BOT_APP_SECRET=...
# OPENAI_API_KEY=sk-... OPENAI_MODEL=...
pnpm run serverAfter startup, verify that the service is available:
# 演示租户 apiKey 首次启动随机生成并打印在启动日志里,取出来存进 TOKEN
TOKEN=<启动日志中的 apiKey> # 形如 zk_1f0c...
curl -s http://localhost:8787/healthz # => {"status":"ok"}
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8787/api/v1/sessionsCloud Deployment (When Public REST Access Is Required)
Rent a cloud server and set HOST=0.0.0.0 to expose the port.
# 推荐用 pm2 常驻
npm install -g pm2
HOST=0.0.0.0 pm2 start "pnpm run server" --name zqagent-server
# 安全建议:只对需要的人开放。若 REST 仅自己用,建议不直接暴露公网,
# 改用内网穿透,或用云服务器防火墙限制来源 IP。Desktop Application (macOS / Windows)
The desktop app automatically starts the server locally; no manual startup is required. See Desktop App.
Three Options When Public REST Access Is Required
| Option | Approach | Applicable When |
|---|---|---|
| A. Intranet tunneling (recommended for individuals) | Cloudflare Tunnel (free) or frp/ngrok, mapping a local port to public HTTPS | Home/intranet machines, no need to rent a server |
| B. Cloud server | Deploy directly to a VPS, HOST=0.0.0.0 | Have an existing server, or need long-term stability |
| C. Do not use REST | Use the full gateway path (credentials issued by the control plane), and use REST only on your own computer | Do not want to expose any port at all |
Cloud Access (Rust Gateway)
Once connected, you can remotely manage this node from any device. The node only needs an outbound connection to the gateway (wss://, usually over 443); no public inbound access, no open ports, and no MQTT broker are required.
Option 1: Connect with a Registration Code (Recommended)
Create a one-time registration code in the user center (Hub), then run the following on the node machine:
zqagent link --hub https://hub.example.com --code <注册码>- If a service is already running on the local machine → hot connect (no restart required);
- Otherwise, credentials are written to
{DATA_DIR}/fleet.json, and the nextzqagent servewill connect automatically.
Option 2: Manual Configuration
# .env
FLEET_TOKEN=<高熵随机> # 命名空间标识
FLEET_SECRET=<高熵随机> # 签名密钥(须与网关侧一致)
FLEET_GATEWAY_URL=wss://gw.example.com/ws
SECRET_KEY=<64位hex> # 强烈建议显式设置Verify after startup:
curl -s -H "Authorization: Bearer $ADMIN_API_KEY" \
http://localhost:8787/api/v1/fleet/pairing
# => {"data":{"gatewayUrl":"wss://gw.example.com/ws","fleetToken":"...","fleetSecret":"...","nodeId":"..."}}Success is indicated when the startup log shows “Cloud access: wss://… (node nodeId)” .
Not Connecting to the Cloud
If no FLEET_* is configured, it is a purely local node: all local features work as usual, but the cloud cannot see it. You can run zqagent link at any time to connect.
For gateway-side deployment (keys, TLS, multiple replicas), see the repository’s
docs/rust-gateway-plan.mdanddeploy/k8s/gateway/. For protocol details, seedocs/wire-protocol.md.
Troubleshooting Common Issues
| Symptom | Troubleshooting |
|---|---|
| Node cannot connect to the gateway | Confirm the address is wss://.../ws; the certificate is issued by a CA (not self-signed); the firewall allows 443 |
| Log says “Failed to connect to gateway” | Check the reachability of FLEET_GATEWAY_URL and whether FLEET_SECRET matches the gateway |
| Server does not listen externally | HOST defaults to 127.0.0.1; for public access, set HOST=0.0.0.0 and allow the port |
| QQ gateway connection fails | Check AppID/Secret; whether intents permissions have been applied for; use QQ_BOT_SANDBOX=1 for sandbox |
| Emails cannot be sent | For QQ Mail, use an authorization code (not the login password); secure must match the port (465→true, 587→false) |
Credentials invalid after changing SECRET_KEY | SECRET_KEY should be fixed; changing it invalidates all credentials of old tenants |
