1 Prerequisites
Hardware Requirements
| Component | Minimum (Dev / Eval) | Recommended (Production) |
|---|---|---|
| CPU | 4 cores | 8+ cores |
| RAM | 16 GB | 32 GB |
| Storage | 50 GB SSD | 100 GB SSD |
| GPU (for local LLM) | NVIDIA GPU, 16 GB VRAM | NVIDIA GPU, 24+ GB VRAM |
The GPU is required for running the local LLM (Ollama with qwen3:14b). Alternatively, you can use a remote Ollama instance or a cloud LLM provider (OpenAI, Anthropic).
Production Sizing Guide
LLM inference is the primary bottleneck. A single request takes ~20 seconds (4 agent steps, 1 tool call). Ollama serializes GPU requests, so concurrent users experience linear latency increase.
| Team Size | LLM Backend | GPU | Notes |
|---|---|---|---|
| 1–3 users | Ollama | 16 GB VRAM (e.g. RTX 5070 Ti) | Sufficient for evaluation and small teams. Sequential processing. |
| 5–20 users | vLLM | 24+ GB VRAM (e.g. RTX 5090) | Batched inference enables concurrent requests. Significant throughput improvement over Ollama. |
| 20+ users | vLLM or Cloud LLM | 48+ GB VRAM or multi-GPU | Consider cloud LLM providers (OpenAI, Anthropic) for large teams to avoid GPU infrastructure complexity. |
Why vLLM for production? Ollama processes requests sequentially — with 5 concurrent users, response times exceed 2 minutes and requests start timing out. vLLM uses continuous batching and PagedAttention to serve multiple requests simultaneously, but requires at least 24 GB VRAM for the KV cache headroom needed by qwen3:14b.
To enable vLLM, set these environment variables:
REVA_VLLM_URL=http://gpu-server:8100/v1
REVA_VLLM_API_KEY=any-string
The Ollama router model (llama3.2:3b) must remain on a separate Ollama instance to avoid GPU contention. See src/reva/vllm_client.py for details.
Recommended Models
Reva requires models with strong tool-calling (function calling) capabilities and multilingual support. Not all models perform equally well — the following recommendations are based on extensive testing with Reva's agent loop:
| Model | Size | Rating | Notes |
|---|---|---|---|
qwen3:14b | 14B | Best choice | Excellent tool calling, reliable output format, strong multilingual (DE/EN/FR/ES/NL). Default agent model. |
qwen3:32b | 32B | Excellent | Even better quality, but requires 24+ GB VRAM and is slower. Good for vLLM deployments. |
gemma3:27b | 27B | Good | Good tool calling, but occasional formatting inconsistencies in structured output. |
llama3.3:70b | 70B | Good | Strong general performance, requires significant GPU resources. Better for cloud/multi-GPU setups. |
mistral-small3.2 | 24B | Moderate | Usable but less reliable tool calling compared to Qwen3. |
qwen2.5-coder:32b | 32B | Moderate | Good quality, but too slow for interactive use on a single GPU. |
Cloud LLM models: When using OpenAI or Anthropic, models like gpt-4o or claude-sonnet-4-5-20250514 deliver excellent results. Cloud models eliminate GPU requirements entirely and scale to any team size.
The router model (llama3.2:3b) classifies incoming messages and does not require tool-calling capabilities. It runs on Ollama regardless of the agent model backend.
Software Requirements
| Development | Test / Acceptance / Production | |
|---|---|---|
| Runtime | Docker Engine 24+ & Docker Compose v2 | k3s (lightweight Kubernetes) |
| Build | Docker (builds locally) | Docker (for image build) + kubectl |
| LLM | Ollama (local or remote) — or a cloud LLM API key | |
| Registry | Access to ghcr.io/x-idra-systems-gmbh/reva (credentials provided by X-idra) | |
Network Requirements
- HTTPS endpoint publicly reachable from Azure Bot Framework (e.g. via reverse proxy with TLS termination)
- Outbound access to
login.microsoftonline.comandsmba.trafficmanager.net(Teams) - Access to your Digital.ai Release instance (HTTP/HTTPS)
- Access to Jira Cloud (HTTPS) — if using Jira integration
2 Azure Bot Registration
Reva communicates with Microsoft Teams through the Azure Bot Framework. You need to register a bot in your Azure tenant.
2.1 Create an App Registration
- Go to Azure Portal → Microsoft Entra ID → App registrations → New registration
- Name:
Reva - Supported account types: Accounts in this organizational directory only (Single Tenant)
- Click Register
- Go to Certificates & secrets → New client secret
- Copy the secret value immediately — it is shown only once
Record these three values — you will need them later:
Application (client) ID, Directory (tenant) ID, and the Client secret.
2.2 Create an Azure Bot Resource
- In Azure Portal, search for Azure Bot → Create
- Bot handle:
Reva - Pricing tier: F0 (free — sufficient for Teams)
- App type: Single Tenant
- Use existing app registration → enter the App ID from step 2.1
- Data residency: Local (EU: westeurope recommended)
2.3 Configure Messaging Endpoint
In the Azure Bot resource, go to Configuration and set the messaging endpoint:
https://your-domain.example.com/api/messages
2.4 Enable Teams Channel
- In the Azure Bot resource, go to Channels
- Click Microsoft Teams (Commercial) → Apply
3 Download & Authenticate
3.1 Extract the Deployment Package
Download the deployment package provided by X-idra and extract it:
tar xzf reva-1.0.4.tar.gz
cd reva-1.0.4
3.2 Authenticate with the Container Registry
Log in to the GitHub Container Registry using the credentials provided by X-idra:
echo "$GHCR_TOKEN" | docker login ghcr.io -u "$GHCR_USER" --password-stdin
3.3 Pull the Reva Image
docker compose pull
Pin the version in your .env file: REVA_VERSION=1.0.4. The docker-compose.yml uses this variable to select the image tag.
4 Generate Secrets
All sensitive credentials are stored as files in secrets/ (gitignored). Both Docker Compose and Kubernetes deployments use these same files.
./bin/generate-secrets.sh
The script auto-generates a PostgreSQL admin password, SSL certificates (self-signed CA + server cert), a database URL secret file, and a webhook secret, then prompts for:
| Secret File | Description | Source |
|---|---|---|
reva_microsoft_app_password | Azure App client secret | Step 2.1 above |
reva_release_password | Digital.ai Release password | Release admin (basic auth) |
reva_release_token | Digital.ai Release API token | Release admin (token auth) |
reva_ldap_bind_password | LDAP bind password | Your LDAP administrator |
reva_jira_token | Jira Cloud API token | Atlassian API tokens |
You only need to provide the secrets relevant to your setup. Skip any that don't apply.
5 Configure Environment
cp .env.example .env
Required Settings
| Variable | Description | Example |
|---|---|---|
OLLAMA_URL | Ollama API endpoint | http://localhost:11434 |
REVA_MICROSOFT_APP_ID | Azure App ID (from step 2.1) | d57d6dd5-4399-... |
REVA_MICROSOFT_APP_TENANT_ID | Azure Tenant ID (from step 2.1) | 847e08d2-a338-... |
REVA_RELEASE_BASE_URL | Digital.ai Release API URL | http://release:5516 |
REVA_RELEASE_AUTH_TYPE | basic or token | token |
LLM Model Setup
Reva uses two models: a small router model for message classification and a larger agent model for tool-calling:
ollama pull llama3.2:3b # Router (fast, small)
ollama pull qwen3:14b # Agent (tool-calling, multilingual)
ollama pull nomic-embed-text # Embeddings (for cross-session memory)
Do not set AGENT_MODEL in your .env file. The agent model is configured per role in config/agent_roles.yaml. Setting AGENT_MODEL would override the router model and degrade performance.
Cloud LLM Providers (Alternative)
Instead of Ollama, you can use a cloud LLM provider:
REVA_OPENAI_API_KEY=sk-... # OpenAI
REVA_ANTHROPIC_API_KEY=sk-ant-... # Anthropic Claude
6 Deploy
Choose your deployment target:
Docker Compose (Development & Evaluation)
The fastest way to get Reva running. MCP servers are spawned as Docker containers via the Docker socket.
docker compose up -d
Pin the version in your .env file: REVA_VERSION=1.0.4
This starts three services:
Wait for all services to become healthy:
docker compose ps
Expected output — all services show Up (healthy):
NAME STATUS PORTS
reva Up (healthy) 0.0.0.0:3978→8000/tcp
reva-postgres Up (healthy) 5432/tcp
reva-redis Up (healthy) 6379/tcp
Docker Compose mounts the Docker socket (/var/run/docker.sock) to spawn MCP server containers. This approach is simple but not suitable for production Kubernetes environments.
Reverse Proxy (TLS)
Place a reverse proxy in front of Reva to terminate TLS. Example HAProxy backend:
backend reva
server reva 127.0.0.1:3978 check
Database Backup
# Manual backup
./bin/backup-db.sh
# Automated (add to crontab)
0 2 * * * /path/to/reva/bin/backup-db.sh
Backups are saved to backups/ with 30-day retention.
Kubernetes (Test / Acceptance / Production)
Production-grade deployment on k3s. MCP servers run as sidecar containers in the same pod using SSE transport — no Docker socket required.
6.1 Install k3s
# Install k3s (single-node, includes Traefik ingress)
curl -sfL https://get.k3s.io | sh -
# Set up kubeconfig
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
# Verify
kubectl get nodes
k3s adds only ~512 MB RAM overhead and includes Traefik as the default ingress controller. No additional load balancer setup required.
6.2 Deploy with the Deploy Script
The deploy script handles everything: image build, secret import, manifest application, and health check.
# Full deploy (build image + create secrets + apply manifests)
./bin/k8s-deploy.sh
# Or step by step:
./bin/k8s-deploy.sh --build-only # Build image and import to k3s
./bin/k8s-deploy.sh --secrets # Create/update Kubernetes secrets
./bin/k8s-deploy.sh --apply-only # Apply manifests only (no build)
Architecture
Security hardening: Both Docker Compose and Kubernetes deployments include PostgreSQL user restriction (app user has no superuser privileges), PostgreSQL SSL encryption, and secrets management via Docker secrets / K8s Secrets. See docs/security-hardening.md for the full hardening guide.
Key difference from Docker Compose: MCP servers run as sidecar containers in the same pod, communicating via SSE on localhost instead of Docker stdio. The k8s-specific MCP config (config/mcp_servers.k8s.yaml) is automatically mounted.
6.3 Verify Deployment
# Check all pods are running
kubectl get pods -n reva
# Expected: 3/3 READY for reva, 1/1 for postgres and redis
NAME READY STATUS RESTARTS AGE
reva-xxxxx-yyyyy 3/3 Running 0 2m
postgres-0 1/1 Running 0 2m
redis-xxxxx-yyyyy 1/1 Running 0 2m
6.4 Operations
# View logs
kubectl logs -n reva -l app=reva -c reva -f # App
kubectl logs -n reva -l app=reva -c release-mcp -f # Release MCP
kubectl logs -n reva -l app=reva -c jira-mcp -f # Jira MCP
# Restart
kubectl rollout restart deployment/reva -n reva
# Manual database backup
kubectl create job --from=cronjob/db-backup db-backup-manual -n reva
# Rollback to previous version
kubectl rollout undo deployment/reva -n reva
6.5 Ingress & TLS
TLS is enabled by default via the Traefik websecure entrypoint. The k8s/ingress.yaml routes traffic through HTTPS. For custom hostnames, edit k8s/ingress.yaml. For production certs, use cert-manager or provide your own TLS secret.
# Generate self-signed TLS certificate
./bin/generate-k8s-tls.sh
# Or use cert-manager for production
# traefik.ingress.kubernetes.io/router.entrypoints: websecure
# cert-manager.io/cluster-issuer: letsencrypt-prod
6.6 ConfigMap Customization
Non-secret environment variables are stored in k8s/configmap.yaml. After editing, apply changes:
kubectl apply -k k8s/
kubectl rollout restart deployment/reva -n reva
7 Teams App Sideloading
7.1 Prepare the App Package
Run the manifest configurator script. It prompts for your Azure App ID and bot endpoint domain, then creates the Teams app package:
./bin/configure-manifest.sh
You only need to provide two values:
- Azure App ID — from step 2.1 (used for both
idandbotId) - Bot endpoint domain — e.g.
revaapi.example.com
The developer section (company name, URLs) stays as X-idra Systems GmbH.
Manual alternative: Edit appPackage/manifest.json directly — replace {{AZURE_APP_ID}} and {{BOT_DOMAIN}}, then zip: cd appPackage && zip ../reva-teams-app.zip manifest.json color.png outline.png
7.2 Enable Custom App Uploads
In the Teams Admin Center → Teams apps → Setup policies → enable Upload custom apps.
7.3 Sideload the App
- Open Microsoft Teams → Apps → Manage your apps → Upload an app
- Select Upload a custom app → choose
reva-teams-app.zip - Click Add
8 Verify Installation
Health Check
curl http://localhost:3978/api/health
kubectl exec -n reva deploy/reva -c reva -- \
python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8000/api/health').read().decode())"
Expected response:
{
"status": "ok",
"adapter_initialized": true,
"db": true,
"mcp": {
"release": { "connected": true, "tools": 38 },
"jira": { "connected": true, "tools": 29 }
}
}
Functional Test
In Microsoft Teams, send these messages to Reva:
- “Hello” — Reva should greet you
- “List all active releases” — Reva should query Release and show results
- “Show my dashboard” — personal release overview
9 Optional Integrations
Jira Cloud
REVA_JIRA_URL=https://yourorg.atlassian.net
REVA_JIRA_USERNAME=your-email@company.com
Ensure the reva_jira_token secret file contains a valid Atlassian API token.
LDAP Group Resolution
REVA_LDAP_URL=ldap://ldap.company.com:389
REVA_LDAP_BIND_DN=cn=reva,ou=services,dc=company,dc=com
REVA_LDAP_GROUP_BASE=ou=groups,dc=company,dc=com
Release Webhook Notifications
Copy plugins/xlr-reva-notify-plugin-1.0.4.jar to your Digital.ai Release server's plugin directory and restart Release. Then point the webhook to:
https://your-domain.example.com/api/notify
Autonomous Monitoring
REVA_MONITOR_ENABLED=true
REVA_MONITOR_INTERVAL=300
REVA_MONITOR_OVERDUE_THRESHOLD_HOURS=24
REVA_MONITOR_STALE_APPROVAL_HOURS=48
User Authorization
REVA_AUTH_ENABLED=true
REVA_AUTH_USER_MAP=TeamsName1=releaseUser1,TeamsName2=releaseUser2
Cross-Session Memory
Reva can remember user preferences and context across conversations. Memories are stored per user with semantic deduplication and automatic cleanup.
MEMORY_ENABLED=true
MEMORY_EXTRACTION_ENABLED=true
Requires the nomic-embed-text embedding model and pgvector (included in the default PostgreSQL image).
GDPR: Users can type show memories to see what Reva remembers, and forget memories to delete all stored memories. Memories are soft-deleted with an audit trail.
10 Troubleshooting
Cannot pull image
If docker compose pull fails with an authentication error:
- Verify you are logged in:
docker login ghcr.io - Check that your
GHCR_TOKENhas not expired - Ensure
REVA_VERSIONin.envmatches a published version
Health check returns 503
MCP servers failed to connect. Check credentials, network access, and logs:
docker compose logs reva | grep -i "mcp\|error"
kubectl logs -n reva -l app=reva -c reva | grep -i "mcp\|error"
kubectl logs -n reva -l app=reva -c release-mcp
kubectl logs -n reva -l app=reva -c jira-mcp
Teams messages not arriving
- Verify the messaging endpoint in Azure Bot Configuration matches your public URL
- Check that HTTPS is correctly terminated
- Ensure
REVA_MICROSOFT_APP_IDandREVA_MICROSOFT_APP_TENANT_IDare set - Check logs for JWT validation errors
MCP containers not starting (Docker Compose)
docker ps # Check Docker socket access
docker pull xebialabsearlyaccess/dai-release-mcp:25.3.1-beta.212
docker pull ghcr.io/sooperset/mcp-atlassian:0.21.0
MCP sidecars not ready (Kubernetes)
# Check sidecar status
kubectl describe pod -n reva -l app=reva
# Verify ConfigMaps exist
kubectl get configmap -n reva
LLM responses are slow
- Ensure Ollama runs on a machine with a GPU
- Do not set
OLLAMA_NUM_PARALLEL> 1 with less than 24 GB VRAM - Agent model is configured in
config/agent_roles.yaml, not in.env
Getting Help
Contact us at info@x-idra.de.
What’s Next
Installation complete? Here’s what to do next:
- Getting Started Guide — Your first 10 minutes with Reva: example queries, tips, and troubleshooting
- Compatibility Matrix — Supported versions of Release, Jira, Kubernetes, Docker, Ollama, and GPUs
- Monitoring Setup — Prometheus + Grafana dashboard for production observability
- Capacity Planning — GPU sizing, users per instance, and scaling guidance
- Upgrade Guide — Step-by-step version upgrades and rollback procedures
- Support & SLA — Support tiers, response times, and escalation process