Run the sovereign Odyshell control plane and PostgreSQL on your infrastructure.
Self-hosting uses the same Better Auth identity layer, Server, PostgreSQL schema, remote MCP and HTTP protocols, dashboard, and Linux Client as Cloud. Identity, policy, Task, Command, audit, and credential data stay in the deployment owner's PostgreSQL database. Clerk and hosted analytics are not required.
cp .env.example .env
docker compose config
docker compose up -d --build
pnpm test:self-hostFill every blank secret in the root .env first. BETTER_AUTH_SECRET and
ODYSHELL_WEB_KEY require at least 32 random characters, and POSTGRES_PASSWORD must be a URL-safe
random value. Compose runs Web and Server in production mode, binds every published port to
loopback by default, and fails when a required secret is absent.
The smoke test creates the first local account and Organization, verifies authenticated dashboard access, proves the single-Organization boundary, and checks anonymous MCP denial. Use a fresh PostgreSQL volume if you want to perform first-user onboarding manually instead.
Put Web and Server behind TLS, keep PostgreSQL private, and set the canonical public URLs before building:
BETTER_AUTH_URL=https://app.example.com
NEXT_PUBLIC_ODYSHELL_SERVER_URL=https://api.example.com
ODYSHELL_MCP_URL=https://api.example.com/mcpThe public Server URL is embedded into the Web image at build time. The private Compose network uses HTTP only for JWKS fetches from Server to Web; use HTTPS if that hop crosses a trusted network boundary. Store database and application secrets in the deployment platform, encrypt backups, test restores, and run one Server replica in this release because live Machine connections are process-local.
Self-hosted mode permits one Organization. Local email/password is built in. Google sign-in is
optional and must be configured before building the Web image.
Generic OIDC is also optional: configure OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, an HTTPS
OIDC_DISCOVERY_URL, matching server/public provider IDs, and
NEXT_PUBLIC_OIDC_AUTH_ENABLED=true. Odyshell uses PKCE and strict issuer validation.
/mcp resource to the external Agent runtime.ods on the target Linux host.npm install --global @odyshell/cli
ods --server https://api.example.com up \
--token <single-use-token> \
--name production-api \
--agent-id <agent-id>The Machine initiates the connection and needs no inbound port, SSH credential, or VPN route. Run the Client as a dedicated Linux user without root, sudo, or Docker membership.
For the complete production and lifecycle checklist, see the repository self-hosting guide.