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. config.api_key (from pretorin login against the customer platform)
  2. OPENAI_API_KEY
  3. config.openai_api_key

If the user passes --base-url explicitly (pointing the agent at a non-platform model endpoint), the order flips to OPENAI_API_KEY first, then falls back to the config keys.

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

When PRETORIN_MODEL_API_BASE_URL is set via env or config (without an explicit --base-url flag), the agent uses config.api_key from pretorin login against the customer platform, so shell OPENAI_API_KEY does not override it. Unset OPENAI_API_KEY only if you also pass --base-url and want the model call to land on a non-platform provider.

Common Issues

SymptomLikely causeFirst check or fix
pretorin whoami or pretorin frameworks list hits hosted PretorinCLI base URL is still using hosted configRun pretorin config list, then set platform_api_base_url to https://<platform-host>/api/v1/public.
CLI returns 401 or 403API key is for another endpoint, expired, or missing required scopesRun 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 credentialsExplicit --base-url flag flips precedence to OPENAI_API_KEY first, or stored openai_api_key config overrides the platform keyDrop --base-url and set PRETORIN_MODEL_API_BASE_URL to the customer endpoint so the agent uses config.api_key from pretorin login.
AI provider validation failed during platform installOPENAI_BASE_URL is wrong, missing /v1, or unreachable from the clusterIn 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 outNetworkPolicy blocks API or AI egress to the local model endpointAdd matching API and AI NetworkPolicy egress rules, then rerun Helm upgrade.
OPENAI_API_KEY is required or provider env is missingPlatform secret was not created or was created before env vars were exportedRerun scripts/customer/create-customer-secrets.sh, then restart API and AI deployments.
Embedding count is zero or below the control countThe embedding hook failed, is still running, or the API does not have the local embedding model envCheck pretorin-api-embedding-sync-* job logs and confirm API env includes OPENAI_BASE_URL and OPENAI_EMBEDDING_MODEL.
Embedding dimension mismatchLocal embedding model does not return 1536-dimensional vectorsUse a 1536-dimension embedding model for OPENAI_EMBEDDING_MODEL.
Data seeding fails or NIST 800-53 is missingFramework seed hook did not completeCheck pretorin-api-seed-frameworks-* job logs and rerun Helm upgrade after fixing the error.
Smoke test passes with --skip-chat but fails without itProvider supports basic calls but not streaming chat, tool calling, or the configured chat modelConfirm the model supports streaming chat completions and tool calls; update OPENAI_MODEL if needed.
Chat stream emits an error after a session is createdAI service can start the request but failed during agent executionCheck 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