Self-Hosted Install¶
Purpose¶
This guide describes the first supported DecisionGraph self-hosted install path.
The supported path today is source-first, with an optional packaged OTP release built from the same repo:
- clone the repository
- run PostgreSQL locally or on a trusted nearby host
- start the BEAM umbrella from
beam/ - optionally seed the curated
release-demotenant for the Phase 10 operator showcase
What Is Mandatory¶
You need:
- a DecisionGraph repository checkout
- Elixir
~> 1.19 - a compatible OTP release
- PostgreSQL 16 reachable from the BEAM node
Helpful but optional:
- Docker for the repo
postgresandotel-collectorservices curlfor smoke tests- a process supervisor for long-running self-hosted installs
Fastest Local Bootstrap¶
From the repository root:
docker compose up postgres otel-collector -d
cd beam
mix setup
set PHX_SERVER=true
iex -S mix
Then open:
http://localhost:4100
This is the default local evaluation path.
Development Auth Defaults¶
Development config currently includes:
dev-reader-tokendev-writer-tokendev-admin-token
Default development tenants:
defaultrelease-demo
These defaults are meant for trusted local evaluation. They should not be treated as a production auth story.
Release Demo Bootstrap¶
Once Phoenix is running, seed the curated operator demo from a second terminal:
cd beam
mix dg.demo.seed --output ../.tmp/phase10-demo-report.json
This creates a realistic evaluation tenant named release-demo with:
- an approved precedent trace
- a live escalated exception review
- an incident review workflow
Primary console routes:
http://localhost:4100/?tenant=release-demo&trace_id=trace-live-renewal-002&workflow_id=trace-live-renewal-002:exception:ex-live-renewal-002http://localhost:4100/?tenant=release-demo&trace_id=trace-incident-review-003&workflow_id=trace-incident-review-003:trace_review:incident_triage
Production-Oriented Source Deployment¶
The first supported non-dev deployment is still source-based. Before exposing the service on a network, set at least:
DATABASE_URLSECRET_KEY_BASEPHX_HOSTPORTPOOL_SIZEPHX_SERVER=true
Then, from beam/:
mix deps.get
mix compile
mix ecto.migrate
mix phx.server
Example runtime environment:
MIX_ENV=prod
DATABASE_URL=ecto://decisiongraph:decisiongraph@localhost/decisiongraph_beam_prod
SECRET_KEY_BASE=<long-random-secret>
PHX_HOST=localhost
PORT=4100
POOL_SIZE=10
PHX_SERVER=true
DECISION_GRAPH_DEPLOYMENT_ENV=prod
Service-Account Bootstrap¶
Today the preferred production bootstrap is file-driven. The repo does not yet ship a UI first-run wizard, but it no longer requires hand-authoring service-account config in Elixir files.
Generate a bootstrap file:
cd beam
mix dg.accounts.bootstrap --output ../.tmp/service-accounts.json
Then point the runtime at it:
DECISION_GRAPH_SERVICE_ACCOUNTS_FILE=/absolute/path/to/service-accounts.json
DECISION_GRAPH_OPERATOR_ACCOUNT_ID=admin-main
After the runtime is up, you can also open http://localhost:4100/bootstrap to preview a
fresh bootstrap payload and inspect a safe token-overlap rotation plan for the configured
service accounts.
For packaged OTP releases, you can also place the file at:
config/service-accounts.json
inside the extracted release root. The release runtime will load that path automatically.
The generated JSON format is:
{
"operator_console_account_id": "admin-main",
"service_accounts": [
{
"account_id": "reader-main",
"roles": ["reader"],
"permissions": [],
"tenant_ids": ["default"],
"tokens": ["replace-me-reader"]
}
]
}
Current self-hosted expectation:
- use
defaultas the first tenant unless you already need logical isolation - keep replay controls disabled until the operator account is configured
- replace development tokens before any non-local exposure
Token rotation rule:
- each account may carry a
tokenslist - keep old and new tokens together during the overlap window
- remove the old token only after clients have moved
Smoke Test Checklist¶
Deployment Health¶
curl http://localhost:4100/api/healthz
Expected:
200
Projection Health¶
curl http://localhost:4100/api/v1/projections/health -H "Authorization: Bearer dev-reader-token" -H "x-tenant-id: release-demo"
Expected:
200- a JSON response with per-projection lag, digest, and status data
Replay Admission¶
curl -X POST http://localhost:4100/api/v1/admin/replays -H "Authorization: Bearer dev-admin-token" -H "x-tenant-id: release-demo" -H "content-type: application/json" -d "{\"mode\":\"catch_up\",\"projection\":\"trace_summary\",\"reason\":\"self-hosted smoke test\"}"
Expected:
202
Bootstrap Validation Checklist¶
Use this checklist on a clean machine or fresh server bootstrap:
- Postgres starts and accepts connections
mix setupormix ecto.migratecompletes without manual fixes/api/healthzreturns200- authenticated projection health returns
200 - the operator console loads at
/ - replay admission works with an admin token
- the install path is understandable without reading source files
Release-Candidate Validation Command¶
For the supported self-hosted evaluation path, the one-command release validator is:
cd beam
mix dg.release.validate --output ../.tmp/phase10-release-validation.json --summary-output ../.tmp/phase10-release-validation.md
This command starts the real HTTP runtime, seeds the release-demo tenant, and records validation evidence for the current release candidate.
For a staging-style verification pass that reuses existing seeded data instead of resetting the tenant:
cd beam
mix dg.release.validate --seed-mode reuse --quiet --output ../.tmp/phase10-release-validation.json --summary-output ../.tmp/phase10-release-validation.md
OTP Release Packaging¶
Build the packaged BEAM release:
cd beam
mix release decisiongraph_beam
The packaged release lives under:
beam/_build/prod/rel/decisiongraph_beam
Run migrations from the packaged release:
cd beam
_build/prod/rel/decisiongraph_beam/bin/decisiongraph_beam eval "DecisionGraph.Store.Release.migrate()"
Start the packaged release:
cd beam
_build/prod/rel/decisiongraph_beam/bin/decisiongraph_beam start
Tagged GitHub releases can also publish:
- a signed packaged OTP tarball attached to the GitHub Release
- a prebuilt GHCR image derived from
beam/Dockerfile
Container Image Build¶
Build the repo-provided image from the packaged OTP release:
cd beam
mix release decisiongraph_beam
docker build -f Dockerfile -t decisiongraph-beam:local _build/prod/rel
If you prefer a source-building Docker path that compiles the release inside Docker, use:
cd beam
docker build -f Dockerfile.build -t decisiongraph-beam:source .
Known Limits In The Current Install Story¶
Current Phase 8 limits are explicit:
- there is no hosted SaaS path
- auth bootstrap writes are still file-driven or env-driven; the
/bootstrapUI is a preview and planning surface, not a persistence wizard - clustering and multi-node failover are out of scope for the supported topology
If those limits are acceptable, this is the supported self-hosted path today.