Deployment
Operyn can be deployed locally with Docker Compose or to a Kubernetes cluster for production use.
Local Development (Docker Compose)
The quickest way to run the full stack locally.
Infrastructure Only
Start just the backing services (PostgreSQL, Redis, OpenSearch, Jaeger, Prometheus, OpenTelemetry Collector):
bun run infra:up
Then run application services in development mode:
bun run dev
Full Stack
Run everything — infrastructure and application services — in containers:
bun run docker:dev
This uses docker-compose.yml to start all services.
Production Containers (Prod Start)
Run everything in production-mode containers:
bun run docker:prod
This uses docker-compose.prod.yml to build and start the full stack in production mode (images are built locally from each service's Dockerfile).
It also loads configuration from .env (via env_file: .env in the compose file) and exposes these ports:
- Dashboard:
3000 - Services:
3001(ingestion),3003(core-platform),3006(docs) - Infrastructure:
5432(Postgres),6379(Redis),9200(OpenSearch),16686(Jaeger UI),9090(Prometheus),4317/4318(OTLP Collector)
To stop:
bun run docker:prod:down
Stopping
bun run infra:down
# or
docker compose down
Environment Variables
See the Environment Variables section in the README for the full list.
Key variables for deployment:
| Variable | Purpose |
|---|---|
POSTGRES_HOST / POSTGRES_PORT | Database connection |
REDIS_HOST / REDIS_PORT | Queue connection |
OPENSEARCH_HOST | Search/indexing connection |
LLM_PROVIDER | AI provider selection |
REMEDIATION_MODE | simulate or live |
OPERYN_API_KEY | API key for ingestion auth |
BETTER_AUTH_SECRET | Dashboard auth session signing secret |
BETTER_AUTH_URL | Dashboard base URL (used by auth links/tokens) |
BETTER_AUTH_TRUSTED_ORIGINS | Better Auth trusted origins (CSV) |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP collector endpoint used by services (http://otel-collector:4318 in Compose, http://localhost:4318 in local dev) |
OTEL_SERVICE_NAME_CORE_PLATFORM | Stable service name for core-platform telemetry |
OTEL_SERVICE_NAME_INGESTION | Stable service name for ingestion telemetry |
OTEL_TRACES_SAMPLER_RATIO | Trace sampling ratio (0..1) |
Docker Images
Primary runtime images:
services/ingestion/Dockerfile
services/core-platform/Dockerfile
apps/dashboard/Dockerfile
These are the only active backend runtime images. The legacy split-service images have been removed along with the retired backend services.
Build all images:
docker compose build
Kubernetes
The infra/k8s/ directory contains Kubernetes manifests for production deployment.
Considerations
- Ingestion: deploy with horizontal pod autoscaling — this is the highest-traffic service.
- Core Platform: size for combined incident, remediation, notification, and AI workflow load; if needed later, AI can be extracted again.
- Dashboard: standard Next.js deployment; can be served via a CDN.
Networking
- Use an Ingress to expose the Ingestion Service and Dashboard.
- Keep ingestion-to-core-platform and internal integrations private (ClusterIP services).
- The Ingestion Service should be the only externally-accessible backend endpoint.
Production Checklist
- Set
OPERYN_API_KEYfor ingestion auth. - Use
REMEDIATION_MODE=simulateinitially, switch toliveafter validation. - Configure Slack/Email/webhook dispatch in core-platform.
- Configure Jira via the Dashboard (encrypted-at-rest per-org credentials in core-platform).
- Set up TLS termination on the Ingress.
- Configure resource limits and HPA for the Ingestion Service.
- Set up database backups for PostgreSQL.
- Review Kubernetes RBAC for core-platform's service account.
- Route OTEL traces/metrics to your production backend (AWS X-Ray / CloudWatch on ECS).