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.