Skip to content
Documentation
On this page

Self-host with Docker

Run the whole hosted server in one container, with an embedded database and no separate Postgres, queue or proxy, on your own infrastructure.

Self-host is the hosted server on your own infrastructure. One container holds the API, the MCP endpoint, authentication, the app runtime and the dashboard, over an embedded PGlite database. There is no separate database, worker, queue or proxy to run.

It has the same organizations, invitations and browser sign-in as hosted. It does not offer the hosted Google and GitHub sign-in buttons.

Configure it

Three settings are required. The container will not start without them.

Variable Required Purpose
BETTER_AUTH_URL yes The exact public origin you load in the browser.
BETTER_AUTH_SECRET yes Session secret. At least 32 characters. Rotating it signs everyone out.
EXECUTOR_ENCRYPTION_KEY yes Key that encrypts stored credentials. Exactly 64 hexadecimal characters.
EXECUTOR_ENVIRONMENT no Label for this deployment. The default is self-host.
EXECUTOR_APP_UI_BASE_URL no HTTPS origin that serves app web pages. See below.
SSO_DISCOVERY_URL no OIDC discovery document. Leave it empty to keep SSO off.
SSO_CLIENT_ID, SSO_CLIENT_SECRET no Credentials for that identity provider.
SSO_ALLOWED_DOMAINS no Comma-separated email domains allowed to join through SSO.

BETTER_AUTH_URL must match the scheme, host and port you actually use. If it does not, browser sign-in is rejected as an invalid origin. Origins are never inferred from a request header.

Keep <BETTER_AUTH_URL>/api/oauth/callback reachable; connecting a provider account by OAuth uses it. The SSO callback is <BETTER_AUTH_URL>/api/auth/callback/sso.

Tracing is configured separately and is off until you set an endpoint. See Tracing.

Run it

During the beta the image is built from the repository rather than pulled from a registry.

git clone https://github.com/UsefulSoftwareCo/executor-next
cd executor-next
docker compose -f apps/hosted/self-host/compose.yaml up --build -d

Supply the three required variables in the environment of that command, or in a .env file beside it.

BETTER_AUTH_URL=https://executor.example.com
BETTER_AUTH_SECRET=<stable random secret of at least 32 characters>
EXECUTOR_ENCRYPTION_KEY=<stable 64-character hexadecimal key>

The container publishes port 4400 on loopback only, as 127.0.0.1:4400. Put your own TLS terminator in front of it and forward to that port. Startup initializes the embedded database before it opens HTTP, so the first boot takes a moment.

Stop it with:

docker compose -f apps/hosted/self-host/compose.yaml down

The first person to finish setup becomes the owner, and one organization is created. After that, people join through invitations, or through SSO when you have configured it.

Storage

Everything that must survive a restart lives in the named volume pglite-data, mounted at /app/data. That is the database, the encrypted credentials and the diagnostics.

Back up by snapshotting that volume. Do not remove it when you update the image.

Serving app web pages

Some apps ship a web page. Set EXECUTOR_APP_UI_BASE_URL to an HTTPS origin with no trailing slash, and point a wildcard DNS record and certificate at your proxy:

EXECUTOR_APP_UI_BASE_URL=https://apps.example.net

Each page is served at <app-slug>--<organization-slug>.<base>, forwarded to container port 4400. That whole first label must fit in 63 characters, so keep app and organization slugs short. On localhost the origin is derived for you and you do not need to set this.

Running without Docker

You can run the same server directly with Node. Data persists under .local/hosted; set EXECUTOR_DATA_DIR to choose a different parent directory. HOST defaults to 0.0.0.0 and PORT to 4400.

Self-host needs no DATABASE_URL, no separate Postgres, and no migration command.

Connect an agent

The MCP endpoint is <your origin>/mcp. Sign-in happens in the browser, the same way as hosted. See Add an MCP client.

What is coming later

  • A published container image, so self-hosting does not need a clone and a build.

Was this page helpful?