Skip to content
Contextely

Deployment

Self-hosting

“It holds a condensed copy of our systems of record” ends the conversation at a lot of companies unless it runs on their own hardware. So it does, with no plan limits.

Run it

git clone https://github.com/maxbeech/contextely
cd contextely

export LLM11_API_KEY=...
export CONTEXTELY_SELF_HOSTED=1
export CONTEXTELY_ENCRYPTION_KEY=$(openssl rand -base64 32)
docker compose up --build

# http://localhost:3000

Compose brings up Postgres 17 alongside the app. Apply the schema once with npm run db:push.

Point the tools at it

Nothing in the client surface is pinned to our deployment. An MCP client takes the URL in its config, and the CLI is told once and stays told.

# Your deployment serves its own copy of the CLI.
curl -fsSL https://contextely.internal/cli.mjs -o contextely && chmod +x contextely

./contextely config set-url https://contextely.internal
./contextely config set-key ctx_sk_...
./contextely search "acme renewal"

# or per call, or from the environment
CONTEXTELY_URL=https://contextely.internal ./contextely usage

What you must supply

DATABASE_URL

Any Postgres 14+. Compose provides one. Server-side only, so there is no browser-reachable database.

LLM11_API_KEY

The one genuine LLM dependency, and it has no fallback: without a key, ingest and refresh fail loudly rather than writing a summary some heuristic invented. LLM11_MODEL picks a routing pack or a pinned model; LLM11_BASE_URL points at your own router.

CONTEXTELY_SELF_HOSTED

Set it to 1 to remove the plan limits. Read explicitly rather than inferred from absent Stripe keys: without it, every workspace resolves to the Free plan.

One number stays finite on purpose. 50,000 memory objects bounds what a retrieval scans, and an unbounded value would read your whole store into memory on every query.

CONTEXTELY_ENCRYPTION_KEY

A source credential is replayed on every refresh, so it is encrypted rather than hashed, and this is the key. Generate one with openssl rand -base64 32.

Keep it away from your database backups: storing both together is the same as storing neither. Rotate through CONTEXTELY_ENCRYPTION_KEY_PREVIOUS and scripts/encrypt-existing-secrets.mjs --rewrap.

What is optional, and what you lose without it

AUTH_SECRET

The dashboard signs people in with Better Auth, running inside the app on your own Postgres. It needs a secret of 32 characters or more to sign session cookies. Left unset, it fails every session check closed, so it lets nobody in rather than everybody.

The REST API and the MCP server use API keys and are unaffected, which for an agent-facing deployment is usually all you need.

SENTRY_DSN

Unset means no error reporting leaves your network. Nothing else changes.

STRIPE_*

Irrelevant when self-hosting. Billing is disabled and there are no plan limits.

What leaves your network

Exactly one thing: the content of a record being condensed, sent to whichever model you route LLM11_MODEL at. Retrieval, scoring, entitlement and freshness are all local.

No telemetry, no licence check, no phone-home. With no internet access beyond your model endpoint, Contextely still works.

Your own use, and everyone else's

Free for your own company, with no limits: your staff, your agents, your internal tools, a subsidiary you own.

It stops at resale. Putting Contextely inside a product you sell, or presenting it under another name, is a partner arrangement and needs a signed agreement.

Nothing in the codebase checks; the licence is a promise rather than a lock. The agreement is how you get the provisioning API, pooled billing and somebody to call: write to [email protected].