Skip to content

Server configuration

Every zidane-server command, flag, environment variable and server.json key with its default, generated from source.

The site build generates the tables from the server's source: the help screen, the configuration loader and the Docker image. Each setting comes from the first source that has it:

  1. a flag of zidane-server start,
  2. a ZIDANE_SERVER_* environment variable,
  3. a key in <data dir>/server.json,
  4. the default.

The server validates everything at start and names the source of a bad value. It never reads the generic PORT variable.

Text
zidane server: Invalid ZIDANE_SERVER_PORT: expected a port (an integer from 0 to 65535).

Commands#

zidane server <command> and zidane-server <command> are the same program.

zidane server commands
CommandDescription
zidane server start [flags]Serve this machine's chat host to remote windows.
zidane server token create --name <name>Create a device token (printed once).
zidane server token listList tokens (never their secrets).
zidane server token revoke <id|name>Revoke a token. Its live connections drop.
zidane server token generatePrint a fresh token without storing it (for ZIDANE_SERVER_BOOTSTRAP_TOKEN).
zidane server pairPrint a one-time code that logs a browser in to the web app.
zidane server machine invitePrint a one-time join code that adds a machine (--name, --ttl).
zidane server machines [--json]List the machines and whether they are online (over the unix socket).
zidane server health [--timeout <ms>]Probe the running server over its unix socket (exit 0 when healthy).
zidane server health --httpProbe GET /healthz on the server's port instead (no socket needed).
zidane server wait-idle [--timeout <ms>]Wait until no run or background task is in flight (before a restart).
zidane server backup --out <file|->Archive the server's state as a tar.gz while it runs (- for stdout).
zidane server setupInstall or change zidane-server on this machine (zidane server setup --help).
zidane server doctor [--fix]Check a server that setup installed.
zidane server channels checkCheck the channels config offline (exit 1 on errors).
zidane server channels statusList the running server's channel integrations.
zidane server channels reloadMake the running server re-read its channels config.
zidane server start --no-channelsNever start channels (as ZIDANE_NO_CHANNELS=1).
zidane-server --versionPrint the version (the standalone binary).

Start flags#

zidane server start flags
FlagDescription
--host <addr>Interface to listen on (default 127.0.0.1).Also ZIDANE_SERVER_HOST or host in server.json.
--port <n>Port (default 4280, 0 picks a free one).Also ZIDANE_SERVER_PORT or port in server.json.
--tls-cert <file>PEM certificate: serve wss:// (with --tls-key).Also ZIDANE_SERVER_TLS_CERT or tlsCert in server.json.
--tls-key <file>PEM private key.Also ZIDANE_SERVER_TLS_KEY or tlsKey in server.json.
--behind-proxyA TLS-terminating proxy fronts the server (required off loopback without TLS). Every upgrade must then carry X-Forwarded-Proto: https.Also ZIDANE_SERVER_BEHIND_PROXY or behindProxy in server.json.
--trusted-proxies <l>With --behind-proxy: the proxies' addresses / CIDRs (comma-separated). Upgrades from any other peer are refused.Also ZIDANE_SERVER_TRUSTED_PROXIES or trustedProxies in server.json.
--name <name>Host name shown to clients (default: the machine's).Also ZIDANE_SERVER_NAME or name in server.json.
--socket <path|off>Unix socket for local tools (default <data dir>/server.sock).Also ZIDANE_SERVER_SOCKET or socket in server.json.
--workspace-root <dir>Where session folders may be. Repeatable, the first is the default (default <data dir>/workspaces, env: path-delimited list).Also ZIDANE_SERVER_WORKSPACE_ROOTS or workspaceRoots in server.json.
--allow-as-machineLend this server as a machine to its clients' computers (local@<server>, docs/MACHINES.md): a client token then runs commands in the workspace roots through it, as it already can with a terminal. Default off.Also ZIDANE_SERVER_ALLOW_AS_MACHINE or allowAsMachine in server.json.
--no-remote-installsRefuse installs, updates and removals of skills, extensions and MCP servers from clients (allowRemoteInstalls, default on, audited).Also ZIDANE_SERVER_ALLOW_REMOTE_INSTALLS or allowRemoteInstalls in server.json.
--no-cloneRefuse clones into the workspace roots from clients (allowClone, default on: any client token may clone).Also ZIDANE_SERVER_ALLOW_CLONE or allowClone in server.json.
--no-create-foldersRefuse new folders in the workspace roots from clients (allowCreateFolders, default on: any client token may create one).Also ZIDANE_SERVER_ALLOW_CREATE_FOLDERS or allowCreateFolders in server.json.
--auto-updateInstall new releases on its own (release binaries): runs pause at a step and continue after the restart. Default off.Also ZIDANE_SERVER_AUTO_UPDATE or autoUpdate in server.json.
--webServe the web app at / (log in with a code from "zidane server pair"). Browsers on the server's own origin are admitted. Default off.Also ZIDANE_SERVER_WEB or web in server.json.
--no-webDon't serve the web app (overrides ZIDANE_SERVER_WEB / server.json).
--web-root <dir>The web app to serve (a directory with an index.html, default the one bundled with the server, web-dist/).Also ZIDANE_SERVER_WEB_ROOT or webRoot in server.json.
--mcpServe MCP at /mcp, so an MCP client (Claude Code, Cursor) drives this server's sessions with a token as the bearer. Default off.Also ZIDANE_SERVER_MCP or mcp in server.json.
--no-mcpDon't serve MCP (overrides ZIDANE_SERVER_MCP / server.json).
--verboseLog connections and requests to stderr.Also ZIDANE_SERVER_VERBOSE or verbose in server.json.
--exposure <mode>private (default) or public. Public refuses remote installs, machine lending, a bootstrap token, other browser origins next to the web app, and pairing codes that live longer than 10 minutes.Also ZIDANE_SERVER_EXPOSURE or exposure in server.json.
--channels-port <n>Also serve channel webhooks and /healthz alone on this port (same host and TLS, 0 picks a free one). Everything else there is a 404.Also ZIDANE_SERVER_CHANNELS_PORT or channelsPort in server.json.
--env-file <file>Read KEY=value lines into the environment before the config loads. Variables already set win. The file must be private (chmod 600).

Token and health flags#

Token and health flags
FlagDescription
--data-dir <dir>Storage root, as ZIDANE_STORAGE_DIR (server files live in <dir>/.zidane). Also ZIDANE_SERVER_DATA_DIR.
--scope <scope>Token scope. A window: chat (sessions, runs and tool approvals) or admin (also the server's settings: everything, the default, also named "client"). Or machine: lends its execution with "zidane machine share" (docs/MACHINES.md). For pair: chat or admin (default chat).
--expires <duration>(token create) How long the token works: 12h, 30d, 90d, 1y (also m and w), or never (the default). An expired token is refused and its connections drop.
--ttl <duration>(pair, machine invite) How long the code works: 30s to 1h, as 90s, 10m or 1h (a bare number is minutes). Default 10m.
--name <label>Names the browser's token "browser: <label>". (machine invite) Names the machine's token. Without it, the machine gives its own name.For pair.
--jsonPrint JSON: { serverVersion, machines }.For machines.
--socket <path>The server's unix socket, when not the default (health, wait-idle, machines).
--out <file|->Where the tar.gz goes (mode 0600, not inside a directory it archives). - writes it to stdout.For backup.
--include-workspacesAlso archive the workspace roots (the projects).For backup.
--httpProbe http(s)://<host>:<port>/healthz (a wildcard host on loopback).For health.

Environment variables#

An Image value is what server/Dockerfile sets. The other variables keep their default in the image.

zidane-server environment variables
VariableDefaultDescription
ZIDANE_SERVER_DATA_DIRZidane's user dirImage: /dataStorage root, as ZIDANE_STORAGE_DIR (server files live in <dir>/.zidane).
ZIDANE_SERVER_HOST127.0.0.1Image: 0.0.0.0Interface to listen on. Off loopback it needs TLS or behindProxy.
ZIDANE_SERVER_PORT4280Port to listen on; 0 picks a free one.
ZIDANE_SERVER_TLS_CERTNonePEM certificate: serve wss:// (with --tls-key).
ZIDANE_SERVER_TLS_KEYNonePEM private key.
ZIDANE_SERVER_BEHIND_PROXYfalseImage: 1A TLS-terminating proxy fronts the server: every upgrade must then carry X-Forwarded-Proto: https.
ZIDANE_SERVER_NAMEThe machine's hostnameHost name reported to clients. Default: the machine's.
ZIDANE_SERVER_HEARTBEAT_MS20000Interval of the server's WebSocket pings, in ms; a connection that misses two in a row is dropped. 0 disables.
ZIDANE_SERVER_MAX_MESSAGE_BYTES33554432Largest incoming message in bytes: a bigger frame closes the connection (1009), a bigger reply is answered with a ResponseTooLarge error.
ZIDANE_SERVER_RATE_LIMIT50Requests per second on one connection; 0 disables.
ZIDANE_SERVER_RATE_BURST200Burst size of that limit: how many may arrive at once.
ZIDANE_SERVER_ALLOWED_ORIGINSNoneBrowser origins allowed to connect; empty refuses every browser.
ZIDANE_SERVER_SOCKET<data dir>/server.sockUnix socket for local tools (default <data dir>/server.sock).
ZIDANE_SERVER_TRUSTED_PROXIESNoneImage: privateBehind a proxy: the only peers believed (IPs, CIDRs, or private); empty believes any peer.
ZIDANE_SERVER_UPGRADE_RATE_LIMIT5Upgrades per second from one client address; 0 disables.
ZIDANE_SERVER_UPGRADE_RATE_BURST30Burst size of that limit: how many may arrive at once.
ZIDANE_SERVER_MAX_CONNECTIONS_PER_TOKEN16Open connections one token may hold; past it, an upgrade gets a 429.
ZIDANE_SERVER_MAX_CONNECTIONS_PER_ADDRESS32Open authenticated connections per client address; past it, an upgrade gets a 429.
ZIDANE_SERVER_WORKSPACE_ROOTS<data dir>/workspacesImage: /data/workspacesWhere session folders may be (absolute; the first is the default for a session created without one). Default <data dir>/workspaces.
ZIDANE_SERVER_DRAIN_TIMEOUT_MS8000Bound on draining the host's runs at shutdown (SIGTERM).
ZIDANE_SERVER_ALLOW_AS_MACHINEfalseLend this server as a machine to its clients' local hosts (local@<server>, docs/MACHINES.md § Reverse direction). Default off.
ZIDANE_SERVER_ALLOW_REMOTE_INSTALLStrueClients may install, update and remove skills, extensions and MCP servers in this server user's scope (audited). Default on.
ZIDANE_SERVER_ALLOW_CLONEtrueClients may clone repositories into the workspace roots (git.clone). Default on.
ZIDANE_SERVER_ALLOW_CREATE_FOLDERStrueClients may create folders in the workspace roots (fs.mkdir). Default on.
ZIDANE_SERVER_VERBOSEfalseLog every connection, authentication, refusal and disconnect to stderr ([server] and [ipc-ws] lines). Default off.
ZIDANE_SERVER_COMPRESS_LARGE_MESSAGESfalseCompress big outgoing WebSocket messages (64 KiB and up, e.g. transcript pages) for clients that accept it (permessage-deflate). Saves bandwidth on slow links, costs event-loop time per big message. Default off.
ZIDANE_SERVER_AUTO_UPDATEfalseInstall new releases on its own, pausing and resuming runs (./auto-update). Release binaries only.
ZIDANE_SERVER_AUTO_UPDATE_INTERVAL_MINUTES30How often it checks for a release.
ZIDANE_SERVER_WEBfalseServe the web app at / (a pairing code logs a browser in: zidane server pair), and admit browsers on the server's own origin. Default off.
ZIDANE_SERVER_WEB_ROOTNoneThe web app's directory (it must hold an index.html). Default: the app bundled with the server (web-dist/). Relative paths in server.json resolve against the data dir.
ZIDANE_SERVER_MCPfalseServe MCP at /mcp (Streamable HTTP, a token as the bearer): an MCP client (Claude Code, Cursor, another agent) drives this server's sessions with the sessions and interactions tools. Default off.
ZIDANE_SERVER_EXPOSUREprivatepublic: the server is reachable from the internet. Start then refuses remote installs, machine lending, a bootstrap token, and other browser origins next to the web app; pair caps a code's lifetime at 10 minutes. Default private.
ZIDANE_SERVER_CHANNELS_PORTNoneA second listener on the same host that serves only channel webhooks and /healthz; 0 picks a free port.
ZIDANE_SERVER_BOOTSTRAP_TOKENNoneA token from token generate, stored at start as the client token "bootstrap" (a new value replaces it). Revoke "bootstrap" once device tokens exist.
ZIDANE_SERVER_BOOTSTRAP_TOKEN_FILENoneA file holding it (a mounted secret, which keeps it out of the environment). Not both.

zidane-server start --no-channels, or ZIDANE_NO_CHANNELS=1, never starts channels. The channels check, status and reload commands are in channels.

Booleans are 1, true, yes, on or 0, false, no, off. Lists are comma-separated (workspace roots are separated like PATH). An empty variable counts as unset.

server.json#

<data dir>/server.json uses JSON types (numbers, booleans, arrays), not strings. An unknown key is a boot error. Relative paths resolve against the data dir.

server.json keys
KeyDefaultDescription
host127.0.0.1stringInterface to listen on. Off loopback it needs TLS or behindProxy.
port4280numberPort to listen on; 0 picks a free one.
tlsCertNonestringPEM certificate: serve wss:// (with --tls-key).
tlsKeyNonestringPEM private key.
behindProxyfalsebooleanA TLS-terminating proxy fronts the server: every upgrade must then carry X-Forwarded-Proto: https.
nameThe machine's hostnamestringHost name reported to clients. Default: the machine's.
heartbeatMs20000numberInterval of the server's WebSocket pings, in ms; a connection that misses two in a row is dropped. 0 disables.
maxMessageBytes33554432numberLargest incoming message in bytes: a bigger frame closes the connection (1009), a bigger reply is answered with a ResponseTooLarge error.
rateLimitperSecond: 50, burst: 200{ perSecond, burst }Requests per connection: a token bucket of perSecond (0 disables) and burst. Over it, a RateLimited error.
allowedOriginsNonestring[]Browser origins allowed to connect; empty refuses every browser.
socket<data dir>/server.sockstringUnix socket for local tools (default <data dir>/server.sock).
trustedProxiesNonestring[]Behind a proxy: the only peers believed (IPs, CIDRs, or private); empty believes any peer.
upgradeRateLimitperSecond: 5, burst: 30{ perSecond, burst }Upgrades per client address.
maxConnectionsPerToken16numberOpen connections one token may hold; past it, an upgrade gets a 429.
maxConnectionsPerAddress32numberOpen authenticated connections per client address; past it, an upgrade gets a 429.
workspaceRoots<data dir>/workspacesstring[]Where session folders may be (absolute; the first is the default for a session created without one). Default <data dir>/workspaces.
drainTimeoutMs8000numberBound on draining the host's runs at shutdown (SIGTERM).
allowAsMachinefalsebooleanLend this server as a machine to its clients' local hosts (local@<server>, docs/MACHINES.md § Reverse direction). Default off.
allowRemoteInstallstruebooleanClients may install, update and remove skills, extensions and MCP servers in this server user's scope (audited). Default on.
allowClonetruebooleanClients may clone repositories into the workspace roots (git.clone). Default on.
allowCreateFolderstruebooleanClients may create folders in the workspace roots (fs.mkdir). Default on.
verbosefalsebooleanLog every connection, authentication, refusal and disconnect to stderr ([server] and [ipc-ws] lines). Default off.
compressLargeMessagesfalsebooleanCompress big outgoing WebSocket messages (64 KiB and up, e.g. transcript pages) for clients that accept it (permessage-deflate). Saves bandwidth on slow links, costs event-loop time per big message. Default off.
autoUpdatefalsebooleanInstall new releases on its own, pausing and resuming runs (./auto-update). Release binaries only.
autoUpdateIntervalMinutes30numberHow often it checks for a release.
webfalsebooleanServe the web app at / (a pairing code logs a browser in: zidane server pair), and admit browsers on the server's own origin. Default off.
webRootNonestringThe web app's directory (it must hold an index.html). Default: the app bundled with the server (web-dist/). Relative paths in server.json resolve against the data dir.
mcpfalsebooleanServe MCP at /mcp (Streamable HTTP, a token as the bearer): an MCP client (Claude Code, Cursor, another agent) drives this server's sessions with the sessions and interactions tools. Default off.
exposureprivatestringpublic: the server is reachable from the internet. Start then refuses remote installs, machine lending, a bootstrap token, and other browser origins next to the web app; pair caps a code's lifetime at 10 minutes. Default private.
channelsPortNonestringA second listener on the same host that serves only channel webhooks and /healthz; 0 picks a free port.
server.json
{
  "host": "0.0.0.0",
  "behindProxy": true,
  "trustedProxies": ["10.0.1.0/24"],
  "name": "build-box",
  "workspaceRoots": ["/srv/code", "workspaces"],
  "allowedOrigins": ["https://agents.example.com"],
  "rateLimit": { "perSecond": 100, "burst": 400 }
}

Exposure, webhooks and the env file#

exposure says whether the internet can reach the port of the clients. It is private (the default) or public. With public, the server refuses remote installs, lending itself as a machine (running another host's commands) and a bootstrap token. It also refuses other browser origins next to the web app, and pairing or join codes that live longer than 10 minutes (exposure).

channelsPort (--channels-port, ZIDANE_SERVER_CHANNELS_PORT) opens a second port. That port serves channel webhooks and /healthz only, and answers 404 to the rest. Make that port public. Keep the port of the clients private.

--env-file <file> on zidane-server start reads an env file, a file of KEY=value lines, before the configuration loads. A variable that is already set wins. The file must be mode 600. zidane machine share --env-file reads the ZIDANE_MACHINE_* variables of a machine the same way (servers and machines).

Data dir#

--data-dir <dir> (or ZIDANE_SERVER_DATA_DIR) sets the storage root, like ZIDANE_STORAGE_DIR for the rest of zidane (folders). Everything, sessions included, lands in <dir>/.zidane. Without it, the server uses zidane's usual folders for its user. The image sets /data (file list).

Provider keys#

The server's agents read provider keys from its environment, under the same names as on a laptop (the list). A key saved from a window into the server's credentials.json wins over the variable. The variables stay in the agents' environment, so their tools can read them.