Veefore docs

Self-host Veefore

Run the control plane, the gateway and the console on your own infrastructure, against your own PostgreSQL.

Using hosted Veefore?

You do not need this page. Install the CLI and run veefore in your agent project; see the Quickstart.

Self-hosting keeps every agent record, policy and audit event inside your own network. Veefore runs as three Node processes over one PostgreSQL database, and this page gets all of them running from one command, first on one machine, then reachable by your engineers. For production deployment, see Deployment.

#Requirements

Version Why
Node 20.10 or newer Native ESM loader behaviour the packages rely on
PostgreSQL 14 or newer The shared database for every process
Python 3.9 or newer Only if you work on the Python SDK
Docker any recent Only as a convenient way to get PostgreSQL

#Get it running

Install dependencies

bash
git clone https://github.com/veefore/veefore.git
cd veefore
npm install

Start a database

Any reachable PostgreSQL works. If you want one in a container:

bash
docker run -d --name veefore-postgres \
  -e POSTGRES_USER=veefore \
  -e POSTGRES_PASSWORD=veefore \
  -e POSTGRES_DB=veefore \
  -p 55432:5432 \
  postgres:16

Port 55432 rather than 5432 so it cannot collide with a PostgreSQL you already run.

Use a real PostgreSQL, not the embedded driver

Veefore ships an embedded PGlite driver, and it is genuinely useful for isolated tests. It is the wrong choice for running the stack, because it is per-process: the control plane, the gateway and the seed script would each get their own private copy of the database, and nothing would see anyone else's writes. The symptom is confusing — an agent you just created does not exist.

Configure

bash
cp .env.example .env

Two things to set, and one to check:

ini
# Point at the database you just started.
DATABASE_URL=postgres://veefore:veefore@127.0.0.1:55432/veefore

# These ship as the defaults. Change them only if a port is taken.
CONTROL_PLANE_PORT=4000
GATEWAY_PORT=4010
VEEFORE_CONSOLE_PORT=5173
CORS_ALLOWED_ORIGINS=http://localhost:5173

DATABASE_URL is empty in .env.example, and empty means the embedded driver — see the warning above. Setting it is the one edit you must make.

If you change the console port, change CORS_ALLOWED_ORIGINS to match or the browser will refuse every request with no useful error. Full list in Configuration reference.

Generate your own keys

.env.example ships with development keys so the stack boots. They are shared with everyone who ever cloned the repository, so they are not secret by definition. Before anything that matters, replace VEEFORE_DATA_ENCRYPTION_KEY, VEEFORE_SIGNING_PRIVATE_KEY, VEEFORE_SESSION_SECRET and VEEFORE_AUDIT_CHAIN_SECRET. See Secrets.

Migrate and seed

bash
npm run migrate
npm run seed:demo

seed:demo creates an organization with agents, tools, policies, delegations, credentials, approvals, incidents and audit history — enough that every console page has something real to render. The accounts it creates are printed at the end; the owner is owner@acme.test with the password shown in the output.

For an empty organization with no sample data, use npm run seed instead.

npm run migrate:check applies every migration to a throwaway database and verifies it comes out clean. That is the one to run in CI.

Start everything

bash
npm run dev
Process URL
Control plane http://localhost:4000
Gateway http://localhost:4010
Console http://localhost:5173

Individual processes, if you want them in separate terminals:

bash
npm run dev:control-plane
npm run dev:gateway
npm run dev:console

Confirm it is healthy

bash
curl -s http://localhost:4000/health/ready
curl -s http://localhost:4010/health/ready
curl -s http://localhost:4000/v1/meta/info

/health/ready checks the database. If the database is gone, readiness goes red — it does not report healthy and then fail every request, which would be the more annoying failure.

/v1/meta/info needs no authentication and tells you the version, the environment, both public URLs, and the published capability and exclusion lists.

#Connect agent projects

Engineers never clone this repository. They install the CLI and the SDK from the package registries. On its own, veefore connects to the hosted Veefore service, so engineers point it at your deployment the first time:

bash
npm install -g veefore
cd their-agent-project
veefore --control-plane https://veefore.your-company.com

After that the CLI remembers the address, and each project records it in its committed veefore.config.json, so teammates run plain veefore. To avoid the flag entirely, set VEEFORE_CONTROL_PLANE_URL on engineers' machines, for example through your device management. The console's Developer page shows the exact command with your address filled in.

The CLI signs them in through the console in their browser, so three addresses must be right before you hand out the URL:

Variable Set it to Why
CONTROL_PLANE_PUBLIC_URL The address engineers pass to --control-plane Published at /v1/meta/info
GATEWAY_PUBLIC_URL The address agents reach the gateway at Written into each project's configuration; it is also the signing audience
CONSOLE_PUBLIC_URL The address people open the console at Where browser sign-in for the CLI happens. Defaults to the first CORS_ALLOWED_ORIGINS entry
VEEFORE_HOSTED false Leave it off for a self-hosted install, so setup instructions include your address

veefore reads the gateway and console addresses from the control plane, so engineers only ever need the one URL. It also remembers it: later commands in any project reuse the last address.

A loopback address only works on the same machine

http://localhost:4000 is right for trying Veefore on your own laptop and wrong for anyone else. Before inviting engineers, serve all three behind HTTPS on addresses their machines and their agents can reach. See Run the stack.

#Run the documentation locally

These docs are a workspace in the same repository.

bash
npm run docs:dev      # http://localhost:4800, rebuilds on save
npm run docs:build    # static output in docs/dist
npm run docs:check    # validate without writing anything

docs:check is the one that matters in CI: it fails on a broken internal link, a page missing from the navigation, a page in the navigation with no file, an API group added to the catalogue without an explanation, or an error code with no documented status group.

#Verify the whole system

bash
npm run verify

This is the single command that proves the system works. Twenty-three stages, in the order a reviewer would run them: typecheck, lint, format, the scope audit, the quality audit, the migration check, then every test suite, then smoke tests that drive real processes over real HTTP.

Optional stages are skipped with a named reason rather than silently omitted, so a green run cannot hide a missing dependency. If the console smoke test says the stack is not running, start npm run dev and re-run.

Individual pieces:

bash
npm test                 # unit, integration, contract, policy, security
npm run test:e2e
npm run test:chaos       # dependency loss must fail closed
npm run test:python
npm run scope:audit      # the out-of-scope features must not exist
npm run quality:audit    # no mock data, no hardcoded metrics, no auth bypass

#Ports, and what to do when they collide

4000 and 5173 are commonly taken on a developer machine, so expect to change at least one of these. Change it in .env — everything reads from there, including the console's Vite config, so one edit is enough.

The console binds with strictPort, so a collision is a startup error rather than a silent move to another port.

Variable Default
CONTROL_PLANE_PORT 4000
GATEWAY_PORT 4010
VEEFORE_CONSOLE_PORT 5173
VEEFORE_CONSOLE_PREVIEW_PORT 4173
VEEFORE_DOCS_PORT 4800
TOOL_SERVER_PORT 4500 (the example downstream service)

#Next

Identity, authority, policy and enforcement for autonomous AI agents.