Self-hosted setup
Manually authored Storyboards need no feature flag and no extra services. Storyboards, receipts and datasets are stored in Cardinal UI’s existing Postgres, and no storyboard scene is rendered in the Cardinal UI pod. (The only image it draws is the text-only summary card of a link preview.) This page covers what your operator configures, starting with the usual self-hosted topology: Cardinal UI inside your VPC, reachable only from your network.
On Cardinal Cloud (app.cardinalhq.io) all of this is already set up; see Use with Claude.
Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.
Requirements
-
A Cardinal UI image that includes Open Storyboards (v1.97.18 or later) for evidence tiers, public links and personal workspaces. Storyboards themselves need v1.97.10 or later.
storyboard__findneeds v1.97.21 or later, and acts (storyboard__add_act,storyboard__discard_act) need a release after v1.97.21; see Upgrading to acts. Associations (about,storyboard__link, find by commit, pull request and file) need v1.99.6 to v1.99.8, and link previews with an authored headline and cover need v1.99.8 or later. -
MAESTRO_MCP_API_KEYon the MCP gateway sidecar as well as the Cardinal UI container. The sidecar uses it to call back into Cardinal UI when Claude creates, previews, publishes and shares a storyboard. ThemaestroHelm chart 0.10.28 or later sets it on both containers from one Secret. Chart 0.10.29 also adds typed, install-time-validated values for the settings on this page:maestro.trustedProxyHops(MAESTRO_TRUSTED_PROXY_HOPS), andshare.hostandshare.ingress.enabled(SHARE_HOST). Setting the variables inmaestro.envstill works; don’t set both. On an older chart, add the sameMAESTRO_MCP_API_KEYentry (the same Secret and key) to bothmaestro.envandmcpGateway.env; see Connect AI clients. -
GATEWAY_AGGREGATOR_ENABLED=trueon the sidecar. Receipts are minted on the gateway’s aggregated MCP endpoint, which the plugins use. With it unset, tool calls return no[receipt:…]trailer and there is nothing to cite:mcpGateway: env: - name: GATEWAY_AGGREGATOR_ENABLED value: "true" -
MAESTRO_BASE_URL(recommended, and required for public links withoutSHARE_HOST). With it set, theview_urlClaude hands you is an absolute link. Without it, Claude returns an app-relative path such as/storyboards/sb_…?org=…; open it on your Cardinal UI host. See Environment variables.
Cardinal Data Lake is optional. An org with no integrations still gets the storyboard__* tools.
Connect Claude inside your VPC
Writes go through Cardinal’s MCP server with an API key; there is no OAuth sign-in. Inside a private network, connect Claude Code with one of these. Neither needs anything from your identity provider beyond what Cardinal UI already uses.
-
The Cardinal plugin,
/cardinal:connect --host https://ui.example.internal. Each user approves in the browser and gets their own key. Until a user connects, the plugin is local-only: itscardinalserver has no URL and contacts nothing. See Install: Claude Code plugin. If your org has no Cardinal Data Lake, orMAESTRO_INGEST_ENDPOINTis unset, connect still sets up the MCP tools and says telemetry is unavailable. -
The shared API key, registered on Cardinal’s aggregated endpoint. Name the server
cardinal, so the plugins’ capture hooks recognize its results as already witnessed:claude mcp add --transport http --scope user cardinal \ "$CARDINAL_MCP_HOST/api/orgs/$CARDINAL_ORG_ID/mcp" \ --header "X-CardinalHQ-API-Key: $CARDINAL_MCP_API_KEY"The key gates every org on the installation; treat it like an admin token (see Lock it down).
Public links
Public links are off by default for team orgs; an organization owner turns them on in Settings → About. Where the links point:
| Setting | Public link URL |
|---|---|
SHARE_HOST set, for example share.example.com | https://share.example.com/s/<token> |
Only MAESTRO_BASE_URL set | <MAESTRO_BASE_URL origin>/s/<token> |
| Neither | Links can’t be created (share_host_not_configured). Share storyboards inside the org with their view_url. |
Only people who can reach that host can open a link. With an in-VPC Cardinal UI, links on MAESTRO_BASE_URL open only inside your network.
Use SHARE_HOST. It is a bare host[:port]: no scheme, no path. Point its DNS and a TLS certificate at the Cardinal UI Service, like your main hostname. On that host Cardinal UI serves only the public viewer (/s/*), its read API (/api/public/*), the Report this page abuse-report POST, and static assets; everything else, including sign-in and the rest of the API, answers 404, and no cookie is ever read or set. That is what makes it safe to publish:
- A Canvas that escapes its sandbox lands on an origin that holds none of your users’ sessions.
- For an in-VPC install, you can route only
SHARE_HOSTthrough an internet-facing ingress, so outside readers reach shared storyboards while the app stays private. Pass the originalHostheader through, and keepMAESTRO_TRUSTED_PROXY_HOPSright for your proxies so per-reader rate limits see real client addresses.
An invalid SHARE_HOST stops Cardinal UI at startup rather than serving shared pages from the app’s origin. With SHARE_HOST set, a request for /s/<token> on the main host is redirected to it.
STORYBOARD_SIGNUP_URL sets where the viewer’s Make your own with Claude link goes (default https://app.cardinalhq.io).
Link previews
When a storyboard’s link is posted in a chat app, the app asks Cardinal for a preview card. Public links have always had one; from v1.99.8, links to storyboards inside your org (the view_url) have one too, on by default.
Inside your VPC, check this first. To unfurl a member link, the chat platform’s own servers fetch the link, from outside your network. If your Cardinal UI host (MAESTRO_BASE_URL) is reachable only from your network, they can’t, and the message shows a plain link with no preview. The storyboard and its link still work for everyone who can reach the host, and your people’s browsers aren’t involved.
A public SHARE_HOST still serves the card image. The preview’s image isn’t on the app host. With SHARE_HOST set, it is served on the share host (see below), without signing in, to anyone who has the storyboard’s id, and that id is in every member link pasted into a chat, a ticket or an email. So when SHARE_HOST is reachable from the internet, each previewing storyboard’s card image is fetchable there from outside your network, even when MAESTRO_BASE_URL is reachable only inside your VPC, and even when Public storyboard links is off. That image shows the question, the headline or finding, the counts and verdict, and the figure, or the designated cover when it binds no raw evidence. If your org doesn’t want that, an organization owner should turn off Settings → About → Storyboard link previews right after upgrading.
To get previews for a private host you must make the member link’s page reachable by the platform’s crawler, which is your operator’s call. What it serves a crawler is the app’s ordinary page with the preview tags in its head. Those tags carry the storyboard’s question, its headline or finding, its counts and verdict, and the card image, to anyone who has the link, without signing in; see what a preview shows. Scenes, evidence, drafts, context and authors are never included, and opening the storyboard itself still needs a signed-in member.
- Where the images are served from. The card’s image is at
/api/public/storyboard-previews/<storyboard id>/card.pngonSHARE_HOSTwhen it is set, else on theMAESTRO_BASE_URLorigin. The chart’s share ingress already routes/api/public/*on the share host, so the image needs nothing new when you already publishSHARE_HOST. With neitherSHARE_HOSTnorMAESTRO_BASE_URLset, a preview has no image and uses the small summary format. A link with no preview gets the app’s generic image, which the app’s page loads fromhttps://cardinalhq.io/assets/og-default.png. - No new settings. There are no new environment variables, chart values, ports or secrets. The org switch and each storyboard’s switch are in the UI; see Turning previews off.
- Upgrading turns member previews on. After you upgrade to v1.99.8, a posted link to any published storyboard unfurls, including ones published before the upgrade. The switch arrives with v1.99.8 too, so member previews are on from the first request the upgraded pods serve; you can’t turn them off ahead of time. If your org doesn’t want them, an organization owner should turn them off in Settings → About → Storyboard link previews right after upgrading. The setting needs no restart and takes effect on the crawler’s next fetch of the page; an image already fetched can be kept for up to a minute (
Cache-Control: private, max-age=60), and apps may hold on to what they already unfurled. Until then, a posted link unfurls wherever the chat platform’s crawler can reach your host. A host reachable only inside your VPC shows no unfurl, but with a publicSHARE_HOSTevery previewing storyboard’s card image is still fetchable there by id in that window (see A publicSHARE_HOSTstill serves the card image above). - The card image is drawn in the Cardinal UI pod, from text, without a browser. It uses the fonts in the Cardinal UI image, which cover Latin, Greek and Cyrillic; other scripts can appear as empty boxes in the image, and emoji may not look the way they do in chat (the preview’s title and description text is unaffected).
- The cover image comes from the author’s machine. The Claude Code plugin uploads its local render after publish, so a Cardinal with no one using the plugin shows only summary cards.
Upgrading to acts
Acts change what a public link may show, so the database and the public read paths learned about acts one release before anything could add one. v1.97.21 is that release: it can’t create acts, but it already shows only the acts a link covers.
Upgrade through v1.97.21. If you upgrade straight from a release older than v1.97.21 to one with storyboard__add_act, then during that rolling upgrade a pod still on the old release doesn’t know about acts. If someone opens a new act on a published storyboard while old pods are still serving, those pods show the draft act’s scenes on the storyboard’s existing public links. Either:
- upgrade to v1.97.21 first, let every pod roll, then upgrade to the release you want; or
- pause storyboard authoring until every pod runs the new release.
Nothing else changes for operators: acts need no new setting, environment variable or chart value, and storyboards created before the upgrade become single-act storyboards with no migration step of yours.
Personal-workspace quotas
Personal workspaces have daily quotas. Team orgs are never metered. Override the defaults with positive integers:
| Variable | Default |
|---|---|
PERSONAL_WORKSPACE_MAX_PUBLISHES_PER_DAY | 20 |
PERSONAL_WORKSPACE_MAX_EVIDENCE_BYTES_PER_DAY | 52428800 (50 MiB) |
PERSONAL_WORKSPACE_MAX_PUBLIC_VIEWS_PER_DAY | 5000 |
Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.
Session-owned visualization
Visualization authoring runs in the connected agent session when the user requests an update or publication. A publish request refreshes and previews the scenes before publishing; there are no recurring end-of-work offers or stop-hook update prompts. Draft-status storyboards are author-only, while published storyboards are visible to org members. No server LLM configuration, generation queue, or generation endpoint is needed. The server retains evidence capture, activity, authoring APIs, validation, viewing, and publishing.
Upgrade the server and agent plugins together. Existing scenes and published snapshots remain available. Historical projection tables are retained for compatibility and rollback; the new server does not run their jobs. Remove STORYBOARD_PROJECTION_* settings from deployment values; this release ignores them. Before rolling back to an older server, keep STORYBOARD_PROJECTION_ENABLED=false so old background or queued work cannot resume.
INVESTIGATION_OWNER_INPUT_ENABLED remains an independent, optional capability. It is not required for session-owned visualization. A visualization update does not upload the session transcript: the agent authors scenes with selected evidence references.