You don’t need to understand the technical details to use this feature. The configuration examples below are copy-paste ready.
Automated setup
The repository includes a setup script that creates directories, generates a gateway token, builds the Docker image, and starts the daemon. This is the recommended way to get started.1
Clone the repository
2
Configure Compose and credentials
Copy the included Compose settings template:Keep persistent credentials in the mounted daemon environment file (the
default Add the credentials required by your chosen provider, for example
COMIS_ENV_FILE is ~/.comis/.env):ANTHROPIC_API_KEY=... or OPENAI_API_KEY=.... OAuth and local keyless
providers do not need a static provider key. If you change COMIS_ENV_FILE
in the project-root .env, edit that target instead.3
Run the setup script
- Creates the data and config directories (both
~/.comisby default) - Generates a gateway authentication token (or reuses an existing one)
- Writes token and network settings to
COMIS_ENV_FILE - Creates a schema-valid
config.yamlwith authenticated gateway, logging, and memory paths - Builds the Docker image from the included
Dockerfile - Prepares data and config ownership for the container’s non-root user (UID 1000)
- Starts the
comis-daemonservice and waits for its health check to pass
4
Verify
Confirm the daemon is healthy:Expected response:
Browser tool (optional)
The published image is browser-free. To use the agent browser tool, rebuild from the repo with one of three build args mirroring the bare-VPS install flags. Image-size impact in parentheses./usr/local/bin/comis-entrypoint.sh) starts Xvfb on :99 automatically when the image was built with COMIS_WITH_XVFB=1. It verifies the X11 socket before starting the daemon and exits if the virtual display cannot start. The daemon’s findChrome() probes ~/.cloakbrowser/chromium-*/chrome first, so when the cloak binary is baked in it wins over stock Chrome with no config change.
Run the CloakBrowser image identically to the no-browser one — same volumes, same ports, same environment variables:
Alternative: installer-based image
The repo also shipsDockerfile.install. It packs the local workspace and runs
the installer’s non-interactive, non-root package-install path inside Ubuntu
24.04. This exercises package installation and selected browser-provisioning
branches, but skips interactive setup, initialization, service management,
dedicated-user creation, and the public-registry download path.
Dockerfile is the primary multi-stage image path.
Dockerfile.install is a focused installer validation image, not a parity image
for a managed host.
See agent-tools/browser for the browser-tool security model.
Optional services
The daemon is the only service that starts by default. The web dashboard and CLI are available as Docker Compose profiles.Web dashboard
Start the Nginx-served web UI on port 8080:http://localhost:8080 in your browser. The dashboard proxies API
calls and WebSocket connections to the daemon automatically.
CLI
Run one-shot CLI commands against the running daemon:127.0.0.1:4766 without extra configuration.
Stopping and updating
Deploying on a VPS
The supplied Compose file and quick-start examples bind the host port to127.0.0.1 by default. If you omit the host address (-p 4766:4766) or set
the host-side bind to 0.0.0.0, a VPS may expose the gateway to the public
internet. Choose an intentional posture below before changing the loopback
default.
Recommended: loopback bind + reverse proxy
Bind the host port to loopback only and put nginx (or Caddy/Traefik) in front to terminate TLS:docker-compose.yml:
http://127.0.0.1:4766 (HTTP) and
http://127.0.0.1:4766/ws (WebSocket). See
Operations: Reverse Proxy for full nginx /
Caddy snippets with WebSocket upgrade headers.
Acceptable: direct exposure + token auth + firewall
If you don’t want a reverse proxy, you can expose the gateway directly, but you must combine three controls:- Token auth on the gateway. The init wizard enables this by default
(
Authentication method → Token). Verify your~/.comis/config.yamlcontains agateway.tokens:section and~/.comis/.envhas aCOMIS_GATEWAY_TOKEN. - Firewall to trusted IPs only. On Ubuntu/Debian:
- TLS. Without TLS, the bearer token crosses the wire in cleartext.
Either run with
gateway.tls.certconfigured (see HTTP gateway: mTLS or front it with a reverse proxy that does TLS for you (in which case use the recommended posture above instead).
comis status from your laptop against a remote VPS
The CLI’s comis status defaults to reading ~/.comis/config.yaml on the
machine where it runs. Copying the VPS’s config to your laptop won’t work
on its own — gateway.host: 0.0.0.0 is a bind address that the CLI
remaps to local loopback, not the VPS’s public IP.
Set COMIS_GATEWAY_URL (and the matching token) on your laptop instead:
wss:// (TLS) when the gateway is reachable over the public internet.
Use ws:// only over a trusted network (VPN, SSH tunnel).
Common issues
Setup script fails
Setup script fails
Common causes:
- Docker not running — start Docker Desktop or the Docker daemon
- Port 4766 in use — stop the other process or set
COMIS_GATEWAY_PORTin.env - Missing openssl — the script uses
openssl rand -hex 32for token generation; install it with your system package manager
Cannot access dashboard from host
Cannot access dashboard from host
Symptom:
curl http://127.0.0.1:4766/health returns “connection refused”
or “connection reset by peer” even though the container is reported healthy.Fix: Two distinct binds are involved — get them in the right place:- Host-side bind (which interface the host listens on): controlled by
COMIS_GATEWAY_HOSTin the project-root Compose.env. The default is127.0.0.1; use0.0.0.0only when you intentionally want LAN exposure and have configured authentication and transport security. - Container-side bind (which interface the daemon listens on inside the container): the base Compose file sets this to
0.0.0.0so port forwarding can reach the daemon. A mountedconfig.yamlhas higher precedence; if it setsgateway.host: 127.0.0.1, change it to0.0.0.0or remove the field.
- The container is running and healthy:
docker compose ps - No firewall is blocking the port
- Confirm no additional Compose file intentionally replaces the loopback host-port mapping.
Container exits immediately
Container exits immediately
Symptom: The container starts but stops within seconds.Fix: Check the logs for the error:Common causes:
- Invalid config.yaml — check YAML syntax and required fields. The daemon writes a recovery snapshot at
~/.comis/config.last-good.yaml; runcp ~/.comis/config.last-good.yaml ~/.comis/config.yamlto restore the previous-known-good config, thendocker compose restart. - Missing API key — verify
COMIS_ENV_FILE(default~/.comis/.env) has the correct variable name - Port already in use — another process is using port 4766 on the host
Daemon can't write to .env (`Is a directory` error)
Daemon can't write to .env (`Is a directory` error)
Symptom: Bringing up Compose without first running If
docker-setup.sh,
the daemon fails to persist credentials and you see
cannot create /home/comis/.comis/.env: Is a directory in the logs.Cause: Docker bind-mounts ${COMIS_ENV_FILE:-~/.comis/.env} into the
container. If the host path doesn’t exist, Docker silently creates it
as a directory instead of a file, then every write fails.Fix: create the file before docker compose up:.env already exists as a directory, remove it first:
rmdir ~/.comis/.env && touch ~/.comis/.env.The repo’s docker-setup.sh handles this automatically — this only
affects manual docker compose up.Next steps
Configuration Guide
Customize your agent settings, add channels, and configure advanced options.
Verify Installation
Run diagnostic commands to confirm everything is working.
Operations: Docker
Docker deployment boundaries, multi-stage builds, and security hardening.
