Skip to main content

Installation Guide

Deploy STOA Platform on any Kubernetes cluster using Helm. This guide covers prerequisites, chart installation, configuration, and post-install verification.

Prerequisites​

RequirementVersionPurpose
Kubernetes1.28+Container orchestration
Helm3.12+Chart deployment
kubectl1.28+Cluster management
PostgreSQL15+Control Plane database
Keycloak24+Identity and access management

Optional Components​

ComponentVersionPurpose
Prometheus2.50+Metrics collection
Grafana10+Dashboard visualization
OpenSearch2.11+Audit logs and search
Redpanda/Kafka23.3+Event streaming (metering)

Resource Requirements​

ProfileNodesCPU (total)RAM (total)Use Case
Starter14 vCPU8 GBDevelopment, evaluation
Standard312 vCPU24 GBSmall production (up to 100 APIs)
Enterprise5+24+ vCPU48+ GBLarge production (100+ APIs)

See Hardware Requirements for detailed sizing guidance.

Quick Install​

# Add the STOA Helm repository
helm repo add stoa https://charts.gostoa.dev
helm repo update

# Create namespace
kubectl create namespace stoa-system

# Install with default values
helm install stoa-platform stoa/stoa-platform \
-n stoa-system \
--set stoaGateway.keycloakUrl="https://auth.<YOUR_DOMAIN>"

Helm Chart Reference​

Chart Metadata​

FieldValue
Chart namestoa-platform
Chart version0.1.0
App version2.0.0
Typeapplication

Installation from Source​

# Clone the repository
git clone https://github.com/stoa-platform/stoa.git
cd stoa

# Lint the chart
helm lint charts/stoa-platform

# Install from local chart
helm install stoa-platform ./charts/stoa-platform \
-n stoa-system \
--create-namespace \
-f my-values.yaml

Values Reference​

STOA Gateway (Rust)​

The primary production gateway. Handles MCP protocol, JWT authentication, rate limiting, and API proxying.

stoaGateway:
enabled: true
image:
repository: ghcr.io/stoa-platform/stoa-gateway
tag: latest
replicas: 2

# Keycloak OIDC
keycloakUrl: "" # Required: https://auth.<YOUR_DOMAIN>
keycloakRealm: stoa
keycloakClientId: stoa-mcp-gateway

# Control Plane connection
controlPlaneUrl: "http://control-plane-api.stoa-system.svc.cluster.local:8000"

# Gateway mode (ADR-024)
mode: edge-mcp # Options: edge-mcp, sidecar, proxy, shadow

# Auto-registration (ADR-028)
autoRegister: true
environment: dev # Options: dev, staging, prod

# Resources
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi

# Secrets
secretName: stoa-gateway-secrets

# Logging
logLevel: info # Options: trace, debug, info, warn, error
logFormat: json # Options: json, text

OPA Policies​

stoaGateway:
opa:
enabled: true
policyPath: /etc/stoa/policies/default.rego

Kafka/Redpanda Metering​

stoaGateway:
kafka:
enabled: false
brokers: "redpanda.stoa-system.svc.cluster.local:9092"
topic: stoa.metering

Kubernetes Watcher​

stoaGateway:
k8sWatcher:
enabled: false # Enable CRD watching for Tool/ToolSet

ServiceMonitor (Prometheus)​

stoaGateway:
serviceMonitor:
enabled: true
interval: 15s
scrapeTimeout: 10s

Sidecar Mode​

For deploying alongside third-party gateways (Kong, webMethods, Envoy):

stoaSidecar:
enabled: false
gatewayType: webmethods # Options: webmethods, kong, envoy, apigee, generic
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi

Grafana OIDC​

grafana:
oidc:
enabled: false
clientId: stoa-observability
roleAttributePath: "contains(roles[*], 'stoa:admin') && 'Admin' || 'Viewer'"
rootUrl: "https://grafana.<YOUR_DOMAIN>"

OpenAPI Sync CronJob​

gatewayOpenapiSync:
enabled: true
schedule: "0 */6 * * *" # Every 6 hours

Custom Resource Definitions​

STOA ships 4 CRDs that must be applied before or alongside the Helm chart:

kubectl apply -f charts/stoa-platform/crds/

Tool CRD (tools.gostoa.dev/v1alpha1)​

Defines an individual API tool for MCP exposure:

apiVersion: gostoa.dev/v1alpha1
kind: Tool
metadata:
name: billing-list-invoices
namespace: tenant-acme
spec:
displayName: List Invoices
description: Retrieve all invoices for the current billing period
endpoint: https://billing.internal/v1/invoices
method: GET
inputSchema:
type: object
properties:
status:
type: string
enum: [paid, pending, overdue]
auth: bearer
rateLimit: "100/min"
annotations:
readOnly: true
idempotent: true

ToolSet CRD (toolsets.gostoa.dev/v1alpha1)​

Federates tools from an upstream MCP server:

apiVersion: gostoa.dev/v1alpha1
kind: ToolSet
metadata:
name: internal-mcp-server
namespace: tenant-acme
spec:
upstream:
url: http://mcp-server.internal:3000/mcp/sse
transport: sse
auth:
type: bearer
secretRef: mcp-server-token
timeoutSeconds: 30
tools: [] # Empty = discover all tools
prefix: internal # Prefix tool names: internal_*

GatewayInstance CRD (gatewayinstances.gostoa.dev/v1alpha1)​

Registers a gateway instance for multi-gateway orchestration:

apiVersion: gostoa.dev/v1alpha1
kind: GatewayInstance
metadata:
name: kong-production
namespace: stoa-system
spec:
displayName: Kong Production
gatewayType: kong
environment: prod
baseUrl: https://kong-admin.internal:8001
capabilities: [rest, rate_limiting]
mode: edge-mcp

GatewayBinding CRD (gatewaybindings.gostoa.dev/v1alpha1)​

Binds an API to a gateway instance with policies:

apiVersion: gostoa.dev/v1alpha1
kind: GatewayBinding
metadata:
name: billing-api-kong
namespace: stoa-system
spec:
apiRef:
name: billing-api
version: v1
gatewayRef:
name: kong-production
policies:
- name: rate-limit
type: rate_limit
config:
per_second: 100
per_minute: 5000

Post-Install Verification​

1. Check Pod Status​

kubectl get pods -n stoa-system

Expected output:

NAME                                 READY   STATUS    RESTARTS   AGE
stoa-gateway-xxx-yyy 1/1 Running 0 2m
control-plane-api-xxx-yyy 1/1 Running 0 2m

2. Verify Gateway Health​

Configure your environment

The examples below use environment variables. Set them for your STOA instance:

export STOA_API_URL="https://api.gostoa.dev"       # Replace with your domain
export STOA_AUTH_URL="https://auth.gostoa.dev" # Keycloak OIDC provider
export STOA_GATEWAY_URL="https://mcp.gostoa.dev" # MCP Gateway endpoint

Self-hosted? Replace gostoa.dev with your domain.

curl -s "${STOA_GATEWAY_URL}/health" | jq

Expected:

{
"status": "healthy",
"version": "2.0.0",
"mode": "edge-mcp"
}

3. Verify CRDs​

kubectl get crd | grep gostoa.dev

Expected:

gatewaybindings.gostoa.dev    2026-01-15T10:00:00Z
gatewayinstances.gostoa.dev 2026-01-15T10:00:00Z
tools.gostoa.dev 2026-01-15T10:00:00Z
toolsets.gostoa.dev 2026-01-15T10:00:00Z

4. Verify Metrics Endpoint​

curl -s "${STOA_GATEWAY_URL}/metrics" | head -5

You should see Prometheus-format metrics starting with stoa_.

Upgrade​

helm repo update
helm upgrade stoa-platform stoa/stoa-platform \
-n stoa-system \
-f my-values.yaml

CRD updates require manual application (Helm does not upgrade CRDs):

kubectl apply -f charts/stoa-platform/crds/

Uninstall​

helm uninstall stoa-platform -n stoa-system
kubectl delete namespace stoa-system

# Optional: remove CRDs (destroys all custom resources)
kubectl delete crd tools.gostoa.dev toolsets.gostoa.dev \
gatewayinstances.gostoa.dev gatewaybindings.gostoa.dev

Troubleshooting​

ProblemCauseFix
Pod CrashLoopBackOffMissing env vars or secretsCheck kubectl logs and verify secretName exists
Gateway 503 on startupKeycloak URL unreachableVerify keycloakUrl resolves from within the cluster
CRDs not foundCRDs not appliedRun kubectl apply -f charts/stoa-platform/crds/
Metrics not scrapedServiceMonitor labels mismatchEnsure prometheus: kube-prometheus-stack label matches
Sidecar gateway unreachableNetwork policy blockingCheck kubectl get networkpolicy -n stoa-system