Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Environment:OpenHands OpenHands SaaS Server Environment

From Leeroopedia
Knowledge Sources
Domains SaaS_Infrastructure, Server_Architecture
Last Updated 2026-02-11 21:00 GMT

Overview

Python 3.12+ SaaS server environment requiring PostgreSQL, Redis, Keycloak identity provider, LiteLLM proxy, and Stripe billing integration.

Description

This environment defines the full stack for running the OpenHands enterprise SaaS server. It is built on Python 3.12+ with FastAPI as the web framework, PostgreSQL as the primary database (with GCP Cloud SQL support), Redis for distributed state management and pub/sub, Keycloak for identity/authentication, LiteLLM as an LLM proxy, and Stripe for billing. The server runs as a uvicorn ASGI application on port 3000. The enterprise image extends the base OpenHands Docker image with additional enterprise dependencies including Datadog APM tracing, PostHog analytics, scikit-learn for solvability analysis, and Alembic for database migrations.

Usage

Use this environment for deploying the SaaS Server Assembly workflow and all Conversation Lifecycle Management workflows. It is the mandatory prerequisite for running the enterprise server, clustered conversation manager, organization onboarding, and all integration webhook handlers (GitHub, GitLab, Slack, Jira, Linear).

System Requirements

Category Requirement Notes
OS Linux (Ubuntu 22.04+ or equivalent) Docker containers use Python 3.13.7 slim base; dev containers use Ubuntu 22.04
Runtime Python >= 3.12, < 3.14 Specified in both root and enterprise pyproject.toml
Database PostgreSQL 12+ With asyncpg for async operations and pg8000 for sync; GCP Cloud SQL connector supported
Cache/Messaging Redis >= 5.2, < 7 Required for clustered mode; used for pub/sub, distributed locks, and rate limiting
Identity Keycloak server External dependency for OAuth/OIDC authentication
Container Docker For runtime sandbox management; Docker socket mount required
Disk 50GB+ SSD For application, dependencies, and Docker images

Dependencies

System Packages

  • `python` >= 3.12, < 3.14
  • `postgresql-client` (for database migrations)
  • `redis-server` >= 5.2 (or managed Redis)
  • `docker` (for sandbox runtime management)
  • `git`, `git-lfs`
  • `curl`, `build-essential` (for native extensions)

Python Packages (Core)

  • `fastapi` (ASGI web framework)
  • `uvicorn` (ASGI server)
  • `sqlalchemy[asyncio]` >= 2.0.40
  • `asyncpg` >= 0.30
  • `pg8000` >= 1.31.2
  • `redis` >= 5.2, < 7
  • `litellm` >= 1.74.3 (excludes 1.64.4 and 1.67.*)
  • `openai` == 2.8 (pinned due to litellm incompatibility)
  • `python-socketio` == 5.13
  • `tenacity` >= 8.5, < 10
  • `python-jose[cryptography]` >= 3.3
  • `python-dotenv`
  • `pyyaml` >= 6.0.2
  • `requests` >= 2.32.5

Python Packages (Enterprise)

  • `alembic` >= 1.14.1 (database migrations)
  • `stripe` >= 11.5.0 (billing)
  • `python-keycloak` >= 5.3.1 (identity)
  • `slack-sdk` >= 3.35.0 (Slack integration)
  • `ddtrace` == 3.13.0 (Datadog APM; pinned to avoid yanked 3.12.4)
  • `posthog` >= 6.0.0 (analytics)
  • `scikit-learn` >= 1.7.0 (solvability analysis)
  • `shap` >= 0.48.0 (ML explainability)
  • `google-cloud-recaptcha-enterprise` >= 1.24.0 (bot protection)
  • `resend` >= 2.7.0 (email delivery)
  • `mcp` >= 1.10.0 (Model Context Protocol)
  • `cloud-sql-python-connector` >= 1.16.0 (GCP database)
  • `coredis` >= 4.22.0 (async Redis)

Credentials

The following environment variables must be set for full SaaS server operation:

Database:

  • `DB_HOST`: PostgreSQL host (default: localhost)
  • `DB_PORT`: PostgreSQL port (default: 5432)
  • `DB_NAME`: Database name (default: openhands)
  • `DB_USER`: Database user (default: postgres)
  • `DB_PASS`: Database password (default: postgres)
  • `GCP_DB_INSTANCE`: GCP Cloud SQL instance (optional, for GCP deployments)
  • `GCP_PROJECT`: GCP project ID (optional)
  • `GCP_REGION`: GCP region (optional)

Redis:

  • `REDIS_HOST`: Redis host (default: localhost)
  • `REDIS_PORT`: Redis port (default: 6379)
  • `REDIS_PASSWORD`: Redis password (default: empty)
  • `REDIS_DB`: Redis database number (default: 0)

Identity (Keycloak):

  • `KEYCLOAK_SERVER_URL`: Keycloak server internal URL
  • `KEYCLOAK_SERVER_URL_EXT`: Keycloak external URL (for browser redirects)
  • `KEYCLOAK_REALM_NAME`: Keycloak realm name
  • `KEYCLOAK_CLIENT_ID`: OAuth client ID
  • `KEYCLOAK_CLIENT_SECRET`: OAuth client secret
  • `KEYCLOAK_ADMIN_PASSWORD`: Admin password (for sync operations)
  • `AUTH_URL`: Authentication service URL
  • `AUTH_WEB_HOST`: Authentication web host

LLM Proxy:

Billing:

  • `STRIPE_API_KEY`: Stripe API key
  • `REQUIRE_PAYMENT`: Enable payment requirement (0/1)
  • `ENABLE_BILLING`: Enable billing features (true/false)
  • `DEFAULT_INITIAL_BUDGET`: Initial credit budget (default: 10)

Analytics:

Application:

  • `WEB_HOST`: Application hostname (default: app.all-hands.dev)
  • `OPENHANDS_CONFIG_CLS`: Server config class override
  • `CONVERSATION_MANAGER_CLASS`: Conversation manager implementation class

Quick Install

# Install core dependencies (root project)
pip install openhands-ai

# Install enterprise dependencies
cd enterprise && poetry install

# Run database migrations
alembic upgrade head

# Start the server
uvicorn enterprise.saas_server:app --host 0.0.0.0 --port 3000

Code Evidence

Database configuration from `enterprise/migrations/env.py:11-15`:

DB_USER = os.getenv('DB_USER', 'postgres')
DB_PASS = os.getenv('DB_PASS', 'postgres')
DB_HOST = os.getenv('DB_HOST', 'localhost')
DB_PORT = os.getenv('DB_PORT', '5432')
DB_NAME = os.getenv('DB_NAME', 'openhands')

Redis client creation from `enterprise/storage/redis.py:6-19`:

REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = int(os.environ.get('REDIS_PORT', '6379'))
REDIS_PASSWORD = os.environ.get('REDIS_PASSWORD', '')
REDIS_DB = int(os.environ.get('REDIS_DB', '0'))

def create_redis_client():
    return redis.Redis(
        host=REDIS_HOST,
        port=REDIS_PORT,
        password=REDIS_PASSWORD,
        db=REDIS_DB,
        socket_timeout=2,
    )

LiteLLM proxy configuration from `enterprise/server/constants.py:42-46`:

LITE_LLM_API_URL = os.environ.get(
    'LITE_LLM_API_URL', 'https://llm-proxy.app.all-hands.dev'
)
LITE_LLM_TEAM_ID = os.environ.get('LITE_LLM_TEAM_ID', None)
LITE_LLM_API_KEY = os.environ.get('LITE_LLM_API_KEY', None)

Python version constraint from `pyproject.toml:13`:

requires-python = ">=3.12,<3.14"

Common Errors

Error Message Cause Solution
`ModuleNotFoundError: No module named 'asyncpg'` Missing PostgreSQL async driver `pip install asyncpg>=0.30`
`redis.exceptions.ConnectionError` Redis not running or unreachable Start Redis: `docker run -p 6379:6379 --name openhands-redis -d redis`
`KeyError: 'STRIPE_API_KEY'` Missing Stripe configuration Set `STRIPE_API_KEY` environment variable or set `REQUIRE_PAYMENT=0`
`litellm.exceptions.BadRequestError` Incompatible litellm/openai versions Ensure `openai==2.8` and `litellm>=1.74.3` (not 1.64.4 or 1.67.*)
`alembic.util.exc.CommandError: Can't locate revision` Database migrations out of sync Run `alembic upgrade head` from enterprise directory

Compatibility Notes

  • GCP Cloud SQL: When `GCP_DB_INSTANCE` is set, the server uses Google Cloud SQL Connector instead of direct PostgreSQL. Requires `cloud-sql-python-connector` and appropriate GCP credentials.
  • Clustered Mode: Requires `REDIS_HOST` to be set. Without Redis, the server runs in standalone mode with no cross-instance coordination.
  • Docker Socket: The server needs access to `/var/run/docker.sock` for sandbox runtime management. In containerized deployments, mount the host Docker socket.
  • ddtrace Pinning: Enterprise pins `ddtrace==3.13.0` to avoid a yanked version (3.12.4). Do not upgrade without checking the PyPI release status.
  • openai Pinning: `openai==2.8` is pinned because newer versions cause incompatibilities with litellm. This is a known constraint.

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment