examples/docker:
one container image, two services, one database file.
web(port 8080) — the authoring app: the widget, theme, schema and action designers over the published authoring surface (@widgentic/mcp/authoring), plus write-only secrets and API keys.mcp(port 8081) — the Streamable HTTP MCP endpoint at/mcp. Mint a key under Keys and connect any MCP host with anx-api-keyheader (or?key=where the host cannot send headers).
createSqliteStore: SQLite compiled
into the Node runtime, so the whole deployment has no runtime dependency to
operate.
The trust shape
The two services mirror the hosted product’s split:Identity without an identity provider
By default the deployment serves one principal with no sign-in. That mode belongs on localhost or a trusted network — treat the app like any admin panel without a login. Multi-user comes from the auth proxy you already run, not from widgentic:Secrets and key custody
Secret values are envelope-encrypted at rest; the database file holds ciphertext and key digests only. The key-encryption key is yours to supply — generated once, handed to both services as a mounted file (WIDGENTIC_KEK_FILE, the compose file uses a docker secret) or the
WIDGENTIC_KEK variable, and never generated at boot: a per-boot key would
write records nothing can read back. With no KEK the Secrets section is off
and everything else works.
Name the trade honestly: here the KEK lives in the process, which is weaker
custody than the hosted product’s, where the key sits in a managed vault and
no process ever holds it. Whoever can read your KEK material can decrypt
every secret this deployment stores, and losing it makes them unreadable
with no recovery. If your threat model needs vault custody, the same cipher
port takes createKeyVaultCipher from @widgentic/mcp/secrets/keyvault.