Documentation

Self Hosted Docker

Run the whole Executor server in one Docker container over a SQLite file: API, MCP, auth, code execution, and the web UI.

The self-hosted image is the entire Executor server in a single container: the typed API, the MCP server, authentication, QuickJS code execution, and the web console, all in one process over a libSQL (SQLite) file. There is no external database, worker, or proxy to run.

Run it

Using the published image:

docker run -d \
  --name executor-selfhost \
  -p 4788:4788 \
  -v executor-data:/data \
  ghcr.io/usefulsoftwareco/executor-selfhost:latest

Or build from a clone of the repo, from apps/host-selfhost:

docker compose up -d --build

No configuration is required. Open http://localhost; the first person to create an account becomes the owner. After that, people join through single-use invite links you mint from the Admin page, and open signup is closed.

Storage

Everything that must persist (the SQLite database and the generated encryption keys) lives in the data directory, mounted at /data in the container. Always mount a volume there so it survives restarts and upgrades:

-v executor-data:/data     # named volume (what compose uses)
# or a host path:
-v /srv/executor:/data

Back it up by snapshotting that volume (or copying /data, primarily data.db). EXECUTOR_DATA_DIR (default /data) sets the directory, and EXECUTOR_DB_PATH (default <data dir>/data.db) sets the database file.

Environment variables

Everything is optional: a bare run boots a working instance. The defaults below are the container defaults.

Variable Default Purpose
PORT 4788 HTTP port the server listens on.
EXECUTOR_HOST 0.0.0.0 Bind address. The image binds all interfaces.
EXECUTOR_DATA_DIR /data Directory holding the database and generated keys.
EXECUTOR_DB_PATH <data dir>/data.db SQLite database file.
EXECUTOR_WEB_BASE_URL auto (http://localhost:4788) Public URL browsers use. Required behind a domain or TLS (see below).
EXECUTOR_TRUSTED_ORIGINS unset Comma-separated browser aliases allowed to authenticate without changing the public URL.
BETTER_AUTH_SECRET generated, persisted in /data Session secret (32+ chars). Rotating it signs everyone out.
EXECUTOR_SECRET_KEY generated, persisted in /data Master key encrypting stored secrets. Set it to manage it yourself.
EXECUTOR_BOOTSTRAP_ADMIN_EMAIL unset Pre-create the admin headlessly (with the password below); skips browser first-run.
EXECUTOR_BOOTSTRAP_ADMIN_PASSWORD unset Password for the bootstrap admin.
EXECUTOR_BOOTSTRAP_ADMIN_NAME Admin Display name for the bootstrap admin.
EXECUTOR_ORG_NAME Default Display name of the single org every user joins.
EXECUTOR_ORG_SLUG default URL slug for that org.
EXECUTOR_ALLOW_LOCAL_NETWORK false Allow sandboxed code to reach loopback / private addresses. Keep off unless you trust the code.
EXECUTOR_DISABLE_AUTH_RATE_LIMIT false Turn off sign-in rate limiting. Only when a proxy or WAF in front of Executor limits instead.

Tracing is configured separately, and off unless you turn it on — see Tracing.

Behind a domain or TLS

docker run -d \
  -p 4788:4788 \
  -v executor-data:/data \
  -e EXECUTOR_WEB_BASE_URL=https://executor.example.com \
  ghcr.io/usefulsoftwareco/executor-selfhost:latest

For a headless deploy (CI or infra-as-code), set EXECUTOR_BOOTSTRAP_ADMIN_EMAIL and EXECUTOR_BOOTSTRAP_ADMIN_PASSWORD to create the admin without the browser setup screen.

Additional browser aliases

Keep EXECUTOR_WEB_BASE_URL pinned to the canonical public HTTPS origin used for OAuth callbacks and generated links. If the same instance is intentionally available through additional browser addresses, allow those exact origins separately:

-e EXECUTOR_WEB_BASE_URL=https://executor.example.com \
-e EXECUTOR_TRUSTED_ORIGINS=http://executor.home.arpa:4788,http://192.0.2.10:4788

Only cookie-authenticated browser requests use this allowlist. OAuth callbacks, MCP metadata, approval links, and other absolute URLs remain pinned to EXECUTOR_WEB_BASE_URL. Origins are never inferred from request headers.

Connect an agent

The server exposes a streamable-HTTP MCP endpoint at /mcp. Point your client at http://localhost:4788/mcp (or your public URL). See MCP Proxy for how that endpoint exposes your integrations.