Deploy
A dox deployment is one Node process serving static files, with its state in a dox-data/ folder next to the code directory. There is no database to provision and no build step at start-up.
What actually ships
system/server.js the process (imports .ts directly — needs Node 22.6+)
icanvas/ the canvas HTML
event/ graph.json + sdk.js
app/*/dist built front ends
app/*/manifest.json the registry entries
app/*/server optional routers
dox-data/ is created on first run beside the code directory, never inside it — which is what makes upgrading a matter of replacing one folder.
Option A — run from a checkout
git clone https://github.com/dox012/dox.git /srv/dox
cd /srv/dox
npm install
npm run build --workspaces --if-present
DOX_DATA_DIR=/srv/dox-data PORT=3000 node dox.mjs
dox.mjs also tries to open a browser; on a headless box that attempt is silent and harmless.
Option B — build a release directory
node pack.mjs # → release/<platform>/
node pack.mjs --slim # same, but does not bundle a Node runtime
The full build copies a Node binary into launcher/, so the target machine needs nothing installed. The bundled runtime dominates the download: a slim Linux build is about 3 MB, the same build with a Node runtime lands around 60–90 MB depending on platform. --slim leaves it out and is the right choice on a server that already has Node 22.6+.
On Linux the release includes launcher/deploy.sh, which starts the server in the background, waits for /api/health, and prints the command to reach it from your laptop.
Option C — borrow a Node you already have
If the machine has no system Node but does run code-server or similar, its bundled runtime usually works: it is a real Node binary and recent versions support type stripping.
/path/to/code-server/lib/node system/server.js
Check first:
/path/to/code-server/lib/node -e "console.log(process.version, process.features.typescript)"
# v22.21.1 strip
Ports and binding
The server listens on 127.0.0.1 only, on PORT (default 3000). It is not reachable from another machine by design — an agent with bash access should not be exposed by accident.
Three ways to get to it:
SSH tunnel — simplest, nothing to configure:
ssh -N -L 3000:127.0.0.1:3000 user@server
# then open http://localhost:3000/
Reverse proxy — put nginx or Caddy in front, with authentication:
server {
listen 443 ssl;
server_name dox.example.com;
location / {
auth_basic "dox";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_buffering off; # chat responses stream
}
}
Streaming matters: the agent and the shell use chunked newline-delimited JSON, so buffering proxies must be told not to buffer.
Under code-server — if code-server already serves your box, dox is reachable at /proxy/3000/. The front end uses relative paths, so it survives being mounted under a prefix.
Security
Whatever fronts dox should require a login. Anyone who can click in the workspace can:
- run arbitrary shell commands through the agent,
- read and write any file the process can reach,
- read the model API key out of
dox-data/agent/config.json.
Treat it like an SSH session, because it is one with a nicer interface.
Data and upgrades
State is never inside the code directory. By default it sits beside it:
/srv/dox/ code — safe to replace
/srv/dox-data/ config, sessions
An upgrade is therefore: stop, replace the code directory, start. The data folder is untouched. The reasoning behind this layout is in Architecture. Sessions (.sss) and config.json are plain files — back them up by copying the folder.
On clusters and containers
What matters is not the OS convention but the persistence boundary: anything outside the mounted volume is gone when the container restarts, including the root filesystem and $HOME.
| Layout | Default data path | Verdict |
|---|---|---|
| Code and data on the same volume | ../dox-data |
default works |
Code built into the image, volume mounted at /data |
/dox-data on the ephemeral root |
set DOX_DATA_DIR |
$HOME not persisted |
~/.local/share/dox |
never use it |
DOX_DATA_DIR=/data/dox node system/server.js
Point it at the mounted volume, not at whatever the platform calls "home".
Verifying a deployment
curl -s http://127.0.0.1:3000/api/health # {"ok":true,"app":"dox"}
Then open /. That is the only entry point — there is no other path to remember.
Troubleshooting
| Symptom | Cause |
|---|---|
Cannot GET / |
The server is up but the static files are missing — check that icanvas/index.html shipped. |
| App menu is empty | dist/ was not built before packaging. Rebuild and restart. |
| Chat streams nothing through a proxy | Response buffering. Disable it for the location. |
unable to get local issuer certificate |
The runtime cannot see system CAs. Start Node with --use-system-ca. |
| Sessions disappear after redeploy | The build read a different data directory. Check DOX_DATA_DIR, or that dox-data/ sits beside the code. |