## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# Customer-Managed Air-Gapped Installs

Use this guide when Pretorin is installed from a customer-managed or air-gapped deployment bundle and the CLI needs to talk to that private platform instead of the hosted Pretorin service.

The platform bundle owns Kubernetes install, data seeding, embedding, and AI provider validation. The CLI owns developer and agent access to the installed platform.

## Security Notes

Do not paste secret values, decoded Kubernetes secrets, API tokens, model API keys, or full environment dumps into support tickets or chat. The commands below intentionally check non-secret configuration values or secret key names only.

When validating secrets, confirm that required keys exist without decoding their values:

    kubectl get secret -n pretorin pretorin-platform-secrets \
      -o go-template='{{range $k, $_ := .data}}{{println $k}}{{end}}'

## Platform Validation

After the platform is installed and object storage is initialized, run the bundle smoke test from the deployment bundle:

    NAMESPACE=pretorin scripts/customer/validate-airgap-install.sh

The smoke test runs inside the deployed API pod and verifies:

- database connectivity
- seeded framework, package, source, document requirement, and crosswalk data
- NIST 800-53 catalog presence
- OSCAL control embedding coverage and vector dimensions
- direct local AI provider chat and embedding calls
- API-to-AI service connectivity
- dashboard AI chat streaming and chat message persistence

For staged troubleshooting, skip chat first:

    NAMESPACE=pretorin scripts/customer/validate-airgap-install.sh --skip-chat

That confirms data seeding, embeddings, provider reachability, and AI service health before testing the full streaming chat path.

## CLI Configuration

Point the CLI at the private platform public API endpoint:

    pretorin config set platform_api_base_url https://<platform-host>/api/v1/public
    pretorin config set model_api_base_url https://<platform-host>/api/v1/public/model
    pretorin whoami
    pretorin frameworks list

`pretorin config set platform_api_base_url` prompts for an API key for the new endpoint and validates it before saving the change.

For non-interactive hosts, use environment variables:

    export PRETORIN_API_KEY=<platform-api-token>
    export PRETORIN_PLATFORM_API_BASE_URL=https://<platform-host>/api/v1/public
    export PRETORIN_MODEL_API_BASE_URL=https://<platform-host>/api/v1/public/model

    pretorin whoami
    pretorin frameworks list

If you use MCP, the MCP server inherits the same CLI configuration:

    pretorin mcp-serve

For Codex, Claude, Cursor, and other MCP client setup, see MCP Setup Guides.

## Agent Runtime Notes

For `pretorin agent run`, model credential precedence is:

1. `OPENAI_API_KEY`
2. `config.api_key`
3. `config.openai_api_key`

If you want the agent runtime to use the customer platform model endpoint, keep `PRETORIN_MODEL_API_BASE_URL` pointed at:

    https://<platform-host>/api/v1/public/model

If `OPENAI_API_KEY` is set in the shell, it overrides stored Pretorin credentials for model calls. Unset it when you expect model calls to route through the customer Pretorin platform.

## Common Issues

Symptom | Likely cause | First check or fix
--- | --- | ---
`pretorin whoami` or `pretorin frameworks list` hits hosted Pretorin | CLI base URL is still using hosted config | Run `pretorin config list`, then set `platform_api_base_url` to `https://<platform-host>/api/v1/public`.
CLI returns 401 or 403 | API key is for another endpoint, expired, or missing required scopes | Run `pretorin login` or `pretorin config set platform_api_base_url ...` and enter a token from the customer platform.
`pretorin agent run` uses the wrong model credentials | Shell `OPENAI_API_KEY` overrides stored CLI credentials | Unset shell `OPENAI_API_KEY`, or intentionally set `PRETORIN_MODEL_API_BASE_URL` for the customer endpoint.
`AI provider validation failed` during platform install | `OPENAI_BASE_URL` is wrong, missing `/v1`, or unreachable from the cluster | In the deployment environment, run `python -m app.cli.validate_ai_provider` inside the API pod and confirm DNS, port, TLS, and provider path.
Provider calls time out | NetworkPolicy blocks API or AI egress to the local model endpoint | Add matching API and AI NetworkPolicy egress rules, then rerun Helm upgrade.
`OPENAI_API_KEY is required` or provider env is missing | Platform secret was not created or was created before env vars were exported | Rerun `scripts/customer/create-customer-secrets.sh`, then restart API and AI deployments.
Embedding count is zero or below the control count | The embedding hook failed, is still running, or the API does not have the local embedding model env | Check `pretorin-api-embedding-sync-*` job logs and confirm API env includes `OPENAI_BASE_URL` and `OPENAI_EMBEDDING_MODEL`.
Embedding dimension mismatch | Local embedding model does not return 1536-dimensional vectors | Use a 1536-dimension embedding model for `OPENAI_EMBEDDING_MODEL`.
Data seeding fails or NIST 800-53 is missing | Framework seed hook did not complete | Check `pretorin-api-seed-frameworks-*` job logs and rerun Helm upgrade after fixing the error.
Smoke test passes with `--skip-chat` but fails without it | Provider supports basic calls but not streaming chat, tool calling, or the configured chat model | Confirm the model supports streaming chat completions and tool calls; update `OPENAI_MODEL` if needed.
Chat stream emits an error after a session is created | AI service can start the request but failed during agent execution | Check `deployment/pretorin-ai` logs around the smoke-test timestamp.

Useful platform-side checks:

    kubectl get pods,jobs -n pretorin
    kubectl logs -n pretorin job/<failed-job-name>

    kubectl exec -n pretorin deployment/pretorin-api -- \
      sh -c 'env | grep -E "^(OPENAI_BASE_URL|OPENAI_MODEL|OPENAI_EMBEDDING_MODEL|OPENAI_USE_RESPONSES|AI_REQUIRE_LOCAL_PROVIDER|AI_PROVIDER_KIND|AI_PROVIDER_DEFAULT_PROFILE_ID|AI_PROVIDER_DEFAULT_PROFILE_NAME|AI_SERVICE_URL)="'

    kubectl exec -n pretorin deployment/pretorin-ai -- \
      sh -c 'env | grep -E "^(OPENAI_BASE_URL|OPENAI_MODEL|OPENAI_EMBEDDING_MODEL|OPENAI_USE_RESPONSES|AI_REQUIRE_LOCAL_PROVIDER|AI_PROVIDER_KIND|AI_PROVIDER_DEFAULT_PROFILE_ID|AI_PROVIDER_DEFAULT_PROFILE_NAME|AI_SERVICE_URL)="'

## What Passing Looks Like

A healthy install can:

- return `pretorin whoami`
- list seeded frameworks with `pretorin frameworks list`
- run `scripts/customer/validate-airgap-install.sh` without failures
- use chat in the web UI
- route MCP tools through `pretorin mcp-serve`
- route `pretorin agent run` through the configured customer model endpoint