Deployment & Operations
aiod runs in the foreground by default and can be handed to a process supervisor to run unattended. As a single binary, it exposes /health and /v1/capabilities as health checks.
This page follows the deployment flow: install the binary, configure the supervisor and the API key, wire up the health checks, then logs, environment variables, and common troubleshooting.
Place the binary
The install script downloads the build for the machine, verifies it against the release's SHA256SUMS, and installs it. Pin the version a deployment is built on and put the binary where the supervisor expects it:
Add AIOD_WITH_COMPUTER_USE=1 on a host that runs the desktop worker. Every release directory (/v<version>/<platform>/) also carries the raw binaries and SHA256SUMS for an image build that fetches them itself.
Pick the platform directory that matches the target platform: linux-x86_64, linux-arm64, linux-riscv64, or windows-x86_64 (aiod.exe). latest/<platform>/aiod always points at the newest stable release.
Pin v<version>/<platform>/aiod for a specific one. Release notes and per-file checksums are at Daemon Releases.
Run under a supervisor
aiod start stays in the foreground and has no daemonize flag: the supervisor owns restarts, logging and the environment. Use whatever already manages the host. The examples below all set the service to port 8091.
systemd:
supervisord: the prebuilt images run aiod this way, next to nginx and Chromium:
Image CMD: copy the binary into any image and make it the command:
Docker Compose: the same container with /health as the healthcheck:
Windows: aiod.exe runs as a normal process or registers as an SCM service (Session 0). See Windows.
The daemon always starts, even with no bash, no interpreter, no browser, and no desktop reachable. A missing capability degrades its own routes to 503. It does not block startup.
Require an API key
Pass a key to require authentication on every non-public route:
Clients send Authorization: Bearer <key> or x-api-key: <key>. A WebSocket, download, or other URL that cannot set headers takes ?api_key= instead.
These routes stay open either way:
//health/v1/ping/v1/openapi.json/v2/openapi.json/internal/auth
With no key set, every route is open. Bind to a private interface, or keep the port off any public network.
Health vs. capability readiness
/v1/capabilities is cached for 5 s and refreshed in the background. Add ?refresh=true to force a fresh probe. The domains it reports are files, exec, code_interpreter, browser, and computer.
Restart on a failing /health. Gate traffic on /v1/capabilities, not on /health alone.
A healthy process can still report a degraded or absent capability:
- no bash on the host
- no interpreter
- no reachable Chromium
- no desktop
Check both directly:
Logs
aiod writes structured JSON to stdout, one line per request. Each line is tagged HTTP_REQUEST with method, path, status, duration_ms, logid, and client_ip.
Point the container log driver or supervisor at stdout. There is no separate log file to tail. AIO_RUST_LOG_LEVEL (default info) controls verbosity.
Environment variables
Every flag has a matching environment variable (--host/AIO_HOST, --port/AIO_PORT, …). The flag wins when both are set.
Troubleshooting
503on/v1/nodejs,/v1/code,/v2/code— no matching interpreter on the host. Installpython3ornode;capabilities.code_interpreter.missingsays what is missing.501on/v1/jupyter— noipykernelimportable and noAIO_JUPYTER_ENDPOINTset. Installipykernel, or pointAIO_JUPYTER_ENDPOINTat a Jupyter server.503on/v1/browser/*— no Chromium atBROWSER_REMOTE_DEBUGGING_HOST:PORT(default127.0.0.1:9222). Start Chromium with--remote-debugging-port=9222.503on/v2/computer/*— thecomputer-useworker is not reachable. Start it; checkAIO_COMPUTER_USE_URL(defaulthttp://127.0.0.1:18100).- Every
/v1/*or/v2/*call answers401—AIO_API_KEYis set. SendAuthorization: Bearer <key>orx-api-key: <key>;?api_key=for WebSocket and downloads. 400on/v1/shell/wsright after connecting —durable=trueorrestore=truewithout asession_id.POST /v1/shell/sessions/create, then attach with?session_id=<id>.
Full request/response details for every route are in the OpenAPI spec the running daemon serves: /v1/openapi.json, /v2/openapi.json. The v2 reference is also published as the API Reference. Kubernetes-specific guidance is in Kubernetes.