> For the complete documentation index, see [llms.txt](https://docs.visdom.virtuslab.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.visdom.virtuslab.com/visdom-control-plane/deploying-and-configuring.md).

# Deploying and configuring

Running the Control Plane, the environment it reads, and what it needs from Keycloak.

## Shape

One container image, `visdom-control-plane`: a Rust service with the UI embedded, built on `distroless/cc-debian13:nonroot`, running as UID 65532 and listening on **8080**. It needs:

* **PostgreSQL** – the only store. Migrations run automatically on start-up.
* **Keycloak** – the `visdom-auth` realm, or any OIDC issuer with the same clients and roles.
* Optionally an **OpenTelemetry collector**.

Run a single replica, and upgrade with a *Recreate* strategy: one past migration must run with the service scaled to zero, and there is no leader election yet. See [Known limitations](/visdom-control-plane/known-limitations.md).

## Health

* `GET /healthz` – the process is up.
* `GET /readyz` – currently the same static answer; it does not check the database.

## Environment

The server reads configuration only from the environment and refuses to start on a missing required value or a malformed optional one.

| Variable                                                                                                         | Required             | Default                 | Notes                                                                                                 |
| ---------------------------------------------------------------------------------------------------------------- | -------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- |
| `CP_DATABASE_URL`                                                                                                | yes                  |                         | PostgreSQL connection string                                                                          |
| `CP_OIDC_ISSUER_URL`                                                                                             | yes                  |                         | Must match the `iss` claim of incoming tokens                                                         |
| `CP_OIDC_AUDIENCE`                                                                                               | yes                  |                         | Usually `control-plane`                                                                               |
| `CP_SECRETS_MASTER_KEY`                                                                                          | yes                  |                         | Base64 of 32 random bytes (`openssl rand -base64 32`). Losing it makes every stored secret unreadable |
| `CP_LISTEN_ADDR`                                                                                                 |                      | `0.0.0.0:8080`          |                                                                                                       |
| `CP_OIDC_CLIENT_ID`                                                                                              |                      | `visdom-control-plane`  | The client the UI signs in with                                                                       |
| `CP_PUBLIC_URL`                                                                                                  |                      | `http://localhost:8080` |                                                                                                       |
| `CP_LOG`                                                                                                         |                      | `info`                  | `tracing` filter syntax                                                                               |
| `LOG_FORMAT`                                                                                                     |                      | auto                    | `json` or `text`; JSON when stdout is not a terminal                                                  |
| `OTEL_EXPORTER_OTLP_ENDPOINT` and other `OTEL_*`                                                                 |                      | off                     | Setting an endpoint turns on traces, metrics and logs; service name `control-plane`                   |
| `CP_SUITE_CONTROL_PLANE_URL`, `CP_SUITE_ORCHESTRATOR_URL`, `CP_SUITE_CONTEXT_FABRIC_URL`, `CP_SUITE_TRACING_URL` |                      |                         | Links in the module rail and the CORS allow-list                                                      |
| `CP_ORCHESTRATOR_API_URL`, `CP_CONTEXT_FABRIC_API_URL`, `CP_AI_TRACING_API_URL`                                  |                      |                         | Each one turns on project sync to that product                                                        |
| `CP_M2M_CLIENT_ID`, `CP_M2M_CLIENT_SECRET`                                                                       | with any sync target |                         | Credentials of the `control-plane-m2m` client                                                         |

## Keycloak

* A public client `visdom-control-plane` for the UI (authorisation code with PKCE) whose tokens carry the audience `control-plane`.
* The realm role `control-plane-admin` for the first administrators.
* A confidential client `control-plane-m2m` with the audiences of the products it syncs to.
* One confidential client per product (`orchestrator-m2m`, `context-fabric-m2m`, `ai-tracing-m2m`) with the audience `control-plane`.

The `visdom-auth` repository ships a realm export with all of these. Federation to the organisation's directory (Entra ID, LDAP, SAML) is configured in Keycloak, not in the Control Plane.

## Running it locally

```bash
# Keycloak on :8088 with realm visdom-local and a dev/devlocal admin
cd ../visdom-auth && docker compose up -d
# add "127.0.0.1 keycloak" to /etc/hosts

# PostgreSQL and a watch build of the UI
cd ../visdom-control-plane && docker compose up -d
cp .env.example .env            # first time only
set -a; source .env; set +a
cargo run -p cp-server
```

Open `http://localhost:8080` and sign in as `dev` / `devlocal`. `curl localhost:8080/healthz` answers `ok`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.visdom.virtuslab.com/visdom-control-plane/deploying-and-configuring.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
