diff --git a/docs/benchmarks.md b/docs/benchmarks.md index e601d9a0e..b882cae2d 100644 --- a/docs/benchmarks.md +++ b/docs/benchmarks.md @@ -179,10 +179,6 @@ litellm_settings: password: os.environ/REDIS_PASSWORD ``` -:::tip -Use `redis_host`, `redis_port`, and `redis_password` instead of `redis_url` for ~80 RPS better performance. -::: - **Scaling:** DB connections scale linearly with instances. Consider PostgreSQL read replicas beyond 5K RPS. See [Production Configuration](./proxy/prod) for detailed best practices. diff --git a/docs/index.md b/docs/index.md index 0cd6346cc..2aa25f0ee 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,11 +29,7 @@ import Image from '@theme/IdealImage'; uv add litellm ``` -To run the full Proxy Server (LLM Gateway): - -```shell -uv tool install 'litellm[proxy]' -``` +To deploy the full AI Gateway (Proxy) with the Admin UI, follow the [Docker Quickstart](./proxy/docker_quick_start.md); it runs as a container and needs no Python setup. To run it from the CLI instead, see the [Gateway Quickstart](./learn/gateway_quickstart.md). --- diff --git a/docs/providers/azure/azure.md b/docs/providers/azure/azure.md index eb28b01db..d94620c28 100644 --- a/docs/providers/azure/azure.md +++ b/docs/providers/azure/azure.md @@ -1032,7 +1032,7 @@ print("list_batches_response=", list_batches_response) -### [Health Check Azure Batch models](../../proxy/health.md#batch-models-azure-only) +### [Health Check Azure Batch models](../../proxy/health.md#model-modes) ### [BETA] Loadbalance Multiple Azure Deployments diff --git a/docs/providers/vertex.md b/docs/providers/vertex.md index 835e3bbcc..ae9c51847 100644 --- a/docs/providers/vertex.md +++ b/docs/providers/vertex.md @@ -3203,7 +3203,7 @@ def load_vertex_ai_credentials(): :::info -Trying to deploy LiteLLM on Google Cloud Run? Tutorial [here](https://docs.litellm.ai/docs/proxy/deploy#deploy-on-google-cloud-run) +Trying to deploy LiteLLM on Google Cloud Run? Tutorial [here](https://docs.litellm.ai/docs/proxy/deploy#deploy-with-terraform-aws-and-gcp) ::: diff --git a/docs/proxy/access_control.md b/docs/proxy/access_control.md index c74e9547b..ce960575c 100644 --- a/docs/proxy/access_control.md +++ b/docs/proxy/access_control.md @@ -1,4 +1,4 @@ -import Image from '@theme/IdealImage'; +import { TenancyDiagram } from '@site/src/components/CloudArchitecture'; # Role-based Access Controls (RBAC) @@ -8,7 +8,7 @@ Role-based access control (RBAC) is based on Organizations, Teams and Internal U - + - `Organizations` are the top-level entities that contain Teams. diff --git a/docs/proxy/architecture.md b/docs/proxy/architecture.md index 2b83583ed..f199eb716 100644 --- a/docs/proxy/architecture.md +++ b/docs/proxy/architecture.md @@ -1,23 +1,21 @@ -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; +import { RequestFlowDiagram, RouterFlowDiagram, ImageFlowDiagram } from '@site/src/components/CloudArchitecture'; # Life of a Request ## High Level architecture - + ### Request Flow 1. **User Sends Request**: The process begins when a user sends a request to the LiteLLM Proxy Server (Gateway). -2. [**Virtual Keys**](../virtual_keys): At this stage the `Bearer` token in the request is checked to ensure it is valid and under it's budget. [Here is the list of checks that run for each request](https://github.com/BerriAI/litellm/blob/ba41a72f92a9abf1d659a87ec880e8e319f87481/litellm/proxy/auth/auth_checks.py#L43) +2. [**Virtual Keys**](../virtual_keys): At this stage the `Bearer` token in the request is checked to ensure it is valid and under its budget. [Here is the list of checks that run for each request](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/auth/auth_checks.py) - 2.1 Check if the Virtual Key exists in Redis Cache or In Memory Cache - 2.2 **If not in Cache**, Lookup Virtual Key in DB -3. **Rate Limiting**: The [MaxParallelRequestsHandler](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/hooks/parallel_request_limiter.py) checks the **rate limit (rpm/tpm)** for the the following components: +3. **Rate Limiting**: The [parallel request limiter](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/hooks/parallel_request_limiter_v3.py) checks the **rate limit (rpm/tpm)** for the following components: - Global Server Rate Limit - Virtual Key Rate Limit - User Rate Limit @@ -31,16 +29,32 @@ import TabItem from '@theme/TabItem'; 7. **Post-Request Processing**: After the response is sent back to the client, the following **asynchronous** tasks are performed: - [Logging to Lunary, MLflow, LangFuse or other logging destinations](./logging) - - The [MaxParallelRequestsHandler](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/hooks/parallel_request_limiter.py) updates the rpm/tpm usage for the + - The [parallel request limiter](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/hooks/parallel_request_limiter_v3.py) updates the rpm/tpm usage for the - Global Server Rate Limit - Virtual Key Rate Limit - User Rate Limit - Team Limit - - The `_ProxyDBLogger` updates spend / usage in the LiteLLM database. [Here is everything tracked in the DB per request](https://github.com/BerriAI/litellm/blob/ba41a72f92a9abf1d659a87ec880e8e319f87481/schema.prisma#L172) + - The `_ProxyDBLogger` updates spend / usage in the LiteLLM database. [Here is everything tracked in the DB per request](https://github.com/BerriAI/litellm/blob/main/schema.prisma) + +## The router: fallbacks and retries + + + +Step 5 above hands the request to the LiteLLM Router, which owns load balancing, fallbacks, and retries. All unified endpoints (`.completion`, `.embeddings`, and so on) flow through it the same way. + +The request first enters `function_with_fallbacks`, which wraps the call in a try-except so it can fall back to another deployment if the primary one fails. From there it passes to `function_with_retries`, which wraps the call again and retries on an available deployment within the same model group when a request fails. Finally `function_with_retries` calls a base litellm unified function such as `litellm.completion` or `litellm.embeddings`, which makes the actual request to the LLM API. + +A **model_group** is a set of LLM API deployments that share the same `model_name` and can be load balanced across. + +## Image URL handling + + + +Some LLM APIs don't accept image URLs but do accept base64 strings. For those, LiteLLM detects a URL in the request, checks whether the target API supports URLs, and if not, downloads the image and sends the provider a base64 string instead. Up to 10 converted images are cached in memory to reduce latency on repeated calls, and individual downloads are capped at 50MB (configurable with `MAX_IMAGE_URL_DOWNLOAD_SIZE_MB`). ## Frequently Asked Questions 1. Is a db transaction tied to the lifecycle of request? - No, a db transaction is not tied to the lifecycle of a request. - The check if a virtual key is valid relies on a DB read if it's not in cache. - - All other DB transactions are async in background tasks \ No newline at end of file + - All other DB transactions are async in background tasks diff --git a/docs/proxy/config_settings.md b/docs/proxy/config_settings.md index 37f632b27..145ffee1e 100644 --- a/docs/proxy/config_settings.md +++ b/docs/proxy/config_settings.md @@ -261,7 +261,7 @@ router_settings: | database_socket_timeout | float | Maps to the Prisma [`socket_timeout`](https://www.prisma.io/docs/orm/overview/databases/postgresql) URL param (seconds). When set, an idle or slow connection that has not produced data within this window is closed. **Use this to cap idle Prisma connections from LiteLLM.** | | database_extra_connection_params | object | Escape hatch — extra key/value pairs appended verbatim to the Prisma `DATABASE_URL` / `DIRECT_URL` query string (e.g. `sslmode`, `pgbouncer`, `statement_cache_size`). Keys here override any default LiteLLM sets. | | database_disable_prepared_statements | boolean | Appends `pgbouncer=true` to the Prisma connection URL, disabling reuse of server-side prepared statements. Use behind PgBouncer transaction pooling, or to avoid `cached plan must not change result type` errors during rolling schema migrations. An explicit `pgbouncer` key in `database_extra_connection_params` takes precedence. [Disable Server-Side Prepared Statements](configs#disable-server-side-prepared-statements) | -| allow_requests_on_db_unavailable | boolean | If true, allows requests to succeed even if DB is unreachable. **Only use this if running LiteLLM in your VPC** This will allow requests to work even when LiteLLM cannot connect to the DB to verify a Virtual Key [Doc on graceful db unavailability](prod#5-if-running-litellm-on-vpc-gracefully-handle-db-unavailability) | +| allow_requests_on_db_unavailable | boolean | If true, allows requests to succeed even if DB is unreachable. **Only use this if running LiteLLM in your VPC** This will allow requests to work even when LiteLLM cannot connect to the DB to verify a Virtual Key [Doc on graceful db unavailability](prod#gracefully-handle-db-unavailability) | | fail_closed_budget_enforcement | boolean | Default `false`. When `true`, budget checks validate spend against the authoritative database for every budgeted request (key, team, user, organization, end-user, tag, and per-window budgets) instead of trusting only the cross-pod Redis counter, and a request is rejected with a `503` when current spend can be verified against neither Redis nor the database. Use this when a configured budget must be a hard ceiling even while Redis is degraded or restarting; leave it off to keep healthy under-budget traffic off the database. [Doc on budget enforcement](./users#hard-budget-enforcement-fail-closed) | | custom_auth | string | Write your own custom authentication logic [Doc Custom Auth](./custom_auth) | | max_parallel_requests | integer | The max parallel requests allowed per deployment | diff --git a/docs/proxy/credential_routing.md b/docs/proxy/credential_routing.md index 2af57c6b4..a9d60ce05 100644 --- a/docs/proxy/credential_routing.md +++ b/docs/proxy/credential_routing.md @@ -9,7 +9,7 @@ Route the same model to different LLM provider endpoints (e.g. different Azure i In multi-tenant deployments, different teams often need the same model name (e.g., `gpt-4`) to hit different provider endpoints — for example, separate Azure OpenAI instances per business unit for cost isolation, data residency, or rate limit separation. -**Credential routing** lets you configure this in team/project metadata using the existing [credentials table](./ui_credentials.md), without duplicating model definitions or creating separate model groups per team. +**Credential routing** lets you configure this in team/project metadata using the existing [credentials table](./model_management.md#reusable-provider-credentials), without duplicating model definitions or creating separate model groups per team. ``` Hotel Team → gpt-4 → https://hotel-eastus.openai.azure.com/ @@ -31,7 +31,7 @@ When a request comes in, the system walks this precedence chain (first match win ### Step 1: Create Credentials -Store your Azure endpoint credentials in the credentials table. You can do this via the [UI](./ui_credentials.md) or API: +Store your Azure endpoint credentials in the credentials table. You can do this via the [UI](./model_management.md#reusable-provider-credentials) or API: ```bash showLineNumbers # Create credential for Hotel team's Azure endpoint @@ -222,7 +222,7 @@ The `model_config` key is a JSON object in team/project `metadata`: | `defaultconfig` | Fallback credential for any model not explicitly listed | | `` | Model-specific override — must match the LiteLLM model group name | | `` | Provider key (e.g. `azure`, `openai`, `bedrock`). When the model name includes a provider prefix (e.g. `azure/gpt-4`), the system prefers the matching provider key | -| `litellm_credentials` | Name of a credential in the [credentials table](./ui_credentials.md) | +| `litellm_credentials` | Name of a credential in the [credentials table](./model_management.md#reusable-provider-credentials) | ### Credential Values @@ -267,7 +267,7 @@ The feature flag must be enabled before `model_config` entries in team/project m ## Related Documentation -- [Adding LLM Credentials](./ui_credentials.md) — Create and manage reusable credentials +- [Adding LLM Credentials](./model_management.md#reusable-provider-credentials) — Create and manage reusable credentials - [Project Management](./project_management.md) — Project hierarchy and API - [Team Budgets](./team_budgets.md) — Team-level budget management - [Clientside LLM Credentials](./clientside_auth.md) — Passing credentials in the request body diff --git a/docs/proxy/credential_usage_tracking.md b/docs/proxy/credential_usage_tracking.md index 25658144c..7cf585b5b 100644 --- a/docs/proxy/credential_usage_tracking.md +++ b/docs/proxy/credential_usage_tracking.md @@ -1,6 +1,6 @@ # Credential Usage Tracking -When a model is attached to a [reusable credential](./ui_credentials.md), LiteLLM automatically injects the credential name as a tag on every request that uses that model. This means credential-level spend and usage are tracked with zero extra configuration. +When a model is attached to a [reusable credential](./model_management.md#reusable-provider-credentials), LiteLLM automatically injects the credential name as a tag on every request that uses that model. This means credential-level spend and usage are tracked with zero extra configuration. ## How It Works @@ -14,6 +14,6 @@ In the Admin UI, go to **Usage → Tag** and look for tags with the `Credential: ## Related Documentation -- [Adding LLM Credentials](./ui_credentials.md) - How to create and attach reusable credentials to models +- [Adding LLM Credentials](./model_management.md#reusable-provider-credentials) - How to create and attach reusable credentials to models - [Tag Budgets](./tag_budgets.md) - Setting spend limits on tags - [Tag Routing](./tag_routing.md) - Routing requests based on tags diff --git a/docs/proxy/custom_root_ui.md b/docs/proxy/custom_root_ui.md index 28ef57d81..532c9bc5e 100644 --- a/docs/proxy/custom_root_ui.md +++ b/docs/proxy/custom_root_ui.md @@ -13,7 +13,7 @@ Requires v1.72.3 or higher. ::: Limitations: -- This does not work in [litellm non-root](./deploy#non-root---without-internet-connection) images, as it requires write access to the UI files. +- This does not work in [litellm non-root](./docker_image_security) images, as it requires write access to the UI files. ## Usage diff --git a/docs/proxy/db_deadlocks.md b/docs/proxy/db_deadlocks.md index fd02ce50e..f5c6505f9 100644 --- a/docs/proxy/db_deadlocks.md +++ b/docs/proxy/db_deadlocks.md @@ -2,7 +2,7 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# High Availability Setup (Resolve DB Deadlocks) +# Resolve DB Deadlocks (Redis Transaction Buffer) :::tip Essential for Production diff --git a/docs/proxy/db_info.md b/docs/proxy/db_info.md index 5ef9fa550..46d1ffbfa 100644 --- a/docs/proxy/db_info.md +++ b/docs/proxy/db_info.md @@ -47,27 +47,12 @@ You can see the full DB Schema [here](https://github.com/BerriAI/litellm/blob/ma | Table Name | Description | Row Insert Frequency | |------------|-------------|---------------------| | LiteLLM_SpendLogs | Detailed logs of all API requests. Records token usage, spend, and timing information. Tracks which models and keys were used. | **Medium - this is a batch process that runs on an interval.** | +| LiteLLM_DailyUserSpend and siblings (DailyTeamSpend, DailyOrgSpend, DailyTagSpend, DailyEndUserSpend, DailyAgentSpend) | Pre-aggregated daily spend rollups per user, team, org, tag, end user, and agent; the Admin UI Usage views read these aggregates rather than scanning SpendLogs. | Low - one row per entity per day, updated in batches | | LiteLLM_AuditLog | Tracks changes to system configuration. Records who made changes and what was modified. Maintains history of updates to teams, users, and models. | **Off by default**, **High - Runs on every change to an entity** | ## Disable `LiteLLM_SpendLogs` -You can disable spend_logs and error_logs by setting `disable_spend_logs` and `disable_error_logs` to `True` on the `general_settings` section of your proxy_config.yaml file. - -```yaml -general_settings: - disable_spend_logs: True # Disable writing spend logs to DB - disable_error_logs: True # Only disable writing error logs to DB, regular spend logs will still be written unless `disable_spend_logs: True` -``` - -### What is the impact of disabling these logs? - -When disabling spend logs (`disable_spend_logs: True`): -- You **will not** be able to view Usage on the LiteLLM UI -- You **will** continue seeing cost metrics on s3, Prometheus, Langfuse (any other Logging integration you are using) - -When disabling error logs (`disable_error_logs: True`): -- You **will not** be able to view Errors on the LiteLLM UI -- You **will** continue seeing error logs in your application logs and any other logging integrations you are using +Set `disable_spend_logs: True` or `disable_error_logs: True` under `general_settings` to stop writing those tables. With spend logs disabled you lose per-request log detail in the UI but keep cost metrics in your logging integrations (s3, Prometheus, Langfuse); with error logs disabled you lose the Errors view in the UI but keep errors in application logs and other logging integrations. See [keeping error logs out of the database](./prod.md#keep-error-logs-out-of-the-database) in the production checklist. ## Migrating Databases diff --git a/docs/proxy/db_read_replica.md b/docs/proxy/db_read_replica.md index 9a258afef..6a9ce66b7 100644 --- a/docs/proxy/db_read_replica.md +++ b/docs/proxy/db_read_replica.md @@ -58,11 +58,11 @@ worst it degrades to single-database performance. ## RDS IAM authentication When `IAM_TOKEN_DB_AUTH=True`, both the writer and the reader refresh their -IAM tokens independently on the same ~12-minute cadence. The reader does not -need parallel `DATABASE_HOST_READ_REPLICA` / `DATABASE_USER_READ_REPLICA` -env vars — host, port, user, and database name are parsed once from -`DATABASE_URL_READ_REPLICA` at startup, and only the IAM token rotates after -that. +IAM tokens independently on the same ~12-minute cadence. You can supply the +reader either as a single `DATABASE_URL_READ_REPLICA` or assembled from the +component vars (`DATABASE_HOST_READ_REPLICA`, `DATABASE_USER_READ_REPLICA`, +and friends); the token-refresh path re-parses the resulting reader URL, +so only the IAM token rotates after startup. This pairs naturally with Aurora's reader endpoint, which resolves to the reader instances in the cluster. diff --git a/docs/proxy/deploy.md b/docs/proxy/deploy.md index d0634a563..dda4d6a8c 100644 --- a/docs/proxy/deploy.md +++ b/docs/proxy/deploy.md @@ -1,189 +1,204 @@ +--- +title: Deploy +description: Production deployment guide for LiteLLM on AWS, GCP, Azure, or any Kubernetes cluster, with Helm charts and official Terraform modules. +--- + import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Image from '@theme/IdealImage'; +import { CloudArchitectureSelector } from '@site/src/components/CloudArchitecture'; -# Docker, Helm, Terraform - -:::info No Limits on LiteLLM OSS -There are **no limits** on the number of users, keys, or teams you can create on LiteLLM OSS. -::: +# Deploy LiteLLM -You can find the Dockerfile to build litellm proxy [here](https://github.com/BerriAI/litellm/blob/main/Dockerfile) +Production deployment guide for AWS, Google Cloud, Azure, or any Kubernetes cluster. For a first deployment on a single machine, start with the [Docker Quickstart](./docker_quick_start.md); this page picks up where it ends. -Official images are published to `ghcr.io/berriai` (`litellm`, `litellm-database` which bundles prisma for use with Postgres, and `litellm-non_root`) and mirrored at `docker.litellm.ai/berriai`. The snippets below use the `docker.litellm.ai` mirror. +There are two supported paths. If you run Kubernetes, [deploy with Helm](#deploy-with-helm) on EKS, GKE, or AKS; the install is the same on every cloud, only the data stores and ingress differ. If you do not run Kubernetes, AWS and GCP have [official Terraform modules](#deploy-with-terraform-aws-and-gcp) that stand up the entire stack; Azure has no Terraform module, so AKS with Helm is the supported path there. -> Note: for production sizing, see [machine specifications](./prod.md#2-recommended-machine-specifications). +## Architecture -## Quick Start - -:::info -Facing issues with pulling the docker image? Email us at support@berri.ai. -::: - - + - +LiteLLM provides two deployment modes: -``` -docker pull docker.litellm.ai/berriai/litellm:latest -``` +- **Monolithic**: one `litellm` image serves LLM traffic, management APIs, and the UI. This is what the `litellm-helm` chart runs, and the simplest to operate. +- **Microservices**: a `gateway` (LLM traffic, port 4000), `backend` (management APIs and UI backend, port 4001), and `ui` (port 3000), each deployed and scaled independently. This is what the componentized `litellm` chart and both Terraform modules run; see the [chart values](https://github.com/BerriAI/litellm/blob/main/helm/litellm/values.yaml) for the full reference. -[**See all docker images**](https://github.com/orgs/BerriAI/packages) +The supporting infrastructure is identical in either mode: - +| Component | Purpose | Notes | +|---|---|---| +| LiteLLM services | One proxy deployment (monolithic) or gateway + backend + ui (microservices) | Stateless; run 2+ replicas behind a load balancer | +| PostgreSQL | Keys, teams, users, spend logs, config | Required for the proxy's auth and tracking features | +| Redis | Rate limiting, router state, caching across instances | Required once you run more than one instance | +| Migrations job | Applies schema migrations against Postgres | Runs once per upgrade; proxy instances set `DISABLE_SCHEMA_UPDATE=true` | - +## Core configuration -```shell -$ uv tool install 'litellm[proxy]' +```bash +DATABASE_URL="postgresql://user:password@host:5432/litellm" +LITELLM_MASTER_KEY="sk-..." # admin key for the proxy +LITELLM_SALT_KEY="sk-..." # encrypts provider credentials stored in the DB. Set once, never change it +DISABLE_SCHEMA_UPDATE="true" # proxy instances never run migrations; the migrations job does +STORE_MODEL_IN_DB="True" # manage models from the Admin UI instead of config files ``` - - - +`LITELLM_SALT_KEY` cannot be rotated after you add models: it encrypts the provider credentials stored in your database, and changing it makes them unreadable. Generate a strong random value and store both keys in your cloud's secret manager. -Use this docker compose to spin up the proxy with a postgres database running locally. +Official images are published to `ghcr.io/berriai` and mirrored at `docker.litellm.ai/berriai`. Use `ghcr.io/berriai/litellm-database` for monolithic deployments with Postgres (it bundles the Prisma toolchain), and pin a version tag rather than `latest` or a moving tag, so rollbacks are deterministic. All images are signed; see the [Docker Image Security Guide](./docker_image_security.md) for verification and the non-root variant. -```bash -# Get the docker compose file -curl -O https://raw.githubusercontent.com/BerriAI/litellm/main/docker-compose.yml -curl -O https://raw.githubusercontent.com/BerriAI/litellm/main/prometheus.yml +## Provision the data stores -# Add the master key - you can change this after setup -echo 'LITELLM_MASTER_KEY="sk-1234"' > .env +The Helm path needs a PostgreSQL database and a Redis reachable from your cluster. Use the managed services: -# Add the litellm salt key - you cannot change this after adding a model -# It is used to encrypt / decrypt your LLM API Key credentials -# We recommend - https://1password.com/password-generator/ -# password generator to get a random hash for litellm salt key -echo 'LITELLM_SALT_KEY="sk-1234"' >> .env + + -# Start -docker compose up -``` +Provision [RDS PostgreSQL](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html) and [ElastiCache Redis](https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/WhatIs.html) in the same VPC as your EKS cluster, with security groups permitting the cluster's nodes on ports 5432 and 6379. - - -### Verify Docker image signatures + -All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](https://github.com/BerriAI/litellm/commit/0112e53046018d726492c814b3644b7d376029d0). +Provision [Cloud SQL PostgreSQL](https://cloud.google.com/sql/docs/postgres) and [Memorystore Redis](https://cloud.google.com/memorystore/docs/redis) with private IPs on the VPC your GKE cluster uses (Cloud SQL needs [Private Services Access](https://cloud.google.com/vpc/docs/private-services-access)). Use the instances' private IPs as the endpoints below. -**Verify using the pinned commit hash (recommended):** - -A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: + + ```bash -cosign verify \ - --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ - ghcr.io/berriai/litellm: -``` +az group create --name litellm-prod --location eastus -**Verify using a release tag (convenience):** +az aks create --resource-group litellm-prod --name litellm-aks \ + --node-count 3 --enable-managed-identity -Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: +az postgres flexible-server create --resource-group litellm-prod \ + --name litellm-db --database-name litellm \ + --tier GeneralPurpose --sku-name Standard_D2ds_v5 -```bash -cosign verify \ - --key https://raw.githubusercontent.com/BerriAI/litellm//cosign.pub \ - ghcr.io/berriai/litellm: +az redis create --resource-group litellm-prod --name litellm-redis \ + --location eastus --sku Standard --vm-size c1 ``` -Replace `` with the version you are deploying (e.g. `v1.89.4`). - -Expected output: +Docs: [AKS](https://learn.microsoft.com/en-us/azure/aks/what-is-aks), [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/overview), [Azure Cache for Redis](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-overview). Azure Cache for Redis serves TLS on port 6380, and TLS is enabled through the URL scheme: instead of `redis_host` and `redis_port`, set `redis_url: "rediss://:@litellm-redis.redis.cache.windows.net:6380"` under `router_settings` (the `rediss://` scheme turns TLS on). -``` -The following checks were performed on each of these signatures: - - The cosign claims were validated - - The signatures were verified against the specified public key -``` + + -Learn more about LiteLLM's release signing in the [CI/CD v2 announcement](https://docs.litellm.ai/blog/ci-cd-v2-improvements#verify-docker-image-signatures). For a complete guide covering all image variants, CI/CD enforcement, and deployment best practices, see the [Docker Image Security Guide](./docker_image_security.md). +## Deploy with Helm -### Docker Run +First create the secrets both charts consume: -#### Step 1. CREATE config.yaml +```bash +kubectl create secret generic litellm-masterkey \ + --from-literal=masterkey="sk-$(openssl rand -hex 24)" -Example `litellm_config.yaml` +kubectl create secret generic litellm-db \ + --from-literal=username=litellm \ + --from-literal=password="" -```yaml -model_list: - - model_name: azure-gpt-4o - litellm_params: - model: azure/ - api_base: os.environ/AZURE_API_BASE # runs os.getenv("AZURE_API_BASE") - api_key: os.environ/AZURE_API_KEY # runs os.getenv("AZURE_API_KEY") - api_version: "2025-01-01-preview" +kubectl create secret generic litellm-env \ + --from-literal=LITELLM_SALT_KEY="sk-$(openssl rand -hex 24)" \ + --from-literal=REDIS_PASSWORD="" \ + --from-literal=OPENAI_API_KEY="" ``` +Then pick a deployment mode: - -#### Step 2. RUN Docker Image - -```shell -docker run \ - -v $(pwd)/litellm_config.yaml:/app/config.yaml \ - -e AZURE_API_KEY=d6*********** \ - -e AZURE_API_BASE=https://openai-***********/ \ - -p 4000:4000 \ - docker.litellm.ai/berriai/litellm:latest \ - --config /app/config.yaml --detailed_debug + + + +```yaml title="values.yaml" +replicaCount: 3 + +image: + repository: ghcr.io/berriai/litellm-database + tag: "v1.90.2" # pin your version + +masterkeySecretName: litellm-masterkey +masterkeySecretKey: masterkey + +db: + useExisting: true + deployStandalone: false + endpoint: "" + database: litellm + secret: + name: litellm-db + usernameKey: username + passwordKey: password + +environmentSecrets: + - litellm-env + +proxy_config: + model_list: + - model_name: gpt-4o + litellm_params: + model: openai/gpt-4o + api_key: os.environ/OPENAI_API_KEY + router_settings: + redis_host: "" + redis_port: 6379 + redis_password: os.environ/REDIS_PASSWORD ``` -Get the latest image [here](https://github.com/berriai/litellm/pkgs/container/litellm) - -#### Step 3. Test it - -Open the Admin UI at `http://0.0.0.0:4000/ui`, go to the **Test Key** playground, pick `azure-gpt-4o` (the model you set in step 1), and send a message. - -### Docker Run - CLI Args +```bash +helm install litellm oci://ghcr.io/berriai/litellm-helm -f values.yaml +``` -See all supported CLI args [here](https://docs.litellm.ai/docs/proxy/cli): +The chart lives at [`deploy/charts/litellm-helm`](https://github.com/BerriAI/litellm/tree/main/deploy/charts/litellm-helm); the published chart versions carry LiteLLM release numbers (for example `1.90.2`), and `helm show values oci://ghcr.io/berriai/litellm-helm` lists every knob. Beyond the values above it supports autoscaling (`autoscaling.*` or `keda.*`), PodDisruptionBudgets (`pdb.*`), a Prometheus ServiceMonitor (`serviceMonitor.*`), read replica routing (`db.readReplicaUrl`, see [Database Read Replica](./db_read_replica.md)), graceful drain on shutdown (`lifecycle`), and ArgoCD or Helm hooks for the migrations job (`migrationJob.hooks.*`, see [Helm PreSync hooks](./prod.md#run-migrations-from-the-helm-presync-hook)). -Here's how you can run the docker image and pass your config to `litellm` -```shell -docker run docker.litellm.ai/berriai/litellm:latest --config your_config.yaml + + + +```yaml title="values.yaml" +masterKey: + secretName: litellm-masterkey + secretKey: masterkey + +database: + writer: + host: "" + port: 5432 + dbname: litellm + passwordSecret: + name: litellm-db + usernameKey: username + passwordKey: password + # optional: add database.reader to route reads to a replica + +redis: + host: "" + port: 6379 + passwordSecret: + name: litellm-env + passwordKey: REDIS_PASSWORD + +# one host fronting gateway, backend, and ui +ingress: + enabled: true + className: "" + host: llm.example.com ``` -Here's how you can run the docker image and start litellm on port 8002 with `num_workers=8` -```shell -docker run docker.litellm.ai/berriai/litellm:latest --port 8002 --num_workers 8 +```bash +helm upgrade --install litellm \ + oci://ghcr.io/berriai/litellm/chart/litellm \ + --version 1.89.2 \ + -f values.yaml ``` +This deploys `gateway`, `backend`, and `ui` as separate services with per-component autoscaling, so you can run many gateway replicas against a small fixed backend. It requires external Postgres and Redis (no bundled subcharts) and supports reader/writer database splits, IAM database auth, and Redis Cluster mode. Every knob (per-component scaling and probes, read replica routing, Redis Cluster, migrations job, ingress) is documented in the [chart's values.yaml](https://github.com/BerriAI/litellm/blob/main/helm/litellm/values.yaml). -### Use litellm as a base image - -```shell -# Use the provided base image -FROM docker.litellm.ai/berriai/litellm:latest - -# Set the working directory to /app -WORKDIR /app - -# Copy the configuration file into the container at /app -COPY config.yaml . - -# Make sure your docker/entrypoint.sh is executable -RUN chmod +x ./docker/entrypoint.sh - -# Expose the necessary port -EXPOSE 4000/tcp - -# Override the CMD instruction with your desired command and arguments -# WARNING: FOR PROD DO NOT USE `--detailed_debug` it slows down response times, instead use the following CMD -# CMD ["--port", "4000", "--config", "config.yaml"] - -CMD ["--port", "4000", "--config", "config.yaml", "--detailed_debug"] -``` + + -### Terraform +Both charts run the migrations job automatically and keep `DISABLE_SCHEMA_UPDATE=true` on the proxy pods. Expose the service through your cloud's ingress: the [AWS Load Balancer Controller](https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html) on EKS, [GKE Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress) on GKE, or [Application Gateway Ingress (AGIC)](https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview) on AKS, with health checks on `/health/readiness`, then point your DNS record at the resulting load balancer. For secrets, prefer your cloud's secret manager over plain Kubernetes secrets ([Key Vault CSI driver](https://learn.microsoft.com/en-us/azure/aks/csi-secrets-store-driver) on AKS, for example); the charts consume whatever secret you mount. -To provision the full infrastructure stack with Terraform on AWS or GCP, use the official modules described in [Deploy to Cloud](./deploy_cloud.md#deploy-with-terraform-aws-and-gcp). To manage LiteLLM resources (keys, teams, models) with Terraform, use [terraform-provider-litellm](https://github.com/BerriAI/terraform-provider-litellm) (s/o [Nicholas Cecere](https://www.linkedin.com/in/nicholas-cecere-24243549/)). +### Kubernetes without Helm -### Kubernetes +If you manage raw manifests, the equivalent deployment is a ConfigMap for `config.yaml`, a Secret for keys, a Deployment with health probes, and a Service. -A config file based litellm instance runs as a Deployment that loads `config.yaml` from a ConfigMap, with api keys declared as env vars attached from an opaque Secret. The manifest below defines a ConfigMap, a Secret, a Deployment, and a Service; apply it with `kubectl apply -f deployment.yaml`. +
+Full manifest (ConfigMap, Secret, Deployment, Service) ```yaml apiVersion: v1 @@ -192,12 +207,11 @@ metadata: name: litellm-config-file data: config.yaml: | - model_list: + model_list: - model_name: gpt-4o litellm_params: - model: azure/gpt-4o-ca - api_base: https://my-endpoint-canada-berri992.openai.azure.com/ - api_key: os.environ/CA_AZURE_OPENAI_API_KEY + model: openai/gpt-4o + api_key: os.environ/OPENAI_API_KEY --- apiVersion: v1 kind: Secret @@ -205,7 +219,7 @@ type: Opaque metadata: name: litellm-secrets data: - CA_AZURE_OPENAI_API_KEY: bWVvd19pbV9hX2NhdA== # your api key in base64 + OPENAI_API_KEY: bWVvd19pbV9hX2NhdA== # your api key in base64 --- apiVersion: apps/v1 kind: Deployment @@ -214,7 +228,7 @@ metadata: labels: app: litellm spec: - replicas: 1 + replicas: 2 selector: matchLabels: app: litellm @@ -269,502 +283,124 @@ spec: type: NodePort ``` -Port-forward to reach the proxy locally: - -```bash -kubectl port-forward service/litellm-service 4000:4000 -``` - -To connect a database (Virtual Keys, spend tracking), use the `docker.litellm.ai/berriai/litellm-database` image and add `DATABASE_URL` and `LITELLM_MASTER_KEY` to the Secret; nothing else in the manifest changes. See [Deploy with Database](#deploy-with-database). To run more than one instance behind a load balancer, see [Multi-region and scaling](./multi_region.md). - -:::info -To avoid issues with predictability, difficulties in rollback, and inconsistent environments, pin a version or SHA digest (for example, `litellm:main-v1.90.2` or `litellm@sha256:12345abcdef...`) instead of `litellm:latest`. -::: - +
-### Helm Chart +To connect the database, switch the image to `docker.litellm.ai/berriai/litellm-database` and add `DATABASE_URL` and `LITELLM_MASTER_KEY` to the Secret; nothing else in the manifest changes. -:::info +## Deploy with Terraform (AWS and GCP) -[BETA] Helm Chart is BETA. If you run into an issues/have feedback please let us know [https://github.com/BerriAI/litellm/issues](https://github.com/BerriAI/litellm/issues) +The official modules deploy the full microservices stack (network, database, Redis, object storage, secrets, compute, load balancer, and a migrations job that runs before the services start) and are published to the Terraform Registry: -::: - -The canonical chart lives at [`deploy/charts/litellm-helm`](https://github.com/BerriAI/litellm/tree/main/deploy/charts/litellm-helm) in the litellm repo and is published as an OCI artifact at `oci://ghcr.io/berriai/litellm-helm`, the published chart versions carry litellm release numbers (for example, `1.90.2`). This section covers a local quickstart; for a production install on EKS, GKE, or AKS with managed Postgres and Redis, see [Deploy to Cloud](./deploy_cloud.md#deploy-with-helm). +- [`BerriAI/litellm/aws`](https://registry.terraform.io/modules/BerriAI/litellm/aws/latest) +- [`BerriAI/litellm/google`](https://registry.terraform.io/modules/BerriAI/litellm/google/latest) + - - -Inspect the default values, then install with your own `values.yaml`: - -```bash -# View the chart's configurable values -helm show values oci://ghcr.io/berriai/litellm-helm > values.yaml - -# Install (or upgrade) the release -helm install litellm oci://ghcr.io/berriai/litellm-helm -f values.yaml -``` - -Set your proxy config and master key in `values.yaml`; see the [chart values reference](https://github.com/BerriAI/litellm/blob/main/deploy/charts/litellm-helm/values.yaml). Pin a chart version with `--version ` for reproducible installs. - - - - - -Install directly from a checkout of the litellm repo: - -```bash -git clone https://github.com/BerriAI/litellm.git -helm install litellm deploy/charts/litellm-helm --set masterkey=sk-1234 -``` - - - - -Expose the service to localhost: - -```bash -kubectl --namespace default port-forward service/litellm 4000:4000 -``` - -Your LiteLLM Proxy Server is now running on `http://127.0.0.1:4000`. To run multiple replicas behind a load balancer, see [Multi-region and scaling](./multi_region.md). - -#### Make LLM API Requests - -Open the Admin UI at `http://127.0.0.1:4000/ui`, log in with your master key, and send a request from the **Test Key** playground. To call the proxy from code, see [making your first LLM API request](user_keys); LiteLLM is compatible with the OpenAI SDK, Anthropic SDK, Mistral SDK, LlamaIndex, and Langchain (JS, Python). - -## Deployment Options - -| Docs | When to Use | -| ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Quick Start](#quick-start) | call 100+ LLMs + Load Balancing | -| [Deploy with Database](#deploy-with-database) | + use Virtual Keys + Track Spend (Note: When deploying with a database providing a `DATABASE_URL` and `LITELLM_MASTER_KEY` are required in your env ) | -| [Deploy with Redis](#deploy-with-redis) | + load balance across multiple litellm containers (optionally with a database) | - -### Deploy with Database -##### Docker, Kubernetes, Helm Chart +Provisions a VPC with public and private subnets, an Aurora PostgreSQL cluster (writer plus reader, IAM database auth), ElastiCache Redis (multi-AZ, encrypted), an S3 bucket, Secrets Manager entries, an Application Load Balancer, and ECS Fargate services. -:::warning High Traffic Deployments (1000+ RPS) +```hcl title="main.tf" +module "litellm" { + source = "BerriAI/litellm/aws" + version = "~> 1.90" -If you expect high traffic (1000+ requests per second), **Redis is required** to prevent database connection exhaustion and deadlocks. + region = "us-east-1" + azs = ["us-east-1a", "us-east-1b"] + tenant = "acme" + env = "prod" -Add this to your config: -```yaml -general_settings: - use_redis_transaction_buffer: true - -litellm_settings: - cache: true - cache_params: - type: redis - host: your-redis-host -``` - -See [Resolve DB Deadlocks](/docs/proxy/db_deadlocks) for details. - -::: - -Requirements: -- Need a postgres database (e.g. [Supabase](https://supabase.com/), [Neon](https://neon.tech/), etc) Set `DATABASE_URL=postgresql://:@:/` in your env -- Set a `LITELLM_MASTER_KEY`, this is your Proxy Admin key - you can use this to create other keys (must start with `sk-`) - - + ui_password = var.ui_password + litellm_license = var.litellm_license # optional, omit for open source + acm_certificate_arn = var.acm_certificate_arn # TLS is required by default - - -We maintain a [separate Dockerfile](https://github.com/BerriAI/litellm/pkgs/container/litellm-database) for reducing build time when running LiteLLM proxy with a connected Postgres Database - -```shell -docker pull docker.litellm.ai/berriai/litellm-database:latest -``` - -```shell -docker run \ - -v $(pwd)/litellm_config.yaml:/app/config.yaml \ - -e LITELLM_MASTER_KEY=sk-1234 \ - -e DATABASE_URL=postgresql://:@:/ \ - -e AZURE_API_KEY=d6*********** \ - -e AZURE_API_BASE=https://openai-***********/ \ - -p 4000:4000 \ - docker.litellm.ai/berriai/litellm-database:latest \ - --config /app/config.yaml --detailed_debug + proxy_config = { + model_list = [{ + model_name = "gpt-4o" + litellm_params = { + model = "openai/gpt-4o" + api_key = "os.environ/OPENAI_API_KEY" + } + }] + } + gateway_extra_secrets = { + OPENAI_API_KEY = var.openai_key_secret_arn + } +} ``` -Your LiteLLM Proxy Server is now running on `http://0.0.0.0:4000`. - - - - -Use the canonical manifest from the [Kubernetes](#kubernetes) section above. The DB-connected variant is the same manifest with `DATABASE_URL` and `LITELLM_MASTER_KEY` added to the Secret and the image set to `docker.litellm.ai/berriai/litellm-database:main-v1.90.2` (bundles prisma). Nothing else changes. +Before you apply: provision the TLS certificate in [AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html) (the module refuses a plaintext ALB unless you explicitly set `allow_plaintext_alb = true`), and create any provider-key secrets in [Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html) first, since `gateway_extra_secrets` takes their ARNs. After apply, point your DNS record at the ALB hostname. - - - - -Use the [Helm chart](#helm-chart) described above. Set `DATABASE_URL` and `LITELLM_MASTER_KEY` in your `values.yaml` (see the [chart values reference](https://github.com/BerriAI/litellm/blob/main/deploy/charts/litellm-helm/values.yaml)), then run `helm install litellm oci://ghcr.io/berriai/litellm-helm -f values.yaml`. +The module auto-generates the master key into Secrets Manager if you do not supply one. The application connects to Aurora with short-lived IAM tokens, so its `DATABASE_URL` carries no password (the database master password itself is generated into Secrets Manager and never touches the application). Every resource is named `-litellm-`, and the module declares no provider, so you can `for_each` it to run one stack per tenant. - - -### Deploy with Redis -Use Redis when you need litellm to load balance across multiple litellm containers - -The only change required is setting Redis on your `config.yaml` -LiteLLM Proxy supports sharing rpm/tpm shared across multiple litellm instances, pass `redis_host`, `redis_password` and `redis_port` to enable this. (LiteLLM will use Redis to track rpm/tpm usage ) - -```yaml -model_list: - - model_name: gpt-4o - litellm_params: - model: azure/ - api_base: - api_key: - rpm: 6 # Rate limit for this deployment: in requests per minute (rpm) - - model_name: gpt-4o - litellm_params: - model: azure/gpt-4o-ca - api_base: https://my-endpoint-canada-berri992.openai.azure.com/ - api_key: - rpm: 6 -router_settings: - redis_host: - redis_password: - redis_port: 1992 -``` + -Start docker container with config +Provisions a VPC with Private Services Access, Cloud SQL PostgreSQL (primary plus read replica), Memorystore Redis with TLS, a GCS bucket, Secret Manager entries, Cloud Run services, and a global HTTPS load balancer with serverless NEGs. -```shell -docker run docker.litellm.ai/berriai/litellm:latest --config your_config.yaml -``` +```hcl title="main.tf" +module "litellm" { + source = "BerriAI/litellm/google" + version = "~> 1.90" -To combine Redis with a database (Virtual Keys and spend tracking), keep the same `router_settings` above, switch to the `litellm-database` image, and pass `DATABASE_URL`: + project_id = "my-project" + region = "us-central1" + tenant = "acme" + env = "prod" -```shell -docker run --name litellm-proxy \ --e DATABASE_URL=postgresql://:@:/ \ --p 4000:4000 \ -docker.litellm.ai/berriai/litellm-database:latest --config your_config.yaml -``` + ui_password = var.ui_password + litellm_license = var.litellm_license # optional -To scale across regions or many instances, see [Multi-region and scaling](./multi_region.md). + # Cloud Run cannot pull from ghcr.io. Point this at an Artifact Registry + # remote repository backed by ghcr.io, or mirror the images. + image_registry = "us-central1-docker.pkg.dev/my-project/ghcr-remote/berriai" -### (Non Root) - without Internet Connection + lb_domains = ["llm.example.com"] -By default `prisma generate` downloads [prisma's engine binaries](https://www.prisma.io/docs/orm/reference/environment-variables-reference#custom-engine-file-locations). This might cause errors when running without internet connection. - -Use this docker image to deploy litellm with pre-generated prisma binaries. - -```bash -docker pull docker.litellm.ai/berriai/litellm-non_root:latest + proxy_config = { + model_list = [{ + model_name = "gemini-2.5-pro" + litellm_params = { model = "vertex_ai/gemini-2.5-pro" } + }] + } +} ``` -[Published Docker Image link](https://github.com/BerriAI/litellm/pkgs/container/litellm-non_root) +Three GCP-specific caveats. First, always override `image_registry`: it defaults to `ghcr.io/berriai`, which Cloud Run cannot pull from, so the apply succeeds but the services fail at image pull. Point it at an [Artifact Registry remote repository](https://cloud.google.com/artifact-registry/docs/repositories/remote-overview) that proxies `ghcr.io`. Second, the database uses password authentication through Secret Manager rather than IAM auth; LiteLLM's IAM token support is AWS RDS specific. Third, create the DNS record for `lb_domains` pointing at the load balancer IP after apply; the [Google-managed certificate](https://cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs) will not finish provisioning until the domain resolves to it. -## Advanced Deployment Settings - -### 1. Custom server root path (Proxy base url) - -Refer to [Custom Root Path](./custom_root_ui) for more details. - - -### 2. SSL Certification - -Use this, If you need to set ssl certificates for your on prem litellm proxy - -Pass `ssl_keyfile_path` (Path to the SSL keyfile) and `ssl_certfile_path` (Path to the SSL certfile) when starting litellm proxy - -```shell -docker run docker.litellm.ai/berriai/litellm:latest \ - --ssl_keyfile_path ssl_test/keyfile.key \ - --ssl_certfile_path ssl_test/certfile.crt -``` - -Provide an ssl certificate when starting litellm proxy server - -### 3. Http/2 with Hypercorn - -Use this if you want to run the proxy with hypercorn to support http/2 - -Step 1. Build your custom docker image with hypercorn - -```shell -# Use the provided base image -FROM docker.litellm.ai/berriai/litellm:latest - -# Set the working directory to /app -WORKDIR /app - -# Copy the configuration file into the container at /app -COPY config.yaml . - -# Make sure your docker/entrypoint.sh is executable -RUN chmod +x ./docker/entrypoint.sh - -# Expose the necessary port -EXPOSE 4000/tcp - -# Key change: install hypercorn -RUN uv add hypercorn - -# Override the CMD instruction with your desired command and arguments -# WARNING: FOR PROD DO NOT USE `--detailed_debug` it slows down response times, instead use the following CMD -# CMD ["--port", "4000", "--config", "config.yaml"] - -CMD ["--port", "4000", "--config", "config.yaml", "--detailed_debug"] -``` - -Step 2. Pass the `--run_hypercorn` flag when starting the proxy - -```shell -docker run \ - -v $(pwd)/proxy_config.yaml:/app/config.yaml \ - -p 4000:4000 \ - -e LITELLM_LOG="DEBUG"\ - -e SERVER_ROOT_PATH="/api/v1"\ - -e DATABASE_URL=postgresql://:@:/ \ - -e LITELLM_MASTER_KEY="sk-1234"\ - your_custom_docker_image \ - --config /app/config.yaml - --run_hypercorn -``` - -### 4. Granian ASGI server (higher throughput) [Beta] - -:::info Beta feature -`--run_granian` is in **beta**. Uvicorn is still the default server. Try Granian when you need more gateway throughput or see instability under load with uvicorn; report issues on [GitHub](https://github.com/BerriAI/litellm/issues). -::: - -Use this to run the proxy with [Granian](https://github.com/emmett-framework/granian), a Rust-backed ASGI server. The HTTP stack runs in Rust instead of pure Python, which helps the proxy stay responsive when many clients hit health checks, auth, routing, and caching at once. - -**Why it helps:** -- **Higher throughput**: In LiteLLM benchmarks, Granian showed a **10–20 RPS improvement** over uvicorn with the same worker count (see [PR #26027](https://github.com/BerriAI/litellm/pull/26027)). -- **Better stability**: Sustained load tests showed steadier latency and fewer spikes than uvicorn. -- **Fewer failures**: Error rates under load were lower (near-zero failures in the compared runs vs uvicorn). - -Granian is included in `litellm[proxy]` and requires Python 3.9+. Scale throughput with `--num_workers`. - -**Example** (benchmark setup from [PR #26027](https://github.com/BerriAI/litellm/pull/26027)): - -```shell -litellm --config config.yaml --port 4000 --run_granian --num_workers 4 -``` - -Or with Docker: - -```shell -docker run docker.litellm.ai/berriai/litellm:latest \ - --config /app/config.yaml \ - --port 4000 \ - --run_granian \ - --num_workers 4 -``` - -**SSL:** Both `--ssl_certfile_path` and `--ssl_keyfile_path` are required when enabling TLS with Granian. - -**Not supported with Granian:** -- `--max_requests_before_restart` (use Gunicorn if you need per-request worker recycling) -- `--ciphers` (Hypercorn only) - -See [CLI Arguments, Server Backend Options](/docs/proxy/cli#server-backend-options) for full flag details. - -### 5. Keepalive Timeout - -Defaults to 5 seconds. Between requests, connections must receive new data within this period or be disconnected. - - -Usage Example: -In this example, we set the keepalive timeout to 75 seconds. - -```shell showLineNumbers title="docker run" -docker run docker.litellm.ai/berriai/litellm:latest \ - --keepalive_timeout 75 -``` - -Or set via environment variable: -In this example, we set the keepalive timeout to 75 seconds. - -```shell showLineNumbers title="Environment Variable" -export KEEPALIVE_TIMEOUT=75 -docker run docker.litellm.ai/berriai/litellm:latest -``` - - -### Restart Workers After N Requests - -Use this to mitigate memory growth by recycling workers after a fixed number of requests. When set, each worker restarts after completing the specified number of requests. Defaults to disabled when unset. - -Usage Examples: - -```shell showLineNumbers title="docker run (CLI flag)" -docker run docker.litellm.ai/berriai/litellm:latest \ - --max_requests_before_restart 10000 -``` - -Or set via environment variable: - -```shell showLineNumbers title="Environment Variable" -export MAX_REQUESTS_BEFORE_RESTART=10000 -docker run docker.litellm.ai/berriai/litellm:latest -``` - - -### 6. config.yaml file on s3, GCS Bucket Object/url - -Use this if you cannot mount a config file on your deployment service (example - AWS Fargate, Railway etc) - -LiteLLM Proxy will read your config.yaml from an s3 Bucket or GCS Bucket - - - - -Set the following .env vars -```shell -LITELLM_CONFIG_BUCKET_TYPE = "gcs" # set this to "gcs" -LITELLM_CONFIG_BUCKET_NAME = "litellm-proxy" # your bucket name on GCS -LITELLM_CONFIG_BUCKET_OBJECT_KEY = "proxy_config.yaml" # object key on GCS -``` - -Start litellm proxy with these env vars - litellm will read your config from GCS - -```shell -docker run --name litellm-proxy \ - -e DATABASE_URL= \ - -e LITELLM_CONFIG_BUCKET_NAME= \ - -e LITELLM_CONFIG_BUCKET_OBJECT_KEY="> \ - -e LITELLM_CONFIG_BUCKET_TYPE="gcs" \ - -p 4000:4000 \ - docker.litellm.ai/berriai/litellm-database:latest --detailed_debug -``` - - - - - -Set the following .env vars -```shell -LITELLM_CONFIG_BUCKET_NAME = "litellm-proxy" # your bucket name on s3 -LITELLM_CONFIG_BUCKET_OBJECT_KEY = "litellm_proxy_config.yaml" # object key on s3 -``` - -Start litellm proxy with these env vars - litellm will read your config from s3 - -```shell -docker run --name litellm-proxy \ - -e DATABASE_URL= \ - -e LITELLM_CONFIG_BUCKET_NAME= \ - -e LITELLM_CONFIG_BUCKET_OBJECT_KEY="> \ - -p 4000:4000 \ - docker.litellm.ai/berriai/litellm-database:latest -``` -### 7. Disable pulling live model prices - -Disable pulling the model prices from LiteLLM's [hosted model prices file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json), if you're seeing long cold start times or network security issues. - -```env -export LITELLM_LOCAL_MODEL_COST_MAP="True" -``` - -This will use the local model prices file instead. - -## Platform-specific Guide +To manage LiteLLM resources (keys, teams, models) as code once the stack is up, use [terraform-provider-litellm](https://github.com/BerriAI/terraform-provider-litellm). -For managed cloud deployments on AWS (ECS, EKS, CloudFormation), GCP (GKE, Cloud Run), and Azure (AKS), including the Terraform modules, see [Deploy to Cloud (AWS, GCP, Azure)](./deploy_cloud.md). - -Render and Railway are quick options not covered by that guide: +## Other platforms - - -### Render + -https://render.com/ +Deploy on [Render](https://render.com/): - - -### Railway - -https://railway.app - -**Step 1: Click the button** to deploy to Railway +Deploy on [Railway](https://railway.app): click the button, then set `PORT=4000` in the Railway environment variables. [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/S7P9sn?referralCode=t3ukrU) -**Step 2:** Set `PORT` = 4000 on Railway Environment Variables - +## Verify the deployment -## Extras - -### IAM-based Auth for RDS DB - -1. Set AWS env var - -```bash -export AWS_WEB_IDENTITY_TOKEN='/path/to/token' -export AWS_ROLE_NAME='arn:aws:iam::123456789012:role/MyRole' -export AWS_SESSION_NAME='MySession' -``` - -[**See all Auth options**](https://github.com/BerriAI/litellm/blob/089a4f279ad61b7b3e213d8039fb9b75204a7abc/litellm/proxy/auth/rds_iam_token.py#L165) - -2. Add RDS credentials to env - -```bash -export DATABASE_USER="db-user" -export DATABASE_PORT="5432" -export DATABASE_HOST="database-1-instance-1.cs1ksmwz2xt3.us-west-2.rds.amazonaws.com" -export DATABASE_NAME="database-1-instance-1" -export DATABASE_SCHEMA="schema-name" # skip to use the default "public" schema -``` - -3. Run proxy with iam+rds - +Confirm the proxy is up and can reach its database: ```bash -litellm --config /path/to/config.yaml --iam_token_db_auth +curl -s https://llm.example.com/health/readiness ``` -### Blocking web crawlers - -Note: This is an [enterprise only feature](https://docs.litellm.ai/docs/enterprise). - -To block web crawlers from indexing the proxy server endpoints, set the `block_robots` setting to `true` in your `litellm_config.yaml` file. - -```yaml showLineNumbers title="litellm_config.yaml" -general_settings: - block_robots: true -``` - -#### How it works - -When this is enabled, the `/robots.txt` endpoint will return a 200 status code with the following content: - -```shell showLineNumbers title="robots.txt" -User-agent: * -Disallow: / -``` - -## Deployment FAQ - -**Q: Is Postgres the only supported database, or do you support other ones (like Mongo)?** - -A: We explored MySQL but that was hard to maintain and led to bugs for customers. Currently, PostgreSQL is our primary supported database for production deployments. - -Because LiteLLM talks to the database through Prisma over the PostgreSQL wire protocol, any Postgres-wire-compatible distributed SQL database works as a drop-in replacement. [YugabyteDB](https://www.yugabyte.com/) is used in production this way; point `DATABASE_URL` at its YSQL endpoint (`postgresql://:@:/`) and LiteLLM runs its migrations and queries unchanged. This is a good fit if you need horizontal scale or multi-region high availability beyond what a single Postgres instance provides. - +Then open the Admin UI at `https://llm.example.com/ui`, log in with your master key, add a model, create a virtual key, and send a Playground message; a response proves the full path through the load balancer, proxy, database, and provider credentials. The [Docker Quickstart](./docker_quick_start.md#2-log-in-to-the-admin-ui) walks through each of those clicks with screenshots; the flow is identical on a production deployment. -**Q: If there is Postgres downtime, how does LiteLLM react? Does it fail-open or is there API downtime?** +## Next steps -A: You can gracefully handle DB unavailability if it's on your VPC. See our production guide for more details: [Gracefully Handle DB Unavailability](https://docs.litellm.ai/docs/proxy/prod#6-if-running-litellm-on-vpc-gracefully-handle-db-unavailability) +Harden the deployment with the [production checklist](./prod.md) (worker counts, machine sizing, Redis settings, server tuning, graceful degradation). Verify image signatures with the [Docker Image Security Guide](./docker_image_security.md). Add regions with [Multi-Region Deployment](./multi_region.md). For very high throughput (1000+ RPS), see [resolving DB deadlocks](./db_deadlocks.md). diff --git a/docs/proxy/deploy_cloud.md b/docs/proxy/deploy_cloud.md deleted file mode 100644 index 15b287c6f..000000000 --- a/docs/proxy/deploy_cloud.md +++ /dev/null @@ -1,296 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import Image from '@theme/IdealImage'; -import { CloudArchitectureSelector } from '@site/src/components/CloudArchitecture'; - -# Deploy to Cloud (AWS, GCP, Azure) - -Step-by-step guides for running LiteLLM proxy in production on AWS, Google Cloud, or Azure. There are two supported paths. If you run Kubernetes, [deploy with Helm](#deploy-with-helm) on EKS, GKE, or AKS; the install is the same on every cloud, only the data stores and ingress differ. If you do not run Kubernetes, AWS and GCP have [official Terraform modules](#deploy-with-terraform-aws-and-gcp) that stand up the entire stack; Azure has no Terraform module, so AKS with Helm is the supported path there. - -## Architecture - - - -LiteLLM provides two deployment modes: - -- **Monolithic**: one `litellm` image serves LLM traffic, management APIs, and the UI. This is what the `litellm-helm` chart runs, and the simplest to operate. -- **Microservices**: a `gateway` (LLM traffic, port 4000), `backend` (management APIs and UI backend, port 4001), and `ui` (port 3000), each deployed and scaled independently. This is what the componentized `litellm` chart and both Terraform modules run; see [Microservices Helm](./microservices_helm.md) for the full reference. - -The supporting infrastructure is identical in either mode: - -| Component | Purpose | Notes | -|---|---|---| -| LiteLLM services | One proxy deployment (monolithic) or gateway + backend + ui (microservices) | Stateless; run 2+ replicas behind a load balancer | -| PostgreSQL | Keys, teams, users, spend logs, config | Required for the proxy's auth and tracking features | -| Redis | Rate limiting, router state, caching across instances | Required once you run more than one instance | -| Migrations job | Applies schema migrations against Postgres | Runs once per upgrade; proxy instances set `DISABLE_SCHEMA_UPDATE=true` | - -## Core configuration - -```bash -DATABASE_URL="postgresql://user:password@host:5432/litellm" -LITELLM_MASTER_KEY="sk-..." # admin key for the proxy -LITELLM_SALT_KEY="sk-..." # encrypts provider credentials stored in the DB. Set once, never change it -DISABLE_SCHEMA_UPDATE="true" # proxy instances never run migrations; the migrations job does -STORE_MODEL_IN_DB="True" # manage models from the Admin UI instead of config files -``` - -`LITELLM_SALT_KEY` cannot be rotated after you add models: it encrypts the provider credentials stored in your database, and changing it makes them unreadable. Generate a strong random value and store both keys in your cloud's secret manager. - -Official images are published to `ghcr.io/berriai` and mirrored at `docker.litellm.ai/berriai`. Use `ghcr.io/berriai/litellm-database` for monolithic deployments with Postgres (it bundles the Prisma toolchain), and pin a version tag rather than `latest` or a moving tag, so rollbacks are deterministic. - -## Provision the data stores - -The Helm path needs a PostgreSQL database and a Redis reachable from your cluster. Use the managed services: - - - - -Provision [RDS PostgreSQL](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html) and [ElastiCache Redis](https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/WhatIs.html) in the same VPC as your EKS cluster, with security groups permitting the cluster's nodes on ports 5432 and 6379. - - - - -Provision [Cloud SQL PostgreSQL](https://cloud.google.com/sql/docs/postgres) and [Memorystore Redis](https://cloud.google.com/memorystore/docs/redis) with private IPs on the VPC your GKE cluster uses (Cloud SQL needs [Private Services Access](https://cloud.google.com/vpc/docs/private-services-access)). Use the instances' private IPs as the endpoints below. - - - - -```bash -az group create --name litellm-prod --location eastus - -az aks create --resource-group litellm-prod --name litellm-aks \ - --node-count 3 --enable-managed-identity - -az postgres flexible-server create --resource-group litellm-prod \ - --name litellm-db --database-name litellm \ - --tier GeneralPurpose --sku-name Standard_D2ds_v5 - -az redis create --resource-group litellm-prod --name litellm-redis \ - --location eastus --sku Standard --vm-size c1 -``` - -Docs: [AKS](https://learn.microsoft.com/en-us/azure/aks/what-is-aks), [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/overview), [Azure Cache for Redis](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-overview). Azure Cache for Redis serves TLS on port 6380, and TLS is enabled through the URL scheme: instead of `redis_host` and `redis_port`, set `redis_url: "rediss://:@litellm-redis.redis.cache.windows.net:6380"` under `router_settings` (the `rediss://` scheme turns TLS on). - - - - -## Deploy with Helm - -First create the secrets both charts consume: - -```bash -kubectl create secret generic litellm-masterkey \ - --from-literal=masterkey="sk-$(openssl rand -hex 24)" - -kubectl create secret generic litellm-db \ - --from-literal=username=litellm \ - --from-literal=password="" - -kubectl create secret generic litellm-env \ - --from-literal=LITELLM_SALT_KEY="sk-$(openssl rand -hex 24)" \ - --from-literal=REDIS_PASSWORD="" \ - --from-literal=OPENAI_API_KEY="" -``` - -Then pick a deployment mode: - - - - -```yaml title="values.yaml" -replicaCount: 3 - -image: - repository: ghcr.io/berriai/litellm-database - tag: "v1.90.2" # pin your version - -masterkeySecretName: litellm-masterkey -masterkeySecretKey: masterkey - -db: - useExisting: true - deployStandalone: false - endpoint: "" - database: litellm - secret: - name: litellm-db - usernameKey: username - passwordKey: password - -environmentSecrets: - - litellm-env - -proxy_config: - model_list: - - model_name: gpt-4o - litellm_params: - model: openai/gpt-4o - api_key: os.environ/OPENAI_API_KEY - router_settings: - redis_host: "" - redis_port: 6379 - redis_password: os.environ/REDIS_PASSWORD -``` - -```bash -helm install litellm oci://ghcr.io/berriai/litellm-helm -f values.yaml -``` - -The chart lives at [`deploy/charts/litellm-helm`](https://github.com/BerriAI/litellm/tree/main/deploy/charts/litellm-helm); the published chart versions carry LiteLLM release numbers (for example `1.90.2`), and `helm show values oci://ghcr.io/berriai/litellm-helm` lists every knob. Beyond the values above it supports autoscaling (`autoscaling.*` or `keda.*`), PodDisruptionBudgets (`pdb.*`), a Prometheus ServiceMonitor (`serviceMonitor.*`), read replica routing (`db.readReplicaUrl`, see [Database Read Replica](./db_read_replica.md)), graceful drain on shutdown (`lifecycle`), and ArgoCD or Helm hooks for the migrations job (`migrationJob.hooks.*`, see [Helm PreSync hooks](./prod.md#7-use-helm-presync-hook-for-database-migrations-beta)). - - - - -```yaml title="values.yaml" -masterKey: - secretName: litellm-masterkey - secretKey: masterkey - -database: - writer: - host: "" - port: 5432 - dbname: litellm - passwordSecret: - name: litellm-db - usernameKey: username - passwordKey: password - # optional: add database.reader to route reads to a replica - -redis: - host: "" - port: 6379 - passwordSecret: - name: litellm-env - passwordKey: REDIS_PASSWORD - -# one host fronting gateway, backend, and ui -ingress: - enabled: true - className: "" - host: llm.example.com -``` - -```bash -helm upgrade --install litellm \ - oci://ghcr.io/berriai/litellm/chart/litellm \ - --version 1.89.2 \ - -f values.yaml -``` - -This deploys `gateway`, `backend`, and `ui` as separate services with per-component autoscaling, so you can run many gateway replicas against a small fixed backend. It requires external Postgres and Redis (no bundled subcharts) and supports reader/writer database splits, IAM database auth, and Redis Cluster mode. See [Microservices Helm](./microservices_helm.md) for the full values reference. - - - - -Both charts run the migrations job automatically and keep `DISABLE_SCHEMA_UPDATE=true` on the proxy pods. Expose the service through your cloud's ingress: the [AWS Load Balancer Controller](https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html) on EKS, [GKE Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress) on GKE, or [Application Gateway Ingress (AGIC)](https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview) on AKS, with health checks on `/health/readiness`, then point your DNS record at the resulting load balancer. For secrets, prefer your cloud's secret manager over plain Kubernetes secrets ([Key Vault CSI driver](https://learn.microsoft.com/en-us/azure/aks/csi-secrets-store-driver) on AKS, for example); the charts consume whatever secret you mount. - -## Deploy with Terraform (AWS and GCP) - -The official modules deploy the full microservices stack (network, database, Redis, object storage, secrets, compute, load balancer, and a migrations job that runs before the services start) and are published to the Terraform Registry: - -- [`BerriAI/litellm/aws`](https://registry.terraform.io/modules/BerriAI/litellm/aws/latest) -- [`BerriAI/litellm/google`](https://registry.terraform.io/modules/BerriAI/litellm/google/latest) - - - - -Provisions a VPC with public and private subnets, an Aurora PostgreSQL cluster (writer plus reader, IAM database auth), ElastiCache Redis (multi-AZ, encrypted), an S3 bucket, Secrets Manager entries, an Application Load Balancer, and ECS Fargate services. - -```hcl title="main.tf" -module "litellm" { - source = "BerriAI/litellm/aws" - version = "~> 1.90" - - region = "us-east-1" - azs = ["us-east-1a", "us-east-1b"] - tenant = "acme" - env = "prod" - - ui_password = var.ui_password - litellm_license = var.litellm_license # optional, omit for open source - acm_certificate_arn = var.acm_certificate_arn # TLS is required by default - - proxy_config = { - model_list = [{ - model_name = "gpt-4o" - litellm_params = { - model = "openai/gpt-4o" - api_key = "os.environ/OPENAI_API_KEY" - } - }] - } - gateway_extra_secrets = { - OPENAI_API_KEY = var.openai_key_secret_arn - } -} -``` - -Before you apply: provision the TLS certificate in [AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html) (the module refuses a plaintext ALB unless you explicitly set `allow_plaintext_alb = true`), and create any provider-key secrets in [Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html) first, since `gateway_extra_secrets` takes their ARNs. After apply, point your DNS record at the ALB hostname. - -The module auto-generates the master key into Secrets Manager if you do not supply one. The application connects to Aurora with short-lived IAM tokens, so its `DATABASE_URL` carries no password (the database master password itself is generated into Secrets Manager and never touches the application). Every resource is named `-litellm-`, and the module declares no provider, so you can `for_each` it to run one stack per tenant. - - - - -Provisions a VPC with Private Services Access, Cloud SQL PostgreSQL (primary plus read replica), Memorystore Redis with TLS, a GCS bucket, Secret Manager entries, Cloud Run services, and a global HTTPS load balancer with serverless NEGs. - -```hcl title="main.tf" -module "litellm" { - source = "BerriAI/litellm/google" - version = "~> 1.90" - - project_id = "my-project" - region = "us-central1" - tenant = "acme" - env = "prod" - - ui_password = var.ui_password - litellm_license = var.litellm_license # optional - - # Cloud Run cannot pull from ghcr.io. Point this at an Artifact Registry - # remote repository backed by ghcr.io, or mirror the images. - image_registry = "us-central1-docker.pkg.dev/my-project/ghcr-remote/berriai" - - lb_domains = ["llm.example.com"] - - proxy_config = { - model_list = [{ - model_name = "gemini-2.5-pro" - litellm_params = { model = "vertex_ai/gemini-2.5-pro" } - }] - } -} -``` - -Three GCP-specific caveats. First, always override `image_registry`: it defaults to `ghcr.io/berriai`, which Cloud Run cannot pull from, so the apply succeeds but the services fail at image pull. Point it at an [Artifact Registry remote repository](https://cloud.google.com/artifact-registry/docs/repositories/remote-overview) that proxies `ghcr.io`. Second, the database uses password authentication through Secret Manager rather than IAM auth; LiteLLM's IAM token support is AWS RDS specific. Third, create the DNS record for `lb_domains` pointing at the load balancer IP after apply; the [Google-managed certificate](https://cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs) will not finish provisioning until the domain resolves to it. - - - - -## Verify the deployment - -Confirm the proxy is up and can reach its database: - -```bash -curl -s https://llm.example.com/health/readiness -``` - -Then open the Admin UI at `https://llm.example.com/ui` and log in with your master key. - -1. **Add a model.** Go to **Models + Endpoints** and click **Add Model**: pick the provider, the model, and enter the provider credentials. With `STORE_MODEL_IN_DB=True` the model is saved to your database, so you manage models here rather than in config files. - -Adding a model in the LiteLLM Admin UI - -2. **Create a key.** Go to **Virtual Keys** and click **Create New Key**, scoping it to the model you just added. - -Creating a virtual key in the LiteLLM Admin UI - -3. **Send a request.** Go to the **Test Key** playground, select your key and model, and send a message. A response here proves the full path: load balancer, proxy, database, and provider credentials. - -Test Key playground in the LiteLLM Admin UI - -## Next steps - -Harden the deployment with the [production checklist](./prod.md) (worker counts, machine sizing, Redis settings, graceful degradation). Add regions with [Multi-Region Deployment](./multi_region.md). For very high throughput (1000+ RPS), see [resolving DB deadlocks](./db_deadlocks.md). diff --git a/docs/proxy/docker_quick_start.md b/docs/proxy/docker_quick_start.md index 65be1e3bc..0b4d4ec88 100644 --- a/docs/proxy/docker_quick_start.md +++ b/docs/proxy/docker_quick_start.md @@ -1,877 +1,215 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import Image from '@theme/IdealImage'; - -# Getting Started Tutorial - -End-to-End tutorial for LiteLLM Proxy to: -- Add an Azure OpenAI model -- Make a successful /chat/completion call -- Generate a virtual key -- Set RPM limit on virtual key - -## Quick Install (Recommended for local / beginners) - -New to LiteLLM? This is the easiest way to get started locally. One command installs LiteLLM and walks you through setup interactively — no config files to write by hand. - -### 1. Install - -```bash -curl -fsSL https://raw.githubusercontent.com/BerriAI/litellm/main/scripts/install.sh | sh -``` - -This detects your OS, installs `litellm[proxy]`, and drops you straight into the setup wizard. - -### 2. Follow the wizard - -``` -$ litellm --setup - - Welcome to LiteLLM - - Choose your LLM providers - ○ 1. OpenAI GPT-4o, GPT-4o-mini, o1 - ○ 2. Anthropic Claude Opus, Sonnet, Haiku - ○ 3. Azure OpenAI GPT-4o via Azure - ○ 4. Google Gemini Gemini 2.0 Flash, 1.5 Pro - ○ 5. AWS Bedrock Claude, Llama via AWS - ○ 6. Ollama Local models - - ❯ Provider(s): 1,2 - - ❯ OpenAI API key: sk-... - ❯ Anthropic API key: sk-ant-... - - ❯ Port [4000]: - ❯ Master key [auto-generate]: - - ✔ Config saved → ./litellm_config.yaml - - ❯ Start the proxy now? (Y/n): -``` - -The wizard walks you through: -1. Pick your LLM providers (OpenAI, Anthropic, Azure, Bedrock, Gemini, Ollama) -2. Enter API keys for each provider -3. Set a port and master key (or accept the defaults) -4. Config is saved to `./litellm_config.yaml` and the proxy starts immediately - -### 3. Make a call - -Your proxy is running on `http://0.0.0.0:4000`. Test it: - -```bash -curl -X POST 'http://0.0.0.0:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer ' \ --d '{ - "model": "gpt-4o", - "messages": [{"role": "user", "content": "Hello!"}] -}' -``` - -:::tip Already have uv installed? -You can skip the curl install and run `litellm --setup` directly after `uv tool install 'litellm[proxy]'`. -::: - --- - -## Pre-Requisites - -Choose your install method. **Docker Compose** users complete their full setup inside the tab and are done. **Docker** and **LiteLLM CLI** users continue with the steps below the tabs. - - - - - -```bash -docker pull docker.litellm.ai/berriai/litellm:latest -``` - -[**See all docker images**](https://github.com/orgs/BerriAI/packages) - - - - - -```shell -$ uv tool install 'litellm[proxy]' -``` - - - - - -Docker Compose bundles LiteLLM with a Postgres database. Follow the steps below — the proxy will be fully running by the end. - -### Step 1 — Pull the LiteLLM database image - -LiteLLM provides a dedicated `litellm-database` image for proxy deployments that connect to Postgres. - -```bash -docker pull ghcr.io/berriai/litellm-database:latest -``` - -See all available tags on the [GitHub Container Registry](https://github.com/BerriAI/litellm/pkgs/container/litellm-database). - +title: Docker Quickstart +description: Deploy LiteLLM with Docker Compose and go from zero to your first gateway request in about five minutes, using the Admin UI for everything after startup. --- -### Step 2 — Set up a database - -Complete all three config files **before** running `docker compose up`. The proxy server will not start correctly if any of these are missing. - -#### 2.1 — Get `docker-compose.yml` and create `.env` - -```bash -# Get the docker compose file -curl -O https://raw.githubusercontent.com/BerriAI/litellm/main/docker-compose.yml - -# Add the master key - you can change this after setup -echo 'LITELLM_MASTER_KEY="sk-1234"' > .env - -# Add the litellm salt key — cannot be changed after adding a model -# Used to encrypt/decrypt your LLM API key credentials -# Generate a strong random value: https://1password.com/password-generator/ -echo 'LITELLM_SALT_KEY="sk-1234"' >> .env - -# Add your model credentials -echo 'AZURE_API_BASE="https://openai-***********/"' >> .env -echo 'AZURE_API_KEY="your-azure-api-key"' >> .env -``` - -#### 2.2 — Create `config.yaml` - -The default `docker-compose.yml` starts a Postgres container at `db:5432`. Your `config.yaml` must include `database_url` pointing to it: - -```yaml -model_list: - - model_name: gpt-4o - litellm_params: - model: azure/my_azure_deployment - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY - api_version: "2025-01-01-preview" - -general_settings: - master_key: sk-1234 # 🔑 your proxy admin key (must start with sk-) - database_url: "postgresql://llmproxy:dbpassword9090@db:5432/litellm" -``` +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; -:::tip -`database_url` enables virtual keys, spend tracking, and the UI. Replace it with your [Supabase](https://supabase.com/) or [Neon](https://neon.tech/) connection string if you prefer a managed database. -::: +# Docker Quickstart -#### 2.3 — Create `prometheus.yml` +LiteLLM ships as a ready-to-run gateway. You start one Docker Compose stack, then do everything else in your browser: connect providers, add models, create keys, and send test requests from the built-in Admin UI. No config files are required for this guide. -This file **must exist as a file** before `docker compose up`. If it is missing, Docker auto-creates it as an empty directory and the Prometheus container fails to start. +By the end you will have LiteLLM running at `http://localhost:4000` with a model connected, a virtual key issued, and a request served through the gateway. -```yaml -global: - scrape_interval: 15s - evaluation_interval: 15s - -scrape_configs: - - job_name: "litellm" - static_configs: - - targets: ["litellm:4000"] -``` +## 1. Start LiteLLM -Also verify that the `config.yaml` volume mount and `--config` flag are **not commented out** in `docker-compose.yml`: +Save this as `docker-compose.yml`: ```yaml services: litellm: + image: docker.litellm.ai/berriai/litellm-database:latest + ports: + - "4000:4000" + environment: + LITELLM_MASTER_KEY: sk-1234 + LITELLM_SALT_KEY: sk-XXXXXXXXXXXXXXXX + DATABASE_URL: postgresql://litellm:litellm@db:5432/litellm + STORE_MODEL_IN_DB: "True" + depends_on: + db: + condition: service_healthy + + db: + image: postgres:16 + environment: + POSTGRES_USER: litellm + POSTGRES_PASSWORD: litellm + POSTGRES_DB: litellm + healthcheck: + test: ["CMD-SHELL", "pg_isready -U litellm"] + interval: 5s + timeout: 5s + retries: 10 volumes: - - ./config.yaml:/app/config.yaml # ✅ must be uncommented - command: - - "--config=/app/config.yaml" # ✅ must be uncommented -``` + - postgres_data:/var/lib/postgresql/data -:::warning -All three files (`.env`, `config.yaml`, `prometheus.yml`) must be present before running `docker compose up`. See [Troubleshooting](#troubleshooting) if you run into issues. -::: - ---- - -### Step 3 — Start the proxy server and test it - -After `config.yaml`, `prometheus.yml`, and `.env` are complete, start the proxy: - -```bash -docker compose up +volumes: + postgres_data: ``` -Once running, test it with a curl request: +Then start it: ```bash -curl -X POST 'http://0.0.0.0:4000/chat/completions' \ - -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer sk-1234' \ - -d '{ - "model": "gpt-4o", - "messages": [{"role": "user", "content": "Hello!"}] - }' +docker compose up -d ``` -**Expected response:** +That is the entire terminal portion of this guide. The stack runs the gateway on port 4000 and a Postgres database that stores your models, keys, and spend logs. For anything beyond local evaluation, pin a specific release tag instead of `latest`; see [available tags](https://github.com/BerriAI/litellm/pkgs/container/litellm-database). -```json -{ - "id": "chatcmpl-abcd", - "created": 1773817678, - "model": "gpt-4o", - "object": "chat.completion", - "system_fingerprint": "fp_6b1ef07cda", - "choices": [ - { - "finish_reason": "stop", - "index": 0, - "message": { - "content": "Hello! How can I assist you today?", - "role": "assistant", - "annotations": [] - } - } - ], - "usage": { - "completion_tokens": 9, - "prompt_tokens": 9, - "total_tokens": 18, - "completion_tokens_details": { - "accepted_prediction_tokens": 0, - "audio_tokens": 0, - "reasoning_tokens": 0, - "rejected_prediction_tokens": 0 - }, - "prompt_tokens_details": { - "audio_tokens": 0, - "cached_tokens": 0 - } - }, - "service_tier": "default" -} -``` +:::warning Set a real salt key +`LITELLM_SALT_KEY` encrypts the provider API keys you add in the UI. Set it to a long random value before adding models, and never change it afterwards; credentials encrypted with the old value cannot be decrypted with a new one. A password generator works well for this. +::: ---- +## 2. Log in to the Admin UI -### Optional — Navigate to the LiteLLM UI and generate a virtual key +Open [http://localhost:4000/ui](http://localhost:4000/ui). The username is `admin` and the password is your `LITELLM_MASTER_KEY` value (`sk-1234` in the compose file above). -Open [http://localhost:4000/ui](http://localhost:4000/ui) in your browser and log in with your master key (`sk-1234`). +LiteLLM Admin UI login page -Navigate to **Virtual Keys** and click **+ Create New Key**: +## 3. Add your first model -LiteLLM UI — Create Virtual Key +Go to **Models + Endpoints**, open the **Add Model** tab, pick your provider and the models you want to expose, and paste your provider API key. LiteLLM ships with each provider's model catalog, so you select models rather than type them. -Virtual keys let you track spend, set rate limits, and control model access per user or team. +Add Model form with OpenAI provider and gpt-5.5 selected - +Click **Test Connect** to verify the key against the provider, then **Add Model**. It appears under **All Models** with its pricing already mapped: - +All Models list showing the newly added model with cost data -:::note Docker Compose users -Your setup is complete — the steps below are for **Docker** and **LiteLLM CLI** users only. +:::tip Keep provider keys out of the UI +If you prefer to manage provider keys as environment variables, add them to the `litellm` service in your compose file (for example `OPENAI_API_KEY: ${OPENAI_API_KEY}`) and enter `os.environ/OPENAI_API_KEY` in the API key field instead of the raw key. ::: ---- - -## Step 1 — Add a model - -Control LiteLLM Proxy with a `config.yaml` file. Create one with your Azure model: - -```yaml -model_list: - - model_name: gpt-4o - litellm_params: - model: azure/my_azure_deployment - api_base: os.environ/AZURE_API_BASE - api_key: "os.environ/AZURE_API_KEY" - api_version: "2025-01-01-preview" # [OPTIONAL] litellm uses the latest azure api_version by default -``` ---- - -### Model List Specification +## 4. Send a test message -You can read more about how model resolution works in the [Model Configuration](#understanding-model-configuration) section. +Go to **Playground**, select your model, and send a message. The request goes through the gateway to your provider, and the response comes back with latency and token counts: -- **`model_name`** (`str`) - This field should contain the name of the model as received. -- **`litellm_params`** (`dict`) [See All LiteLLM Params](https://github.com/BerriAI/litellm/blob/559a6ad826b5daef41565f54f06c739c8c068b28/litellm/types/router.py#L222) - - **`model`** (`str`) - Specifies the model name to be sent to `litellm.acompletion` / `litellm.aembedding`, etc. This is the identifier used by LiteLLM to route to the correct model + provider logic on the backend. - - **`api_key`** (`str`) - The API key required for authentication. It can be retrieved from an environment variable using `os.environ/`. - - **`api_base`** (`str`) - The API base for your azure deployment. - - **`api_version`** (`str`) - The API Version to use when calling Azure's OpenAI API. Get the latest Inference API version [here](https://learn.microsoft.com/en-us/azure/ai-services/openai/api-version-deprecation?source=recommendations#latest-preview-api-releases). +Playground showing a live response from the model with latency and token metrics +Your gateway works end to end. The **Get Code** button in the Playground generates the equivalent API call for your language. ---- +## 5. Create a virtual key -### Useful Links -- [**All Supported LLM API Providers (OpenAI/Bedrock/Vertex/etc.)**](../providers/) -- [**Full Config.Yaml Spec**](./configs.md) -- [**Pass provider-specific params**](../completion/provider_specific_params.md#proxy-usage) +Virtual keys are what you hand to applications and teammates instead of raw provider keys. Each key can carry its own budget, rate limits, and model access, and all its spend is tracked automatically. +Go to **Virtual Keys**, click **+ Create New Key**, give it a name, and click **Create Key**: -## 2. Make a successful /chat/completion call +Save your Key modal showing the newly created virtual key -LiteLLM Proxy is 100% OpenAI-compatible. Test your azure model via the `/chat/completions` route. +Copy the key now; it is shown only once. -### 2.1 Start Proxy +## 6. Call the gateway from your app -Save your config.yaml from step 1. as `litellm_config.yaml`. +The gateway is OpenAI-compatible, so any OpenAI SDK works by pointing it at `http://localhost:4000` with your virtual key. - - - + ```bash -docker run \ - -v $(pwd)/litellm_config.yaml:/app/config.yaml \ - -e AZURE_API_KEY=d6*********** \ - -e AZURE_API_BASE=https://openai-***********/ \ - -p 4000:4000 \ - docker.litellm.ai/berriai/litellm:latest \ - --config /app/config.yaml --detailed_debug - -# RUNNING on http://0.0.0.0:4000 -``` - - - - - -```shell -$ litellm --config /app/config.yaml --detailed_debug -``` - - - - - - -Confirm your config was loaded correctly — you should see this in the logs: - -``` -Loaded config YAML (api_key and environment_variables are not shown): -{ - "model_list": [ - { - "model_name": ... -``` - -### 2.2 Make Call - -LiteLLM Proxy is 100% OpenAI-compatible. Test your model via `/chat/completions`: - -```bash -curl -X POST 'http://0.0.0.0:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-1234' \ --d '{ - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are an LLM named gpt-4o" - }, - { - "role": "user", - "content": "what is your name?" - } - ] -}' +curl http://localhost:4000/v1/chat/completions \ + -H 'Authorization: Bearer sk-' \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "gpt-5.5", + "messages": [{"role": "user", "content": "Say hello in five words."}] + }' ``` -**Expected Response** +Expected response: -```bash +```json { - "id": "chatcmpl-BcO8tRQmQV6Dfw6onqMufxPkLLkA8", - "created": 1748488967, - "model": "gpt-4o-2024-11-20", + "id": "chatcmpl-DzGKiNRbQ4fe9Mgt8HSHFQ6ApfRJi", + "model": "gpt-5.5", "object": "chat.completion", - "system_fingerprint": "fp_ee1d74bde0", "choices": [ { "finish_reason": "stop", "index": 0, "message": { - "content": "My name is **gpt-4o**! How can I assist you today?", - "role": "assistant", - "tool_calls": null, - "function_call": null, - "annotations": [] + "content": "Hello, nice to meet you.", + "role": "assistant" } } ], "usage": { - "completion_tokens": 19, - "prompt_tokens": 28, - "total_tokens": 47, - "completion_tokens_details": { - "accepted_prediction_tokens": 0, - "audio_tokens": 0, - "reasoning_tokens": 0, - "rejected_prediction_tokens": 0 - }, - "prompt_tokens_details": { - "audio_tokens": 0, - "cached_tokens": 0 - } - }, - "service_tier": null, - "prompt_filter_results": [ - { - "prompt_index": 0, - "content_filter_results": { - "hate": { - "filtered": false, - "severity": "safe" - }, - "self_harm": { - "filtered": false, - "severity": "safe" - }, - "sexual": { - "filtered": false, - "severity": "safe" - }, - "violence": { - "filtered": false, - "severity": "safe" - } - } - } - ] -} -``` - - - -### Useful Links -- [All Supported LLM API Providers (OpenAI/Bedrock/Vertex/etc.)](../providers/) -- [Call LiteLLM Proxy via OpenAI SDK, Langchain, etc.](./user_keys.md#request-format) -- [All API Endpoints Swagger](https://litellm-api.up.railway.app/#/chat%2Fcompletions) -- [Other/Non-Chat Completion Endpoints](../embedding/supported_embedding.md) -- [Pass-through for VertexAI, Bedrock, etc.](../pass_through/vertex_ai.md) - -## Optional: Generate a virtual key - -Track spend and control model access via virtual keys for the proxy. - -### Prerequisite — Set up a database - -:::note Docker Compose users -Your Postgres container is already running — skip ahead to [Create Key w/ RPM Limit](#create-key-w-rpm-limit) below. -::: - -**Docker / LiteLLM CLI users** — you need a Postgres database (e.g. [Supabase](https://supabase.com/), [Neon](https://neon.tech/), or self-hosted). Add `general_settings` to your `config.yaml`: - -```yaml -model_list: - - model_name: gpt-4o - litellm_params: - model: azure/my_azure_deployment - api_base: os.environ/AZURE_API_BASE - api_key: "os.environ/AZURE_API_KEY" - api_version: "2025-01-01-preview" # [OPTIONAL] litellm uses the latest azure api_version by default - -general_settings: - master_key: sk-1234 - database_url: "postgresql://:@:/" # 👈 KEY CHANGE -``` - -Save config.yaml as `litellm_config.yaml` before continuing. - -You must finish this setup before starting the proxy server. - ---- - -**What is `general_settings`?** - -These are settings for the LiteLLM Proxy Server. - -See All General Settings [here](https://docs.litellm.ai/docs/proxy/config_settings). - -1. **`master_key`** (`str`) - - **Description**: - - Set a `master key`, this is your Proxy Admin key - you can use this to create other keys (🚨 must start with `sk-`). - - **Usage**: - - **Set on config.yaml** set your master key under `general_settings:master_key`, example - - `master_key: sk-1234` - - **Set env variable** set `LITELLM_MASTER_KEY` - -2. **`database_url`** (str) - - **Description**: - - Set a `database_url`, this is the connection to your Postgres DB, which is used by litellm for generating keys, users, teams. - - **Usage**: - - **Set on config.yaml** set your `database_url` under `general_settings:database_url`, example - - `database_url: "postgresql://..."` - - Set `DATABASE_URL=postgresql://:@:/` in your env - -### Start Proxy - -```bash -docker run \ - -v $(pwd)/litellm_config.yaml:/app/config.yaml \ - -e AZURE_API_KEY=d6*********** \ - -e AZURE_API_BASE=https://openai-***********/ \ - -p 4000:4000 \ - ghcr.io/berriai/litellm-database:latest \ - --config /app/config.yaml --detailed_debug -``` - -### Create Key w/ RPM Limit - -Create a key with `rpm_limit: 1`. This will only allow 1 request per minute for calls to proxy with this key. - -```bash -curl -L -X POST 'http://0.0.0.0:4000/key/generate' \ --H 'Authorization: Bearer sk-1234' \ --H 'Content-Type: application/json' \ --d '{ - "rpm_limit": 1 -}' -``` - -[**See full API Spec**](https://litellm-api.up.railway.app/#/key%20management/generate_key_fn_key_generate_post) - -**Expected Response** - -```bash -{ - "key": "sk-12..." -} -``` - -### Test it! - -**Use the virtual key you just created.** - -1st call - Expect to work! - -```bash -curl -X POST 'http://0.0.0.0:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-12...' \ --d '{ - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are a helpful math tutor. Guide the user through the solution step by step." - }, - { - "role": "user", - "content": "how can I solve 8x + 7 = -23" - } - ] -}' -``` - -**Expected Response** - -```bash -{ - "id": "chatcmpl-2076f062-3095-4052-a520-7c321c115c68", - "choices": [ - ... -} -``` - -2nd call - Expect to fail! - -**Why did this call fail?** - -We set the virtual key's requests per minute (RPM) limit to 1. This has now been crossed. - - -```bash -curl -X POST 'http://0.0.0.0:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-12...' \ --d '{ - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are a helpful math tutor. Guide the user through the solution step by step." - }, - { - "role": "user", - "content": "how can I solve 8x + 7 = -23" - } - ] -}' -``` - -**Expected Response** - -```bash -{ - "error": { - "message": "LiteLLM Rate Limit Handler for rate limit type = key. Crossed TPM / RPM / Max Parallel Request Limit. current rpm: 1, rpm limit: 1, current tpm: 348, tpm limit: 9223372036854775807, current max_parallel_requests: 0, max_parallel_requests: 9223372036854775807", - "type": "None", - "param": "None", - "code": "429" + "completion_tokens": 70, + "prompt_tokens": 12, + "total_tokens": 82 } } ``` -### Useful Links - -- [Creating Virtual Keys](./virtual_keys.md) -- [Key Management API Endpoints Swagger](https://litellm-api.up.railway.app/#/key%20management) -- [Set Budgets / Rate Limits per key/user/teams](./users.md) -- [Dynamic TPM/RPM Limits for keys](./team_budgets.md#dynamic-tpmrpm-allocation) - -## Key Concepts - -This section explains key concepts on LiteLLM AI Gateway. + + -### Understanding Model Configuration +```python +from openai import OpenAI -For this config.yaml example: +client = OpenAI( + base_url="http://localhost:4000", + api_key="sk-", +) -```yaml -model_list: - - model_name: gpt-4o - litellm_params: - model: azure/my_azure_deployment - api_base: os.environ/AZURE_API_BASE - api_key: "os.environ/AZURE_API_KEY" - api_version: "2025-01-01-preview" # [OPTIONAL] litellm uses the latest azure api_version by default +response = client.chat.completions.create( + model="gpt-5.5", + messages=[{"role": "user", "content": "Say hello in five words."}], +) +print(response.choices[0].message.content) ``` -**How Model Resolution Works:** - -``` -Client Request LiteLLM Proxy Provider API -────────────── ──────────────── ───────────── - -POST /chat/completions -{ 1. Looks up model_name - "model": "gpt-4o" ──────────▶ in config.yaml - ... -} 2. Finds matching entry: - model_name: gpt-4o - - 3. Extracts litellm_params: - model: azure/my_azure_deployment - api_base: https://... - api_key: sk-... - - 4. Routes to provider ──▶ Azure OpenAI API - POST /deployments/my_azure_deployment/... -``` + + -**Breaking Down the `model` Parameter under `litellm_params`:** +```javascript +import OpenAI from "openai"; -```yaml -model_list: - - model_name: gpt-4o # What the client calls - litellm_params: - model: azure/my_azure_deployment # / - ───── ─────────────────── - │ │ - │ └─────▶ Model name sent to the provider API - │ - └─────────────────▶ Provider that LiteLLM routes to -``` - -**Visual Breakdown:** +const client = new OpenAI({ + baseURL: "http://localhost:4000", + apiKey: "sk-", +}); +const response = await client.chat.completions.create({ + model: "gpt-5.5", + messages: [{ role: "user", content: "Say hello in five words." }], +}); +console.log(response.choices[0].message.content); ``` -model: azure/my_azure_deployment - └─┬─┘ └─────────┬─────────┘ - │ │ - │ └────▶ The actual model identifier that gets sent to Azure - │ (e.g., your deployment name, or the model name) - │ - └──────────────────▶ Tells LiteLLM which provider to use - (azure, openai, anthropic, bedrock, etc.) -``` - -**Key Concepts:** -- **`model_name`**: The alias your client uses to call the model. This is what you send in your API requests (e.g., `gpt-4o`). - -- **`model` (in litellm_params)**: Format is `/` - - **Provider** (before `/`): Routes to the correct LLM provider (e.g., `azure`, `openai`, `anthropic`, `bedrock`) - - **Model identifier** (after `/`): The actual model/deployment name sent to that provider's API - -**Advanced Configuration Examples:** - -For custom OpenAI-compatible endpoints (e.g., vLLM, Ollama, custom deployments): - -```yaml -model_list: - - model_name: my-custom-model - litellm_params: - model: openai/nvidia/llama-3.2-nv-embedqa-1b-v2 - api_base: http://my-service.svc.cluster.local:8000/v1 - api_key: "sk-1234" -``` + + -**Breaking down complex model paths:** +## The whole flow, end to end -``` -model: openai/nvidia/llama-3.2-nv-embedqa-1b-v2 - └─┬──┘ └────────────┬────────────────┘ - │ │ - │ └────▶ Full model string sent to the provider API - │ (in this case: "nvidia/llama-3.2-nv-embedqa-1b-v2") - │ - └──────────────────────▶ Provider (openai = OpenAI-compatible API) -``` +Animated walkthrough: add a model, test it in the Playground, create a virtual key -The key point: Everything after the first `/` is passed as-is to the provider's API. +## Running without a database -**Common Patterns:** +If you only need the OpenAI-compatible API (no Admin UI model management, virtual keys, or spend tracking), you can run the plain `litellm` image with a config file instead: ```yaml +# litellm_config.yaml model_list: - # Azure deployment - - model_name: gpt-4 - litellm_params: - model: azure/gpt-4-deployment - api_base: https://my-azure.openai.azure.com - - # OpenAI - - model_name: gpt-4 + - model_name: gpt-5.5 litellm_params: - model: openai/gpt-4 + model: openai/gpt-5.5 api_key: os.environ/OPENAI_API_KEY - - # Custom OpenAI-compatible endpoint - - model_name: my-llama-model - litellm_params: - model: openai/meta/llama-3-8b - api_base: http://my-vllm-server:8000/v1 - api_key: "optional-key" - - # Bedrock - - model_name: claude-3 - litellm_params: - model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 - aws_region_name: us-east-1 -``` - - -## Troubleshooting - -### `prometheus.yml` mount error — "not a directory" - -If you see: - -```bash -Error: cannot create subdirectories in ".../prometheus.yml": not a directory -``` - -Docker created `prometheus.yml` as an **empty directory** instead of a file. This happens when the file is missing at `docker compose up` time. - -Fix it: -Then create the file (see [Step 2.3 — Create `prometheus.yml`](#23--create-prometheusyml)) and run `docker compose up` again. -```bash -rm -rf prometheus.yml -``` - -Then create the file (see [Step 2.4](#step-24--create-prometheusyml)) and run `docker compose up` again. - -### Non-root docker image? - -If you need to run the docker image as a non-root user, use [this](https://github.com/BerriAI/litellm/pkgs/container/litellm-non_root). - -### SSL Verification Issue / Connection Error. - -If you see - -```bash -ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1006) ``` -OR - ```bash -Connection Error. -``` - -You can disable ssl verification with: - -```yaml -model_list: - - model_name: gpt-4o - litellm_params: - model: azure/my_azure_deployment - api_base: os.environ/AZURE_API_BASE - api_key: "os.environ/AZURE_API_KEY" - api_version: "2025-01-01-preview" - -litellm_settings: - ssl_verify: false # 👈 KEY CHANGE -``` - - -### (DB) All connection attempts failed - - -If you see: - -``` -httpx.ConnectError: All connection attempts failed - -ERROR: Application startup failed. Exiting. -3:21:43 - LiteLLM Proxy:ERROR: utils.py:2207 - Error getting LiteLLM_SpendLogs row count: All connection attempts failed -``` - -This might be a DB permission issue. - -1. Validate db user permission issue - -Try creating a new database. - -```bash -STATEMENT: CREATE DATABASE "litellm" -``` - -If you get: - -``` -ERROR: permission denied to create -``` - -This indicates you have a permission issue. - -2. Grant permissions to your DB user - -It should look something like this: - -``` -psql -U postgres -``` - -``` -CREATE DATABASE litellm; -``` - -On CloudSQL, this is: - -``` -GRANT ALL PRIVILEGES ON DATABASE litellm TO your_username; +docker run \ + -v $(pwd)/litellm_config.yaml:/app/config.yaml \ + -e OPENAI_API_KEY= \ + -e LITELLM_MASTER_KEY=sk-1234 \ + -p 4000:4000 \ + docker.litellm.ai/berriai/litellm:latest \ + --config /app/config.yaml ``` +Requests authenticate with the master key. See the [full config reference](./configs.md) for everything the file supports. -**What is `litellm_settings`?** - -LiteLLM Proxy uses the [LiteLLM Python SDK](https://docs.litellm.ai/docs/routing) for handling LLM API calls. - -`litellm_settings` are module-level params for the LiteLLM Python SDK (equivalent to doing `litellm.` on the SDK). You can see all params [here](https://github.com/BerriAI/litellm/blob/208fe6cb90937f73e0def5c97ccb2359bf8a467b/litellm/__init__.py#L114) - -## Support & Talk with founders - -- [Schedule Demo 👋](https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version) - -- [Community Discord 💭](https://discord.gg/wuPM9dRgDw) -- [Community Slack 💭](https://www.litellm.ai/support) - -- Our emails ✉️ ishaan@berri.ai / krrish@berri.ai +## Next steps -[![Chat on WhatsApp](https://img.shields.io/static/v1?label=Chat%20on&message=WhatsApp&color=success&logo=WhatsApp&style=flat-square)](https://wa.link/huol9n) [![Chat on Discord](https://img.shields.io/static/v1?label=Chat%20on&message=Discord&color=blue&logo=Discord&style=flat-square)](https://discord.gg/wuPM9dRgDw) +Going to production: the [Deploy guide](./deploy.md) covers Helm, Terraform, and Kubernetes on AWS, GCP, and Azure, and the [production checklist](./prod.md) covers hardening and tuning. Full container and database options, including Redis and Prometheus, are covered in the repo [docker-compose.yml](https://github.com/BerriAI/litellm/blob/main/docker-compose.yml). diff --git a/docs/proxy/health.md b/docs/proxy/health.md index edbc32499..6adce9bd8 100644 --- a/docs/proxy/health.md +++ b/docs/proxy/health.md @@ -1,357 +1,76 @@ -# Health Checks -Use this to health check all LLMs defined in your config.yaml - -## When to Use Each Endpoint - -| Endpoint | Use Case | Purpose | -|----------|----------|---------| -| `/health/liveliness` | **Container liveness probes** | Basic alive check - use for container restart decisions | -| `/health/readiness` | **Load balancer health checks** | Ready to accept traffic - includes DB connection status | -| `/health` | **Model health monitoring** | Comprehensive LLM model health - makes actual API calls | -| `/health/services` | **Service debugging** | Check specific integrations (datadog, langfuse, etc.) | -| `/health/shared-status` | **Multi-pod coordination** | Monitor shared health check state across pods | - -## Summary - -The proxy exposes: -* a /health endpoint which returns the health of the LLM APIs -* a /health/readiness endpoint for returning if the proxy is ready to accept requests -* a /health/liveliness endpoint for returning if the proxy is alive -* a /health/shared-status endpoint for monitoring shared health check coordination across pods - -## Shared Health Check State - -When running multiple LiteLLM proxy pods, you can enable shared health check state to coordinate health checks across pods and avoid duplicate API calls. This is especially beneficial for expensive models like Gemini 2.5-pro. - -**Key Benefits:** -- Reduces duplicate health checks across pods -- Saves costs on expensive model API calls -- Reduces monitoring noise and logging -- Improves resource efficiency +import Image from '@theme/IdealImage'; -**Requirements:** -- Redis for shared state coordination -- Background health checks enabled -- Multiple proxy pods +# Health Checks -For detailed configuration and usage, see [Shared Health Check State](./shared_health_check.md). +Two things consume the proxy's health state. Your orchestrator (Kubernetes, a load balancer, an uptime monitor) polls lightweight probe endpoints to decide whether the process is up and ready for traffic. You, the operator, check whether each configured LLM can actually serve requests. This page covers both. -## `/health` -#### Request -Make a GET Request to `/health` on the proxy +## Probe endpoints -:::info -**This endpoint makes an LLM API call to each model to check if it is healthy.** -::: +These endpoints answer "is the gateway process up and able to serve traffic?" without making any LLM calls. They are the canonical liveness and readiness contract for the proxy. -```shell -curl --location 'http://0.0.0.0:4000/health' -H "Authorization: Bearer sk-1234" -``` +| Endpoint | Auth | Returns | Meaning | +|----------|------|---------|---------| +| `GET /health/liveliness` | none | `"I'm alive!"` (200), or `{"status": "shutting_down"}` (503) during graceful shutdown | The process is up. No dependencies are checked. `GET /health/liveness` is an alias with the Kubernetes spelling; both are real routes | +| `GET /health/readiness` | none | `{"status": "healthy", "db": ...}` (200) when ready; 503 when a configured database is unreachable | The worker is ready to accept traffic. The `db` field is `"connected"`, `"disconnected"`, or `"Not connected"` when no database is configured | -You can also run `litellm -health` it makes a `get` request to `http://0.0.0.0:4000/health` for you -``` -litellm --health -``` -#### Response -```shell -{ - "healthy_endpoints": [ - { - "model": "azure/gpt-35-turbo", - "api_base": "https://my-endpoint-canada-berri992.openai.azure.com/" - }, - { - "model": "azure/gpt-35-turbo", - "api_base": "https://my-endpoint-europe-berri-992.openai.azure.com/" - } - ], - "unhealthy_endpoints": [ - { - "model": "azure/gpt-35-turbo", - "api_base": "https://openai-france-1234.openai.azure.com/" - } - ] -} -``` - -### Embedding Models - -To run embedding health checks, specify the mode as "embedding" in your config for the relevant model. - -```yaml -model_list: - - model_name: azure-embedding-model - litellm_params: - model: azure/azure-embedding-model - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY - api_version: "2023-07-01-preview" - model_info: - mode: embedding # 👈 ADD THIS -``` +The `db` value lets an orchestrator distinguish a healthy worker from one that booted but cannot reach its database. When the database is configured and unreachable, readiness returns 503 so the pod is pulled from rotation. -### Image Generation Models +The default readiness payload is deliberately low-detail so it is safe to expose to unauthenticated probes. For full diagnostics (callbacks, cache, version), either set `general_settings.allow_public_health_readiness_details: true` to expand `/health/readiness` itself, or call the authenticated `GET /health/readiness/details` endpoint. -To run image generation health checks, specify the mode as "image_generation" in your config for the relevant model. +A minimal Kubernetes probe pair on the proxy's port 4000: ```yaml -model_list: - - model_name: dall-e-3 - litellm_params: - model: azure/dall-e-3 - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY - api_version: "2023-07-01-preview" - model_info: - mode: image_generation # 👈 ADD THIS +livenessProbe: + httpGet: + path: /health/liveliness + port: 4000 +readinessProbe: + httpGet: + path: /health/readiness + port: 4000 ``` -#### Custom Health Check Prompt +For full deployment manifests, see the [Deploy guide](./deploy.md) and the [production checklist](./prod.md). -By default, health checks use the prompt `"test from litellm"`. You can customize this prompt globally by setting an environment variable, or per-model via config: +## Model health in the Admin UI -```bash -DEFAULT_HEALTH_CHECK_PROMPT="this is a test prompt" -``` - -### Text Completion Models +The primary way to check whether your models are serving is the Admin UI. Go to Models + Endpoints, open the Health Status tab, and click Run All Checks. Each model shows a status, error details when it fails, and the last check and last success times. +Model Health Status tab showing a healthy model after Run All Checks -To run `/completions` health checks, specify the mode as "completion" in your config for the relevant model. +The API equivalent is `GET /health`, which accepts any valid key. It runs a real test request against every configured model, so it costs a few tokens per model. -```yaml -model_list: - - model_name: azure-text-completion - litellm_params: - model: azure/text-davinci-003 - api_base: os.environ/AZURE_API_BASE - api_key: os.environ/AZURE_API_KEY - api_version: "2023-07-01-preview" - model_info: - mode: completion # 👈 ADD THIS -``` - -### Speech to Text Models - -```yaml -model_list: - - model_name: whisper - litellm_params: - model: whisper-1 - api_key: os.environ/OPENAI_API_KEY - model_info: - mode: audio_transcription -``` - - -### Text to Speech Models - -```yaml -# OpenAI Text to Speech Models - - model_name: tts - litellm_params: - model: openai/tts-1 - api_key: "os.environ/OPENAI_API_KEY" - model_info: - mode: audio_speech - health_check_voice: alloy -``` - -You can specify a `health_check_voice` if you need to use a voice other than "alloy". - -### Rerank Models - -To run rerank health checks, specify the mode as "rerank" in your config for the relevant model. - -```yaml -model_list: - - model_name: rerank-english-v3.0 - litellm_params: - model: cohere/rerank-english-v3.0 - api_key: os.environ/COHERE_API_KEY - model_info: - mode: rerank -``` - -### Batch Models (Azure Only) - -For Azure models deployed as 'batch' models, set `mode: batch`. - -```yaml -model_list: - - model_name: "batch-gpt-4o-mini" - litellm_params: - model: "azure/batch-gpt-4o-mini" - api_key: os.environ/AZURE_API_KEY - api_base: os.environ/AZURE_API_BASE - model_info: - mode: batch +```shell +curl --location 'http://0.0.0.0:4000/health' -H "Authorization: Bearer sk-1234" ``` -Expected Response - - -```bash +```json { "healthy_endpoints": [ - { - "api_base": "https://...", - "model": "azure/gpt-4o-mini", - "x-ms-region": "East US" - } + {"model": "azure/gpt-35-turbo", "api_base": "https://my-endpoint-canada-berri992.openai.azure.com/"} ], - "unhealthy_endpoints": [], - "healthy_count": 1, - "unhealthy_count": 0 + "unhealthy_endpoints": [ + {"model": "azure/gpt-35-turbo", "api_base": "https://openai-france-1234.openai.azure.com/"} + ] } ``` -### Realtime Models - -To run realtime health checks, specify the mode as "realtime" in your config for the relevant model. - -```yaml -model_list: - - model_name: openai/gpt-4o-realtime-audio - litellm_params: - model: openai/gpt-4o-realtime-audio - api_key: os.environ/OPENAI_API_KEY - model_info: - mode: realtime -``` - -### OCR Models - -To run OCR health checks, specify the mode as "ocr" in your config for the relevant model. - -```yaml -model_list: - - model_name: mistral/mistral-ocr-latest - litellm_params: - model: mistral/mistral-ocr-latest - api_key: os.environ/MISTRAL_API_KEY - model_info: - mode: ocr -``` - -### Wildcard Routes +To check a single model, pass `?model=` or `?model_id=`; you can find a model's id from `GET /v1/model/info`. -For wildcard routes, you can specify a `health_check_model` in your config.yaml. This model will be used for health checks for that wildcard route. +## Background health checks -In this example, when running a health check for `openai/*`, the health check will make a `/chat/completions` request to `openai/gpt-4o-mini`. - -```yaml -model_list: - - model_name: openai/* - litellm_params: - model: openai/* - api_key: os.environ/OPENAI_API_KEY - model_info: - health_check_model: openai/gpt-4o-mini - - model_name: anthropic/* - litellm_params: - model: anthropic/* - api_key: os.environ/ANTHROPIC_API_KEY - model_info: - health_check_model: anthropic/claude-3-5-sonnet-20240620 -``` - -## Background Health Checks - -You can enable model health checks being run in the background, to prevent each model from being queried too frequently via `/health`. - -:::info - -**This makes an LLM API call to each model to check if it is healthy.** - -::: - -Here's how to use it: -1. in the config.yaml add: -``` -general_settings: - background_health_checks: True # enable background health checks - health_check_interval: 300 # frequency of background health checks -``` - -2. Start server -``` -$ litellm /path/to/config.yaml -``` - -3. Query health endpoint: -``` - curl --location 'http://0.0.0.0:4000/health' -``` - -### Disable Background Health Checks For Specific Models - -Use this if you want to disable background health checks for specific models. - -If `background_health_checks` is enabled you can skip individual models by -setting `disable_background_health_check: true` in the model's `model_info`. - -```yaml -model_list: - - model_name: openai/gpt-4o - litellm_params: - model: openai/gpt-4o - api_key: os.environ/OPENAI_API_KEY - model_info: - disable_background_health_check: true -``` - -### Skip the same models on `GET /health` - -By default, `disable_background_health_check: true` only skips those deployments in the **background** health loop. On-demand `GET /health` still probes them unless you enable this global flag: +By default `/health` probes every model on each call. To avoid querying models too frequently, run the checks in the background and have `/health` serve the last cached result. Configure this in `general_settings`: ```yaml general_settings: - health_check_skip_disabled_background_models: true -``` - -When `true`, deployments with `model_info.disable_background_health_check: true` are omitted from on-demand `GET /health` (including `?model=` / `?model_id=`) and from health-check runs that honor `general_settings` (including Redis-backed shared health checks). - -### Hide details - -The health check response contains details like endpoint URLs, error messages, -and other LiteLLM params. While this is useful for debugging, it can be -problematic when exposing the proxy server to a broad audience. - -You can hide these details by setting the `health_check_details` setting to `False`. - -```yaml -general_settings: - health_check_details: False -``` - -## Health Check Driven Routing - -Route traffic away from unhealthy deployments proactively — before user requests hit them. Supports per-error-type failure thresholds, transient error suppression, and automatic safety nets. - -See the full guide: [Health Check Driven Routing](./health_check_routing.md) - -## Health Check Timeout - -The health check timeout is set in `litellm/constants.py` and defaults to 60 seconds. - -This can be overridden in the config.yaml by setting `health_check_timeout` in the model_info section. - -```yaml -model_list: - - model_name: openai/gpt-4o - litellm_params: - model: openai/gpt-4o - api_key: os.environ/OPENAI_API_KEY - model_info: - health_check_timeout: 10 # 👈 OVERRIDE HEALTH CHECK TIMEOUT + background_health_checks: true # run checks in the background + health_check_interval: 300 # seconds between runs (default 300) + health_check_details: true # include endpoint URLs and errors in the response (default true) ``` -## Health Check Max Tokens - -By default, health checks use `max_tokens=5` to balance reliability with low cost and latency. For wildcard models, the default is `max_tokens=10`. +Set `health_check_details: false` to strip endpoint URLs, error messages, and other params from the response when the proxy is exposed to a broad audience. -You can override this per-model by setting `health_check_max_tokens` in the `model_info` section of your config.yaml. +To exclude a model from the background loop, set `disable_background_health_check: true` in its `model_info`. That only skips the background loop; an on-demand `GET /health` still probes it unless you also set `general_settings.health_check_skip_disabled_background_models: true`, which omits those deployments from on-demand and shared health checks as well. ```yaml model_list: @@ -360,169 +79,69 @@ model_list: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: - health_check_max_tokens: 5 # 👈 OVERRIDE HEALTH CHECK MAX TOKENS -``` - -### Reasoning vs non-reasoning defaults - -Reasoning models (per `supports_reasoning` in the model map) often need a higher health-check `max_tokens` because providers count reasoning tokens toward the completion budget. You can set **separate** limits without listing every model: - -**Per deployment (`model_info`)** — used when `health_check_max_tokens` is not set. Ignored for wildcard routes (`*` in `litellm_params.model`, i.e. the deployment model string; not `health_check_model`). - -```yaml -model_list: - - model_name: openai-stack - litellm_params: - model: openai/gpt-5-nano - api_key: os.environ/OPENAI_API_KEY - model_info: - health_check_max_tokens_reasoning: 128 - health_check_max_tokens_non_reasoning: 1 + disable_background_health_check: true ``` -**Global (environment)**: +For coordinating checks across multiple pods so expensive models are not probed once per pod, see [Shared Health Check State](./shared_health_check.md). -- `BACKGROUND_HEALTH_CHECK_MAX_TOKENS_REASONING` — for non-wildcard reasoning models, this value takes precedence when set -- `BACKGROUND_HEALTH_CHECK_MAX_TOKENS` — global fallback for all models (including wildcard routes) +## Model modes -If neither is set, non-wildcard models default to `5` and wildcard routes omit `max_tokens`. +The health check picks the operation to test from the model's `model_info.mode`. Set it so the probe uses the right API surface; if you leave it unset, LiteLLM auto-detects from the model's capabilities and falls back to a chat completion. -## Health check reasoning effort +| `mode` | Health check calls | +|--------|--------------------| +| `chat` (default) | `/chat/completions` | +| `completion` | `/completions` | +| `embedding` | `/embeddings` | +| `image_generation` | image generation | +| `audio_transcription` | audio transcription | +| `audio_speech` | text to speech (requires `health_check_voice`) | +| `rerank` | rerank | +| `batch` | batch (Azure only) | +| `realtime` | realtime session | +| `ocr` | OCR | +| `video_generation` | video generation | -For reasoning models (e.g. GPT-5, o-series), you can set **only for the health-check request** how much reasoning to use via `health_check_reasoning_effort` in `model_info`. This is forwarded as `reasoning_effort` on the underlying completion call so you can use a minimal level (for example `none` or `minimal`) to reduce latency and cost during probes. - -Applies when `mode` is unset (chat), or explicitly `chat`, `completion`, `batch`, or `responses`. It is not applied for `embedding`, `audio_*`, `rerank`, etc. +For a wildcard route (`*` in `litellm_params.model`), set `health_check_model` to the concrete model the probe should call. With `mode` unset on a wildcard route, `max_tokens` is left unset on the probe request. ```yaml model_list: - - model_name: openai/gpt-5-nano + - model_name: azure-embedding-model litellm_params: - model: openai/gpt-5-nano - api_key: os.environ/OPENAI_API_KEY + model: azure/azure-embedding-model + api_base: os.environ/AZURE_API_BASE + api_key: os.environ/AZURE_API_KEY + api_version: "2023-07-01-preview" model_info: - health_check_reasoning_effort: none # options depend on provider/model map + mode: embedding ``` -### Checking which `reasoning_effort` values your model supports +## Health check tuning reference -LiteLLM reads per-model flags from [`model_prices_and_context_window.json`](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json). For reasoning effort, entries may include `supports_none_reasoning_effort`, `supports_minimal_reasoning_effort`, `supports_low_reasoning_effort`, `supports_xhigh_reasoning_effort`, `supports_max_reasoning_effort`, and similar keys. When a key is **`true`**, LiteLLM treats that level as supported for that model. +Set these under a model's `model_info` unless noted otherwise. They control how the probe request is shaped. -Call **`litellm.get_model_info()`** with the **same model string** you use under `litellm_params.model` (including a provider prefix such as `azure/` when you use one), then inspect the returned `supports_*_reasoning_effort` fields: +| Key | Default | Purpose | +|-----|---------|---------| +| `health_check_timeout` | 60s | Per-model timeout for the probe | +| `health_check_max_tokens` | 16 (unset for wildcard routes) | `max_tokens` on the probe request | +| `health_check_max_tokens_reasoning` | unset | `max_tokens` for reasoning models when `health_check_max_tokens` is not set | +| `health_check_max_tokens_non_reasoning` | unset | `max_tokens` for non-reasoning models when `health_check_max_tokens` is not set | +| `health_check_reasoning_effort` | unset | `reasoning_effort` on the probe (chat, completion, batch, responses modes only) | +| `health_check_voice` | `alloy` | Voice for `audio_speech` probes | +| `health_check_model` | unset | Concrete model a wildcard route probes | +| `disable_background_health_check` | false | Skip this model in the background loop | -```python -import litellm - -info = litellm.get_model_info("azure/gpt-5.4-mini") -for name in sorted(dir(info)): - if "reasoning_effort" in name and not name.startswith("_"): - print(name, getattr(info, name)) -``` - -If the model is not present in the LiteLLM model map, `get_model_info` may raise. In that case add or fix the entry in the JSON, or confirm allowed values from your provider’s API documentation (Azure OpenAI, OpenAI, Anthropic, etc.)—provider docs are the final authority when the map has not caught up to a new SKU. - -## `/health/readiness` - -Unprotected endpoint for checking if proxy is ready to accept requests - -Example Request: - -```bash -curl http://0.0.0.0:4000/health/readiness -``` - -Example Response: - -```json -{ - "status": "connected", - "db": "connected", - "cache": null, - "litellm_version": "1.40.21", - "success_callbacks": [ - "langfuse", - "_PROXY_track_cost_callback", - "response_taking_too_long_callback", - "_PROXY_MaxParallelRequestsHandler", - "_PROXY_MaxBudgetLimiter", - "_PROXY_CacheControlCheck", - "ServiceLogging" - ], - "last_updated": "2024-07-10T18:59:10.616968" -} -``` +Reasoning models often need a higher probe `max_tokens` because providers count reasoning tokens toward the completion budget; the separate reasoning and non-reasoning keys let you raise it without listing every model. Three environment variables set global defaults: `DEFAULT_HEALTH_CHECK_PROMPT` overrides the default probe prompt (`"test from litellm"`), `BACKGROUND_HEALTH_CHECK_MAX_TOKENS` is the global `max_tokens` fallback, and `BACKGROUND_HEALTH_CHECK_MAX_TOKENS_REASONING` takes precedence for non-wildcard reasoning models. -If the proxy is not connected to a database, then the `"db"` field will be `"Not -connected"` instead of `"connected"` and the `"last_updated"` field will not be present. +To route traffic away from deployments that fail health checks, see [Health Check Driven Routing](./health_check_routing.md). -## `/health/liveliness` +## Other health endpoints -Unprotected endpoint for checking if proxy is alive - - -Example Request: - -``` -curl -X 'GET' \ - 'http://0.0.0.0:4000/health/liveliness' \ - -H 'accept: application/json' -``` - -Example Response: - -```json -"I'm alive!" -``` - -## `/health/services` - -Use this admin-only endpoint to check if a connected service (datadog/slack/langfuse/etc.) is healthy. - -```bash -curl -L -X GET 'http://0.0.0.0:4000/health/services?service=datadog' -H 'Authorization: Bearer sk-1234' -``` - -[**API Reference**](https://litellm-api.up.railway.app/#/health/health_services_endpoint_health_services_get) - - -## Advanced - Call specific models - -To check health of specific models, here's how to call them: - -### 1. Get model id via `/model/info` - -```bash -curl -X GET 'http://0.0.0.0:4000/v1/model/info' \ ---header 'Authorization: Bearer sk-1234' \ -``` - -**Expected Response** - -```bash -{ - "model_name": "bedrock-anthropic-claude-3", - "litellm_params": { - "model": "anthropic.claude-3-sonnet-20240229-v1:0" - }, - "model_info": { - "id": "634b87c444..", # 👈 UNIQUE MODEL ID -} -``` - -### 2. Call specific model via `/chat/completions` - -```bash -curl -X POST 'http://localhost:4000/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-1234' \ --D '{ - "model": "634b87c444.." # 👈 UNIQUE MODEL ID - "messages": [ - { - "role": "user", - "content": "ping" - } - ], -} -' -``` +All of these require a valid key unless noted. +- `GET /health/services?service=` tests a configured alerting or logging service (datadog, slack, langfuse, and so on); accepts any valid key +- `GET /health/readiness/details` returns the authenticated readiness diagnostics (db, cache, callbacks, version) +- `GET /health/history` returns past health check results +- `GET /health/latest` returns the most recent health check result +- `GET /health/backlog` returns the number of in-flight requests on the worker +- `GET /health/drain` starts a graceful drain for Kubernetes `preStop` hooks; disabled by default (404) unless `general_settings.enable_drain_endpoint: true`, and gated by the `X-Drain-Token` header when `DRAIN_ENDPOINT_TOKEN` is set diff --git a/docs/proxy/high_availability_control_plane.md b/docs/proxy/high_availability_control_plane.md index 6d6278c48..1eee85eb7 100644 --- a/docs/proxy/high_availability_control_plane.md +++ b/docs/proxy/high_availability_control_plane.md @@ -16,33 +16,17 @@ This is an Enterprise feature. ::: -## Why This Architecture? +## When to use this -In the [standard multi-region setup](./multi_region.md), all instances share a single database and master key. This works, but introduces a shared dependency. If the database goes down, every instance is affected. It also means one license covers every region; with the independent workers on this page, each worker is its own deployment with its own license. +Each worker is a fully independent LiteLLM proxy with its own database, Redis, and master key. Keys, teams, and budgets are local to a worker and never span workers; a single control plane UI manages all of them from one place. -The **High Availability Control Plane** takes a different approach: - -| | Shared Database (Standard) | High Availability Control Plane | -|---|---|---| -| **Database** | Single shared DB for all instances | Each instance has its own DB | -| **Redis** | Shared Redis | Each instance has its own Redis | -| **Master Key** | Same key across all instances | Each instance has its own key | -| **Failure isolation** | DB outage affects all instances | Failure is isolated to one instance | -| **User management** | Centralized, one user table | Independent, each worker manages its own users | -| **UI** | One UI per admin instance | Single control plane UI manages all workers | - -### Benefits - -- **True high availability**: no shared infrastructure means no single point of failure -- **Blast radius containment**: a misconfiguration or outage on one worker doesn't affect others -- **Regional isolation**: workers can run in different regions with data residency requirements -- **Simpler operations**: each worker is a self-contained LiteLLM deployment +Pick this over the shared-database [Multi-Region Deployment](./multi_region.md) topology when blast-radius isolation matters more than global consistency. A database outage on one worker cannot affect another, but a key created on one worker will not authenticate on another. Multi-Region covers the full tradeoff and the licensing table, where this page appears as a row. ## Architecture -The **control plane** is a LiteLLM instance that serves the admin UI and knows about all the workers. It is **not a router**; it does not proxy or route any LLM requests. It exists purely so admins can switch between workers and manage them from a single UI. +The **control plane** is a LiteLLM instance that serves the admin UI and knows about all the workers. It is not a router; it does not proxy or route any LLM requests. It exists purely so admins can switch between workers and manage them from a single UI. Each **worker** is a fully independent LiteLLM proxy that handles LLM requests for its region or team. Workers have their own database, Redis, users, keys, teams, and budgets. No infrastructure is shared between workers. @@ -50,7 +34,7 @@ Each **worker** is a fully independent LiteLLM proxy that handles LLM requests f ### 1. Control Plane Configuration -The control plane needs a `worker_registry` that lists all worker instances. +The control plane needs a `worker_registry` that lists all worker instances. Each entry requires `worker_id`, `name`, and `url`. ```yaml title="cp_config.yaml" model_list: [] @@ -76,7 +60,7 @@ litellm --config cp_config.yaml --port 4000 ### 2. Worker Configuration -Each worker needs `control_plane_url` in its `general_settings` to enable cross-origin authentication from the control plane UI. +Each worker needs `control_plane_url` in its `general_settings`. This enables the `/v3/login` and `/v3/login/exchange` endpoints on the worker so the control plane UI can authenticate against it cross-origin. `PROXY_BASE_URL` must also be set for each worker so that SSO callback redirects resolve correctly. @@ -119,34 +103,27 @@ PROXY_BASE_URL=http://localhost:4002 litellm --config worker_b_config.yaml --por Each worker must have its own `master_key` and `database_url`. The whole point of this architecture is that workers are independent. ::: +:::info +If a worker runs more than one instance behind a load balancer, configure Redis on that worker (the `cache` section of its config); the login code issued by `/v3/login` is stored server-side, so without shared Redis the exchange can land on a different instance and fail with a 401. +::: + ### 3. SSO Configuration (Optional) -SSO is configured on the **control plane** instance the same way as a standard LiteLLM proxy. See the [SSO setup guide](./admin_ui_sso.md) for full instructions. +SSO is configured on the control plane instance the same way as a standard LiteLLM proxy. See the [SSO setup guide](./admin_ui_sso.md) for full instructions. -If using SSO, make sure to register each worker URL and the control plane URL as allowed callback URLs in your SSO provider's dashboard. +If using SSO, register each worker URL and the control plane URL as allowed callback URLs in your SSO provider's dashboard. ## How It Works ### Login Flow -1. User visits the control plane UI (`http://localhost:4000/ui`) -2. The login page shows a **worker selector** dropdown listing all registered workers -3. User selects a worker (e.g. "Worker A") and logs in with username/password or SSO -4. The UI authenticates against the **selected worker** using the `/v3/login` endpoint -5. On success, the UI stores the worker's JWT and points all subsequent API calls at the worker -6. The user can now manage keys, teams, models, and budgets on that worker, all from the control plane UI - -### Switching Workers +On load, the UI reads the control plane's `/.well-known/litellm-ui-config` endpoint, which reports `is_control_plane: true` along with the registered workers (their IDs, names, and URLs). Because it is a control plane, the login page shows a worker selector dropdown. -Once logged in, users can switch workers from the **navbar dropdown** without leaving the UI. Switching redirects back to the login page to authenticate against the new worker. +The user picks a worker and logs in with username/password or SSO. The UI authenticates against the selected worker by calling its `/v3/login` endpoint, which returns a single-use code; the UI redeems that code at the worker's `/v3/login/exchange` for a JWT. From then on it points all subsequent API calls at that worker, so keys, teams, models, and budgets are managed on the selected worker from the control plane UI. -### Discovery - -The control plane exposes a `/.well-known/litellm-ui-config` endpoint that the UI reads on load. This endpoint returns: -- `is_control_plane: true` -- The list of workers with their IDs, names, and URLs +### Switching Workers -This is how the login page knows to show the worker selector. +Once logged in, users can switch workers from the navbar dropdown without leaving the UI. Switching redirects back to the login page to authenticate against the new worker. ## Local Testing @@ -174,17 +151,15 @@ Then open `http://localhost:4000/ui`. You should see the worker selector on the | `worker_registry` | Top-level config | List of worker instances | | `worker_registry[].worker_id` | Required | Unique identifier for the worker | | `worker_registry[].name` | Required | Display name shown in the UI | -| `worker_registry[].url` | Required | Full URL of the worker instance | +| `worker_registry[].url` | Required | Full URL of the worker instance (must start with `http://` or `https://`) | ### Worker Settings | Field | Location | Description | |---|---|---| -| `general_settings.control_plane_url` | Required | URL of the control plane instance. Enables `/v3/login` and `/v3/login/exchange` endpoints on this worker. | +| `general_settings.control_plane_url` | Required | URL of the control plane instance. Enables the `/v3/login` and `/v3/login/exchange` endpoints on this worker. | | `PROXY_BASE_URL` | Environment variable | The worker's own external URL. Required for SSO callback redirects. | ## Related Documentation -- [Multi-Region Deployment](./multi_region.md) - shared-database architecture, licensing across regions -- [SSO Setup](./admin_ui_sso.md) - configuring SSO for the admin UI -- [Production Deployment](./prod.md) - production best practices +For the shared-database alternative and cross-region licensing, see [Multi-Region Deployment](./multi_region.md); for authentication, the [SSO setup guide](./admin_ui_sso.md); and for hardening, the [production deployment guide](./prod.md) diff --git a/docs/proxy/image_handling.md b/docs/proxy/image_handling.md deleted file mode 100644 index 300ab0bc3..000000000 --- a/docs/proxy/image_handling.md +++ /dev/null @@ -1,21 +0,0 @@ -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Image URL Handling - - - -Some LLM API's don't support url's for images, but do support base-64 strings. - -For those, LiteLLM will: - -1. Detect a URL being passed -2. Check if the LLM API supports a URL -3. Else, will download the base64 -4. Send the provider a base64 string. - - -LiteLLM also caches this result, in-memory to reduce latency for subsequent calls. - -The limit for an in-memory cache is 1MB. \ No newline at end of file diff --git a/docs/proxy/key_auth_arch.md b/docs/proxy/key_auth_arch.md index 2b544fe0a..ed2cebde3 100644 --- a/docs/proxy/key_auth_arch.md +++ b/docs/proxy/key_auth_arch.md @@ -22,18 +22,18 @@ These strings are reserved as enum values in `litellm.proxy._types.SpecialModelN | Sentinel | Where it belongs | Effect | |---|---|---| | `all-proxy-models` | Key, team, or user `models` list | Grants every model on the proxy. On a team, treated the same as an empty `models` list. On a user, grants direct access to every non-team deployment. | -| `all-team-models` | Key `models` list only | Inherits the parent team's `models` at request time. If the key has no `team_id` the sentinel resolves to itself, matches nothing, and access is denied rather than silently opening up. | +| `all-team-models` | Key `models` list only | Inherits the parent team's `models` at request time. If the key has no `team_id`, the check resolves to an empty restriction list, which means the key is unrestricted (all proxy models); attach a `team_id` or use an explicit model list when the key must stay constrained. | | `no-default-models` | User `models` list only | Hard denial on the user path; forces the user to route requests through a team. Set via `default_internal_user_params.models` so SSO signups cannot mint standalone keys with proxy-wide access. | -`all-team-models` is the sentinel most often confused with an empty list. Empty means "all models"; `all-team-models` means "whatever the team says, and nothing if there is no team". +`all-team-models` is the sentinel most often confused with an empty list. Empty means "all models"; `all-team-models` means "whatever the team says", and with no team attached it also resolves to all models rather than to a denial. ## Resolution: with team_id vs without Two rules cover every case. A standalone key (no `team_id`) is authorized purely against its own `models` list. A team-attached key must pass both its own list and a second check against `team.models`; the intersection is what the caller can actually reach, so a key holding `["gpt-4"]` under a team holding `["azure-gpt-3.5"]` cannot call anything. -The failure surface tells you which step rejected. The key step raises `Invalid model for key`. The team step raises `Invalid model for team : . Valid models for team are: [...]` (see [Restrict models by team_id](./model_access.md#restrict-models-by-team_id)). +Both steps reject with the same message shape: `{object_type} not allowed to access model. This {object_type} can only access models=[...]. Tried to access `, where `object_type` is `key`, `team`, `user`, or `org`, so the prefix tells you which step rejected. A separate team-config validation path raises `Invalid model for team : . Valid models for team are: [...]` (see [Restrict models by team_id](./model_access.md#restrict-models-by-team_id)). -The sentinels change the shape of these two checks: `all-proxy-models` on a team makes the team step trivially pass but the key still has to match; `all-team-models` on a key skips the key step and defers to the team step (and denies if no team is attached). +The sentinels change the shape of these two checks: `all-proxy-models` on a team makes the team step trivially pass but the key still has to match; `all-team-models` on a key skips the key step and defers to the team step (and resolves to the full proxy list when no team is attached). ## Access groups and wildcards diff --git a/docs/proxy/master_key_rotations.md b/docs/proxy/master_key_rotations.md index 171367986..0edc4af00 100644 --- a/docs/proxy/master_key_rotations.md +++ b/docs/proxy/master_key_rotations.md @@ -1,12 +1,26 @@ -# Rotating Master Key +# Rotating the Master Key -Here are our recommended steps for rotating your master key. +The master key is the proxy's admin credential; it authenticates admin API calls and logs you into the Admin UI. In some deployments it is also the key used to encrypt credentials at rest in the database. How you rotate it depends on which of those roles it plays, and getting this wrong can leave your stored credentials unreadable, so read the case that matches your setup before running anything. +:::warning -**1. Backup your DB** -In case of any errors during the encryption/de-encryption process, this will allow you to revert back to current state without issues. +If you set a [salt key](./prod.md#set-the-salt-key), the proxy decrypts stored credentials with the salt key, not the master key. Do not rotate the master key with `POST /key/regenerate` and `new_master_key` in that setup. That flow re-encrypts everything under the new master key, but the running proxy keeps decrypting with the salt key, so every stored credential becomes unreadable and the deployment can be bricked. Follow the salt-key section below instead. -**2. Call `/key/regenerate` with the new master key** +::: + +Back up your database before either flow. Model re-encryption deletes and recreates rows rather than updating them in place, and credential re-encryption skips any row that fails, so a partial failure can strand data. A backup lets you revert cleanly. + +Virtual keys are stored hashed, not encrypted, so they keep working after either rotation. Only models stored in the database (`store_model_in_db`) are re-encrypted by the regenerate flow; models defined in your config file are not affected. This is available on the open-source build; master-key rotation is not gated behind the enterprise tier. There is no Admin UI flow for this; rotation is API-only by design. + +## If you use a salt key (recommended setup) + +When `LITELLM_SALT_KEY` is set, the salt key encrypts and decrypts your stored credentials, and the master key is only an auth credential. Rotating it does not touch anything encrypted at rest, so there is nothing to re-encrypt. + +Generate a new master key value, update wherever the secret lives (the `LITELLM_MASTER_KEY` environment variable, or `general_settings.master_key` in your config), and restart every proxy instance so they pick up the new value. Do not call `POST /key/regenerate` with `new_master_key` here; that would re-encrypt your credentials under a key the proxy never uses to decrypt. + +## If the master key is your encryption key + +When no salt key is set, the master key doubles as the at-rest encryption key, so rotating it requires re-encrypting stored data. Call `POST /key/regenerate` with the current master key and the new one. ```bash curl -L -X POST 'http://localhost:4000/key/regenerate' \ @@ -18,36 +32,21 @@ curl -L -X POST 'http://localhost:4000/key/regenerate' \ }' ``` -This will re-encrypt any models in your Proxy_ModelTable with the new master key. - -Expect to start seeing decryption errors in logs, as your old master key is no longer able to decrypt the new values. +This re-encrypts stored models, the `environment_variables` saved in the config table, the credentials table, and the MCP server, user, and per-user environment credential tables under the new master key. It returns the new key: -```bash - raise Exception("Unable to decrypt value={}".format(v)) -Exception: Unable to decrypt value= +```json +{ + "key": "sk-PIp1h0RekR", + "token": "sk-PIp1h0RekR", + "key_name": "sk-PIp1h0RekR", + "expires": null +} ``` -**3. Update LITELLM_MASTER_KEY** - -In your environment variables update the value of LITELLM_MASTER_KEY to the new_master_key from Step 2. +The running process does not adopt the new key on its own, so finish with the steps below before it can decrypt what it just re-encrypted. -This ensures the key used for decryption from db is the new key. +## After rotating -**4. Test it** +Update the master key everywhere the old value lived: the `LITELLM_MASTER_KEY` environment variable and your secret manager, and `general_settings.master_key` in your config if you set it there. If both are present, `general_settings.master_key` takes precedence over the environment variable, so make sure it holds the new value. -Make a test request to a model stored on proxy with a litellm key (new master key or virtual key) and see if it works - -```bash - curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer sk-1234' \ --d '{ - "model": "gpt-4o-mini", # 👈 REPLACE with 'public model name' for any db-model - "messages": [ - { - "content": "Hey, how's it going", - "role": "user" - } - ], -}' -``` \ No newline at end of file +Restart every proxy instance so they load the new key. Then verify by logging into the Admin UI with the new master key; if the UI loads and your stored models and credentials resolve, the rotation is complete. diff --git a/docs/proxy/microservices_helm.md b/docs/proxy/microservices_helm.md deleted file mode 100644 index 68f4905a3..000000000 --- a/docs/proxy/microservices_helm.md +++ /dev/null @@ -1,223 +0,0 @@ -# Microservices Helm - -Run LiteLLM as **three independently scalable services** — a `gateway` for LLM -traffic, a `backend` for the management/UI API, and a static `ui` — plus a -one-shot `migrations` Job. - -![Reference architecture: LiteLLM on Amazon EKS — gateway, backend, and ui behind one ALB Ingress, with Aurora Postgres, ElastiCache Redis, S3/CloudWatch, and Secrets Manager](/img/blog/componentized_deployment/eks_topline.png) - -For the motivation behind splitting the proxy (why a slow control-plane query -can otherwise recycle the pods serving inference), see the blog post -[*One Slow Dashboard Query Shouldn't Take Down Your LLM Traffic*](/blog/componentized-deployment). - -## Components - -| Component | Port | Surface | -|---|---|---| -| **gateway** | 4000 | LLM data plane — `/chat/completions`, `/v1/messages`, embeddings, audio, batches, passthroughs, `/health`, `/metrics` | -| **backend** | 4001 | Management/UI API — keys, users, teams, orgs, SSO, audit logs, **spend & usage analytics** | -| **ui** | 3000 | Next.js dashboard, static export served by nginx | -| **migrations** | Job | `prisma migrate deploy`, run once as a pre-install/pre-upgrade Helm hook | - -Each component is its own Deployment with its own Service, liveness/readiness -probes, and HorizontalPodAutoscaler — a failure or load spike on one is -contained to that surface. - -## Prerequisites - -- A Kubernetes cluster and Helm 3.8+ (OCI registry support). -- An external Postgres database (writer endpoint; optional read replica). -- Optional: Redis for caching / rate limiting. - -## Install - -### Step 1 — Create the Secrets - -Sensitive values are passed by Secret reference only — create them first: - -```bash -kubectl create namespace litellm - -kubectl -n litellm create secret generic litellm-master-key-secret \ - --from-literal=master-key="sk-..." - -kubectl -n litellm create secret generic litellm-writer-secret \ - --from-literal=username=litellm --from-literal=password="..." - -# Only if you use a read replica (see "Separate read and write databases") -kubectl -n litellm create secret generic litellm-reader-secret \ - --from-literal=username=litellm --from-literal=password="..." -``` - -### Step 2 — Minimal `values.yaml` - -```yaml -masterKey: - secretName: litellm-master-key-secret - secretKey: master-key - -database: - writer: - host: litellm-pg-rw.litellm.svc - port: 5432 - dbname: litellm - passwordSecret: - name: litellm-writer-secret - usernameKey: username - passwordKey: password - -# Optional: front all three services behind one host -ingress: - enabled: true - className: alb - host: aigateway.example.com -``` - -### Step 3 — Install from the OCI registry - -The chart is published to GitHub Container Registry: -[`ghcr.io/berriai/litellm/chart/litellm`](https://github.com/BerriAI/litellm/pkgs/container/litellm%2Fchart%2Flitellm). - -```bash -helm upgrade --install litellm \ - oci://ghcr.io/berriai/litellm/chart/litellm \ - --version 1.86.0-dev \ - -n litellm \ - -f values.yaml -``` - -The chart runs `prisma migrate deploy` as a pre-install/pre-upgrade hook Job, -then brings up the `gateway`, `backend`, and `ui` Deployments. With -`ingress.enabled=true` a single host fronts all three: data-plane prefixes → -`gateway`, UI assets → `ui`, catch-all → `backend`. - -## Configuration - -### Separate read and write databases - -Routing heavy analytics reads off the writer is just the `database.reader` -block. Set `reader.host` to enable it; leave it empty and every query goes to -the writer. Unset reader fields fall back to the writer's values. - -```yaml -database: - # Writer — all writes (spend logs, tokens, config) land here - writer: - host: litellm-pg-rw.litellm.svc - port: 5432 - dbname: litellm - passwordSecret: - name: litellm-writer-secret - usernameKey: username - passwordKey: password - - # Reader — read-heavy ops (find_*, count, group_by, raw reads) - reader: - host: litellm-pg-ro.litellm.svc - port: 5432 - dbname: litellm - passwordSecret: - name: litellm-reader-secret - usernameKey: username - passwordKey: password -``` - -The chart assembles `DATABASE_URL` and `DATABASE_URL_READ_REPLICA` from these -pieces before the proxy starts. See -[Database Read Replica](/docs/proxy/db_read_replica) for how reads are routed. - -**RDS / Aurora IAM auth** — set `useIAMAuth: true` on `database.writer` (and -optionally `database.reader`) to mint short-lived IAM tokens instead of -referencing a password Secret: - -```yaml -database: - writer: - host: litellm.cluster-xxxx.us-east-1.rds.amazonaws.com - dbname: litellm - useIAMAuth: true - reader: - host: litellm.cluster-ro-xxxx.us-east-1.rds.amazonaws.com - useIAMAuth: true # requires database.writer.useIAMAuth: true -serviceAccount: - create: true - name: litellm - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam:::role/litellm-db -``` - -### Redis - -Leave `redis.host` empty to disable. Set `redis.cluster: true` for Redis -Cluster mode (e.g. ElastiCache Cluster) — the chart emits `REDIS_CLUSTER_NODES` -from `host`/`port` as the seed and the client discovers the rest from -`CLUSTER SLOTS`. - -```yaml -redis: - cluster: true - host: litellm-redis.litellm.svc - port: 6379 - passwordSecret: - name: litellm-redis-secret # leave empty for auth-less Redis - passwordKey: password -``` - -### Per-component scaling and probes - -Each of `gateway`, `backend`, `ui` accepts `image`, `resources`, -`livenessProbe`, `readinessProbe`, `hpa`, `extraEnv`, `envConfigMaps`, -`envSecrets`, `logLevel`, `nodeSelector`, `tolerations`, and `affinity`. -`gateway` additionally takes `numWorkers` (uvicorn workers per pod, default -`1`) and `config.proxy_config` (rendered into a ConfigMap and mounted at -`/app/config/config.yaml`). - -Defaults size each surface for its own load profile: - -```yaml -gateway: - numWorkers: 1 - hpa: { enabled: true, minReplicas: 1, maxReplicas: 10, - targetCPUUtilizationPercentage: 70, targetMemoryUtilizationPercentage: 80 } - -backend: - hpa: { enabled: true, minReplicas: 1, maxReplicas: 4, - targetCPUUtilizationPercentage: 70 } - -ui: - hpa: { enabled: false, minReplicas: 1, maxReplicas: 3 } -``` - -### Migrations Job - -Enabled by default. Runs `prisma migrate deploy` against the writer database as -a Helm pre-install/pre-upgrade hook, using a dedicated `litellm-migrations` -image. Disable it if your pipeline runs migrations out-of-band: - -```yaml -migrationJob: - enabled: true - backoffLimit: 4 - ttlSecondsAfterFinished: 120 - # The v2 resolver is used by default. To opt back into v1: - extraEnv: - - name: USE_V2_MIGRATION_RESOLVER - value: "false" -``` - -### Ingress - -Enable to wire the three Services behind one L7 entrypoint (required when -serving the static UI over the network): - -```yaml -ingress: - enabled: true - className: alb - host: aigateway.example.com - annotations: {} - tls: [] -``` - -The chart routes UI paths to the `ui` pods, data-plane prefixes to `gateway`, -and the catch-all (`/key/*`, `/user/*`, `/spend/*`, …) to `backend`. diff --git a/docs/proxy/model_management.md b/docs/proxy/model_management.md index 1faaf697d..254be8d38 100644 --- a/docs/proxy/model_management.md +++ b/docs/proxy/model_management.md @@ -1,182 +1,73 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; # Model Management -Add new models + Get model info without restarting proxy. -## In Config.yaml +When `STORE_MODEL_IN_DB` is on, your models live in the database rather than in a static `config.yaml`. That means day-2 changes happen right in the Admin UI: adding a model, editing pricing, rotating a provider key, or retiring a deployment, all with no config edits and no proxy restart. -```yaml -model_list: - - model_name: text-davinci-003 - litellm_params: - model: "text-completion-openai/text-davinci-003" - model_info: - metadata: "here's additional metadata on the model" # returned via GET /model/info -``` +This page covers those ongoing operations. If you are adding your very first model, start with the [Docker Quickstart](./docker_quick_start.md), which walks you through startup, provider connection, and your first request. Come back here once the gateway is running and you want to manage the models you have. -## Get Model Information - `/model/info` +## The model list -Retrieve detailed information about each model listed in the `/model/info` endpoint, including descriptions from the `config.yaml` file, and additional model info (e.g. max tokens, cost per input token, etc.) pulled from the model_info you set and the [litellm model cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json). Sensitive details like API keys are excluded for security purposes. +Go to **Models + Endpoints** and open the **All Models** tab to see every model the gateway currently serves. Each row shows the public model name, the underlying provider and litellm model, and the input and output cost per token that LiteLLM maps automatically from its [model cost map](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json). -:::tip Sync Model Data -Keep your model pricing data up to date by [syncing models from GitHub](sync_models_github.md). -::: +A badge on each model tells you where it came from: models added through the UI or API carry a database badge, while models loaded from `config.yaml` are marked as config. This distinction matters because config models cannot be edited from the UI (see [Database vs config.yaml models](#database-vs-configyaml-models) below). Use the search box and the provider filters to narrow a long list down to the models you care about. - - +All Models list in the Admin UI -```bash -curl -X GET "http://0.0.0.0:4000/model/info" \ - -H "accept: application/json" \ -``` - - +## Inspect and edit a model -## Add a New Model +Click a Model ID in the list to open its detail page. The **Overview** tab summarizes the model's settings and provider, and the **Raw JSON** tab shows the full stored definition, useful when you want to confirm exactly what the gateway is holding. -Add a new model to the proxy via the `/model/new` API, to add models without restarting the proxy. +Click **Edit Settings** to change the model in place. You can update the public model name that clients call, the litellm model name that requests are routed to, and the input and output cost per 1M tokens when you want to override the mapped pricing. Save, and the change takes effect immediately for new requests. - - - -```bash -curl -X POST "http://0.0.0.0:4000/model/new" \ - -H "accept: application/json" \ - -H "Content-Type: application/json" \ - -d '{ "model_name": "azure-gpt-turbo", "litellm_params": {"model": "azure/gpt-3.5-turbo", "api_key": "os.environ/AZURE_API_KEY", "api_base": "my-azure-api-base"} }' -``` - - - -```yaml -model_list: - - model_name: gpt-3.5-turbo ### RECEIVED MODEL NAME ### `openai.chat.completions.create(model="gpt-3.5-turbo",...)` - litellm_params: # all params accepted by litellm.completion() - https://github.com/BerriAI/litellm/blob/9b46ec05b02d36d6e4fb5c32321e51e7f56e4a6e/litellm/types/router.py#L297 - model: azure/gpt-turbo-small-eu ### MODEL NAME sent to `litellm.completion()` ### - api_base: https://my-endpoint-europe-berri-992.openai.azure.com/ - api_key: "os.environ/AZURE_API_KEY_EU" # does os.getenv("AZURE_API_KEY_EU") - rpm: 6 # [OPTIONAL] Rate limit for this deployment: in requests per minute (rpm) - model_info: - my_custom_key: my_custom_value # additional model metadata -``` - - - +Two more actions live on this page. **Test Connection** re-verifies the model against the provider using its stored credentials, so you can confirm a key still works or that a newly edited setting is valid before clients hit it. **Delete Model** removes the model from the gateway; for database models this deletes the stored definition outright. +Model detail page with Edit Settings, Test Connection, and Delete Model -### Model Parameters Structure +## Reusable provider credentials -When adding a new model, your JSON payload should conform to the following structure: +Most deployments have several models behind the same provider account. Rather than paste the same API key into every model, create a named credential once and reuse it. -- `model_name`: The name of the new model (required). -- `litellm_params`: A dictionary containing parameters specific to the Litellm setup (required). -- `model_info`: An optional dictionary to provide additional information about the model. +Open the **LLM Credentials** tab and click **Add Credential**. Pick your provider, enter the API key, and give the credential a name. The fields adapt to the provider you choose, so selecting Vertex AI, for example, gives you `Vertex Project`, `Vertex Location`, and `Vertex Credentials` instead of a single key field. -Here's an example of how to structure your `ModelParams`: +Add New Credential modal -```json -{ - "model_name": "my_awesome_model", - "litellm_params": { - "some_parameter": "some_value", - "another_parameter": "another_value" - }, - "model_info": { - "author": "Your Name", - "version": "1.0", - "description": "A brief description of the model." - } -} -``` ---- - -Keep in mind that as both endpoints are in [BETA], you may need to visit the associated GitHub issues linked in the API descriptions to check for updates or provide feedback: +Once saved, the credential is available wherever you add or edit a model. In the Add Model form, choose it from the **Existing Credentials** dropdown instead of typing a key. From a model's detail page you can also go the other way with the **Re-use Credentials** button, which turns the credentials of a model you already configured into a named credential for future models. Models attached to a named credential are tagged `Credential: ` in the Usage page, so you can filter spend by credential without any extra setup; see [Credential Usage Tracking](./credential_usage_tracking.md). -- Get Model Information: [Issue #933](https://github.com/BerriAI/litellm/issues/933) -- Add a New Model: [Issue #964](https://github.com/BerriAI/litellm/issues/964) +## Database vs config.yaml models -Feedback on the beta endpoints is valuable and helps improve the API for all users. +Storing models in the database is what makes UI-driven management possible. Turn it on by setting `STORE_MODEL_IN_DB="True"` as an environment variable, or `general_settings.store_model_in_db: true` in your config. You can also toggle it at runtime from the **Models + Endpoints** settings in the UI, which is handy for cloud deployments where editing the config means a full release; the UI value overrides the config value. +With it enabled, every model you add through the UI or the API persists in the database and survives restarts and additional proxy instances. Provider credentials for those models are encrypted at rest using `LITELLM_SALT_KEY` (falling back to `LITELLM_MASTER_KEY` if the salt key is not set); keep that value secret and never change it once models exist, since credentials encrypted with the old value cannot be decrypted with a new one. -## Add Additional Model Information +Database storage does not replace your `config.yaml`. Any models defined there keep working and show up alongside your database models. The one difference is that config models are owned by the file, so they cannot be edited or deleted from the UI; change them in the config and reload. For the config format itself, see [Config.yaml](./configs.md). -If you want the ability to add a display name, description, and labels for models, just use `model_info:` +## Automation (API) -```yaml -model_list: - - model_name: "gpt-4" - litellm_params: - model: "gpt-4" - api_key: "os.environ/OPENAI_API_KEY" - model_info: # 👈 KEY CHANGE - my_custom_key: "my_custom_value" -``` +The same operations are available over HTTP, which is what you want for CI/CD or scripting bulk changes. These endpoints require `store_model_in_db` to be enabled; with it off, `POST /model/new` fails because there is nowhere to persist the model. -### Usage - -1. Add additional information to model - -```yaml -model_list: - - model_name: "gpt-4" - litellm_params: - model: "gpt-4" - api_key: "os.environ/OPENAI_API_KEY" - model_info: # 👈 KEY CHANGE - my_custom_key: "my_custom_value" -``` - -2. Call with `/model/info` - -Use a key with access to the model `gpt-4`. +Add a model: ```bash -curl -L -X GET 'http://0.0.0.0:4000/v1/model/info' \ --H 'Authorization: Bearer LITELLM_KEY' \ +curl -X POST "http://0.0.0.0:4000/model/new" \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model_name": "azure-gpt-4o", + "litellm_params": { + "model": "azure/gpt-4o", + "api_key": "os.environ/AZURE_API_KEY", + "api_base": "https://my-endpoint.openai.azure.com/" + } + }' ``` -3. **Expected Response** - -Returned `model_info = Your custom model_info + (if exists) LITELLM MODEL INFO` - +The rest of the operations: -[**How LiteLLM Model Info is found**](https://github.com/BerriAI/litellm/blob/9b46ec05b02d36d6e4fb5c32321e51e7f56e4a6e/litellm/proxy/proxy_server.py#L7460) +| Operation | Route | Notes | +| --- | --- | --- | +| List models | `GET /model/info` | Returns the full model list with API keys masked | +| Update a model | `POST /model/update` | Change `litellm_params` or `model_info` for an existing model | +| Delete a model | `POST /model/delete` | Body `{"id": ""}`, admin only. This is a POST; there is no DELETE-verb route | -[Tell us how this can be improved!](https://github.com/BerriAI/litellm/issues) - -```bash -{ - "data": [ - { - "model_name": "gpt-4", - "litellm_params": { - "model": "gpt-4" - }, - "model_info": { - "id": "e889baacd17f591cce4c63639275ba5e8dc60765d6c553e6ee5a504b19e50ddc", - "db_model": false, - "my_custom_key": "my_custom_value", # 👈 CUSTOM INFO - "key": "gpt-4", # 👈 KEY in LiteLLM MODEL INFO/COST MAP - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 3e-05, - "input_cost_per_character": null, - "input_cost_per_token_above_128k_tokens": null, - "output_cost_per_token": 6e-05, - "output_cost_per_character": null, - "output_cost_per_token_above_128k_tokens": null, - "output_cost_per_character_above_128k_tokens": null, - "output_vector_size": null, - "litellm_provider": "openai", - "mode": "chat" - } - }, - ] -} -``` +You can attach arbitrary `model_info` fields when you create or update a model, and they pass straight through to `GET /model/info` alongside the mapped cost and context data. That is the mechanism for annotating models with your own metadata, such as an owning team, a description, or a version, and reading it back programmatically. diff --git a/docs/proxy/multi_region.md b/docs/proxy/multi_region.md index 26b29672a..e5ce23fc6 100644 --- a/docs/proxy/multi_region.md +++ b/docs/proxy/multi_region.md @@ -7,7 +7,7 @@ import { MultiRegionArchitecture } from '@site/src/components/CloudArchitecture' Run LiteLLM proxy instances in multiple regions of the same cloud provider, all connected to one shared PostgreSQL database. Clients get routed to the nearest region for low latency, while keys, teams, users, and spend tracking stay consistent everywhere because there is a single source of truth. -This page covers the supported topology, how licensing works across regions, and step-by-step setup. For deploying the proxy itself in each region, see [Deploy to Cloud (AWS, GCP, Azure)](./deploy_cloud.md). +This page covers the supported topology, how licensing works across regions, and step-by-step setup. For deploying the proxy itself in each region, see [Deploy](./deploy.md). ## Architecture @@ -59,11 +59,11 @@ Rate limits (TPM/RPM on keys, teams, and users) are enforced through Redis. With ## Setup -The steps below assume you can already deploy a single-region production proxy (load balancer, proxy instances, Postgres, Redis). If not, start with [Deploy to Cloud](./deploy_cloud.md) and the [production checklist](./prod.md). +The steps below assume you can already deploy a single-region production proxy (load balancer, proxy instances, Postgres, Redis). If not, start with the [Deploy guide](./deploy.md) and the [production checklist](./prod.md). ### 1. Provision the shared database -Create one PostgreSQL database in your primary region and run the schema migrations against it once, using the migrations job from the [Helm charts](./deploy_cloud.md#deploy-with-helm) or the [Terraform modules](./deploy_cloud.md#deploy-with-terraform-aws-and-gcp). All regions will use this database's connection string. +Create one PostgreSQL database in your primary region and run the schema migrations against it once, using the migrations job from the [Helm charts](./deploy.md#deploy-with-helm) or the [Terraform modules](./deploy.md#deploy-with-terraform-aws-and-gcp). All regions will use this database's connection string. ### 2. Connect the regions' networks @@ -125,13 +125,9 @@ Health-check each region against `/health/liveliness`, not `/health/readiness`. 1. Open the primary region's Admin UI (`https://llm.example.com/ui`), go to **Virtual Keys**, and create a key. -Creating a virtual key in the LiteLLM Admin UI - 2. Open the secondary region's UI directly (`https://eu.llm.example.com/ui`), go to the **Test Key** playground, paste the key you just created, and send a request. It succeeds because both regions validate keys against the same database. -Test Key playground in the LiteLLM Admin UI - -3. Back on **Virtual Keys**, confirm the key shows the spend from the request you made through the secondary region. +3. Back on **Virtual Keys**, confirm the key shows the spend from the request you made through the secondary region. The UI flows themselves are covered with screenshots in the [Docker Quickstart](./docker_quick_start.md#5-create-a-virtual-key). ## Optional: dedicated admin instance @@ -182,7 +178,7 @@ Often not. A single-region deployment with a multi-AZ database and Redis already The shared-database topology itself runs on the open source proxy. Enterprise features are covered by one license across regions, as described in [Licensing across regions](#licensing-across-regions). **What happens if the primary region's database goes down?** -All regions lose database access: key validation falls back to caches, and management operations fail until the database returns. The database is the single point of coupling in this architecture. Set `general_settings.allow_requests_on_db_unavailable: true` so proxies keep serving traffic for already-cached keys during the outage (see [graceful DB unavailability](./prod.md#6-if-running-litellm-on-vpc-gracefully-handle-db-unavailability)), run the database multi-AZ with automated failover, and if that is still not enough isolation, consider the [High Availability Control Plane](./high_availability_control_plane.md) instead. +All regions lose database access: key validation falls back to caches, and management operations fail until the database returns. The database is the single point of coupling in this architecture. Set `general_settings.allow_requests_on_db_unavailable: true` so proxies keep serving traffic for already-cached keys during the outage (see [graceful DB unavailability](./prod.md#gracefully-handle-db-unavailability)), run the database multi-AZ with automated failover, and if that is still not enough isolation, consider the [High Availability Control Plane](./high_availability_control_plane.md) instead. **Can I run different LiteLLM versions in different regions?** Briefly, during a rolling upgrade. Do not run mixed versions steady-state; the shared database schema follows the newest version, and migrations should run exactly once per upgrade. \ No newline at end of file diff --git a/docs/proxy/multi_tenant_architecture.md b/docs/proxy/multi_tenant_architecture.md index 9e71530f1..081486cec 100644 --- a/docs/proxy/multi_tenant_architecture.md +++ b/docs/proxy/multi_tenant_architecture.md @@ -1,710 +1,74 @@ -import Image from '@theme/IdealImage'; +import { TenancyDiagram } from '@site/src/components/CloudArchitecture'; # Multi-Tenant Architecture with LiteLLM ## Overview -LiteLLM provides a centralized solution that scales across multiple tenants, enabling organizations to: +Multi-tenancy in LiteLLM means running a single proxy that serves many distinct tenants (organizations, teams, departments, or customers) while keeping their access, spend, and usage isolated from one another. One gateway acts as the shared entry point to every LLM provider, and every request carries the tenant context that determines which models it can reach, which budget it draws from, and where its cost lands. -- **Centrally manage** LLM access for multiple tenants (organizations, teams, departments) -- **Isolate spend and usage** across different organizational units -- **Delegate administration** without compromising security -- **Track costs** at granular levels (organization → team → user → key) -- **Scale seamlessly** as new teams and users are added +The design solves a few problems that show up whenever more than one group shares an LLM gateway. Cost has to be attributed to the right business unit rather than pooled. Access has to differ per tenant, since teams need different models, budgets, and rate limits. Administration has to be delegated, so a team lead can manage their own team without platform-wide admin rights. And the same architecture has to hold from a handful of users to tens of thousands without a redesign. :::info Open Source vs. Enterprise -- **Teams + Virtual Keys**: ✅ Available in open source -- **Organizations + Org Admins**: ✨ Enterprise feature ([Get a 7 day trial](https://www.litellm.ai/#trial)) - -You can implement multi-tenancy using **Teams** alone in the open source version, or add **Organizations** on top for additional hierarchy in the enterprise version. -::: - -## The Multi-Tenant Challenge - -Organizations with multi-tenant architectures face several challenges when deploying LLM solutions: - -1. **Centralized vs. Decentralized**: Need a single unified gateway while maintaining tenant isolation -2. **Cost Attribution**: Tracking spend across different business units, departments, or customers -3. **Access Control**: Different teams need different models, budgets, and rate limits -4. **Delegation**: Team leads should manage their teams without platform-wide admin access -5. **Scalability**: Solution must scale from 10 to 10,000+ users without architectural changes - -## How LiteLLM Solves Multi-Tenancy - - - -LiteLLM implements a hierarchical multi-tenant architecture with four levels: - -### 1. Organizations (Top-Level Tenants) ✨ Enterprise Feature - -**Organizations** represent the highest level of tenant isolation - typically different business units, departments, or customers. - -- Each organization has its own: - - Budget limits - - Allowed models - - Admin users (org admins) - - Teams - - Spend tracking - -**Use Cases:** -- **Enterprise Departments**: Separate organizations for Engineering, Marketing, Sales -- **Multi-Customer SaaS**: Each customer is an organization with full isolation -- **Geographic Regions**: EMEA, APAC, Americas as separate organizations - -**Key Features:** -- Organizations cannot see each other's data -- Each organization can have multiple teams -- Organization admins manage teams within their organization only -- Spend and usage tracked at organization level - -[API Reference for Organizations](https://litellm-api.up.railway.app/#/organization%20management) - ---- - -### 2. Teams (Mid-Level Grouping) ✅ Open Source - -**Teams** can work independently or sit within organizations, representing logical groupings of users working together. - -:::tip -Teams are available in **open source** and can be used as your primary multi-tenant boundary without needing Organizations. Organizations provide an additional layer of hierarchy for enterprise deployments. +Teams and Virtual Keys are available in open source, and Teams alone can serve as your top-level tenant boundary. Organizations and Org Admins add a further layer of hierarchy on top and are an enterprise feature ([get a 7 day trial](https://www.litellm.ai/#trial)). ::: -- Each team has: - - Team-specific budgets and rate limits - - Team admins who manage members - - Service account keys for shared resources - - Model access controls - - Granular team member permissions - -**Use Cases:** -- **Project Teams**: ML Research team, Product team, Data Science team -- **Customer Sub-Groups**: Different divisions within a customer organization -- **Environment Separation**: Development, Staging, Production teams - -**Key Features:** -- Teams inherit organization constraints (can't exceed org budget/models) -- Team admins can manage their team without affecting others -- Service account keys survive team member changes -- Per-team spend tracking and billing - -[API Reference for Teams](https://litellm-api.up.railway.app/#/team%20management) - ---- - -### 3. Users (Individual Members) ✅ Open Source - -**Users** are individuals who belong to teams and create/use API keys. - -- Each user can: - - Belong to multiple teams - - Have their own budget limits - - Create personal API keys - - Track individual spend - -**User Types:** -- **Internal Users**: Employees, developers, data scientists -- **Team Admins**: Lead their teams, manage members -- **Org Admins**: Manage multiple teams within their organization -- **Proxy Admins**: Platform-wide administrators - -**Key Features:** -- User spend tracked individually -- Users can be on multiple teams simultaneously -- Role-based permissions control what users can do -- User keys deleted when user is removed - -[API Reference for Users](https://litellm-api.up.railway.app/#/user%20management) - ---- - -### 4. Virtual Keys (Authentication Layer) ✅ Open Source - -**Virtual Keys** are the API keys used to authenticate requests and track spend. - -Each key can be one of three types: - -| Key Type | Configuration | Use Case | Spend Tracking | Lifecycle | -|----------|---------------|----------|----------------|-----------| -| **User-only** | `user_id` only | Developer personal keys | User level | Deleted with user | -| **Team Service Account** | `team_id` only | Production apps, CI/CD | Team level | Survives member changes | -| **User + Team** | Both `user_id` and `team_id` | User within team context | User AND Team | Deleted with user | - -**Example Scenarios:** -- Use **user-only keys** for developers testing locally -- Use **team service account keys** for your production application that shouldn't break when employees leave -- Use **user + team keys** when you want individual accountability within a team budget - -[API Reference for Keys](https://litellm-api.up.railway.app/#/key%20management) - ---- - -## Role-Based Access Control (RBAC) - -LiteLLM provides granular RBAC across the hierarchy: - -### Global Proxy Roles (Platform-Wide) - -| Role | Scope | Permissions | -|------|-------|-------------| -| **Proxy Admin** | Entire platform | Create orgs, teams, users. View all spend. Full control. | -| **Proxy Admin Viewer** | Entire platform | View-only access to all data. Cannot make changes. | -| **Internal User** | Own resources | Create/delete own keys. View own spend. | - -### Organization/Team Roles (Scoped) - -| Role | Scope | Permissions | -|------|-------|-------------| -| **Org Admin** ✨ | Specific organization | Create teams, add users, view org spend within their org only. | -| **Team Admin** ✨ | Specific team | Manage team members, budgets, keys within their team only. | - -✨ = Premium Feature - -### Team Member Permissions - -Team admins can configure granular permissions for regular team members: - -**Read-only** (default): -```json -["/key/info", "/key/health"] -``` - -**Allow key creation**: -```json -["/key/info", "/key/health", "/key/generate", "/key/update"] -``` - -**Full key management**: -```json -["/key/info", "/key/health", "/key/generate", "/key/update", "/key/delete", "/key/regenerate", "/key/block", "/key/unblock"] -``` - -[Learn more about RBAC](./access_control) - ---- - -## Spend Tracking & Cost Attribution - -LiteLLM provides multi-level spend tracking that flows through the hierarchy: - -### Hierarchical Spend Flow - -``` -Organization Spend - ├── Team 1 Spend - │ ├── User A Spend - │ │ ├── Key 1 Spend - │ │ └── Key 2 Spend - │ └── Service Account Spend - │ └── Key 3 Spend - └── Team 2 Spend - └── User B Spend - └── Key 4 Spend -``` - -### Budget Enforcement - -Budgets can be set at every level with inheritance: - -1. **Organization Budget**: `$10,000/month` - - Team 1: `$6,000/month` (within org limit) - - User A: `$3,000/month` (within team limit) - - User B: `$3,000/month` (within team limit) - - Team 2: `$4,000/month` (within org limit) - -**Enforcement Rules:** -- Team budgets cannot exceed organization budget -- User budgets cannot exceed team budget -- Requests blocked when any level exceeds budget -- Real-time tracking prevents overruns - -[Learn more about Budgets](./team_budgets) - ---- - -## Common Multi-Tenant Patterns - -### Pattern 1: Enterprise Departments - -**Scenario**: Large enterprise with multiple departments needing centralized LLM access - -**Enterprise Setup** (with Organizations): -``` -Platform (LiteLLM Instance) -├── Engineering Organization ✨ -│ ├── Backend Team -│ ├── Frontend Team -│ └── ML Team -├── Marketing Organization ✨ -│ ├── Content Team -│ └── Analytics Team -└── Sales Organization ✨ - ├── Sales Ops Team - └── Customer Success Team -``` - -**Open Source Alternative** (Teams only): -``` -Platform (LiteLLM Instance) -├── Engineering Backend Team -├── Engineering Frontend Team -├── Engineering ML Team -├── Marketing Content Team -├── Marketing Analytics Team -├── Sales Ops Team -└── Customer Success Team -``` - -**Benefits:** -- Each department/team manages their own budget -- Department leads (org/team admins) control their teams -- Centralized billing and model access -- Cross-department cost visibility for finance - ---- - -### Pattern 2: Multi-Customer SaaS - -**Scenario**: SaaS provider offering LLM-powered features to multiple customers - -**Enterprise Setup** (with Organizations): -``` -Platform (LiteLLM Instance) -├── Customer A Organization ✨ -│ ├── Production Team (Service Accounts) -│ ├── Development Team -│ └── QA Team -├── Customer B Organization ✨ -│ ├── Production Team (Service Accounts) -│ └── Development Team -└── Customer C Organization ✨ - └── Production Team (Service Accounts) -``` - -**Open Source Alternative** (Teams only): -``` -Platform (LiteLLM Instance) -├── Customer A Production Team (Service Accounts) -├── Customer A Development Team -├── Customer A QA Team -├── Customer B Production Team (Service Accounts) -├── Customer B Development Team -└── Customer C Production Team (Service Accounts) -``` - -**Benefits:** -- Complete isolation between customers/teams -- Per-customer/team billing and usage tracking -- Customer/team admins can self-serve -- Production service account keys survive employee turnover - ---- - -### Pattern 3: Environment Separation - -**Scenario**: Single organization with multiple environments - -``` -Platform (LiteLLM Instance) -└── Company Organization - ├── Production Team - │ └── Service Account Keys (strict rate limits) - ├── Staging Team - │ └── Service Account Keys (moderate limits) - └── Development Team - └── User Keys (generous limits for testing) -``` - -**Benefits:** -- Separate budgets for each environment -- Different model access (production vs. development) -- Prevent development usage from affecting production budget -- Easy cost attribution by environment +## The Tenancy Hierarchy ---- + -## Delegation & Self-Service +LiteLLM models tenancy as four nested levels: Organizations contain Teams, Teams contain Users, and Users and Teams own Keys. Each level is a boundary for isolation and for spend attribution. -One of LiteLLM's key advantages is delegated administration: +- Organizations are the top-level tenant and can hold multiple teams. [API Reference](https://litellm-api.up.railway.app/#/organization%20management) +- Teams are collections of users and can hold multiple users. [API Reference](https://litellm-api.up.railway.app/#/team%20management) +- Users belong to teams (possibly several at once) and can own multiple keys. [API Reference](https://litellm-api.up.railway.app/#/user%20management) +- Keys authenticate requests and belong to a user, a team, or both. [API Reference](https://litellm-api.up.railway.app/#/key%20management) -### Without LiteLLM -``` -Every team → Requests platform admin → Admin makes changes -``` -❌ Bottleneck on platform team -❌ Slow onboarding -❌ Poor scalability +### Organizations -### With LiteLLM -``` -Proxy Admin → Creates org + org admin -Org Admin → Creates teams + team admins -Team Admin → Manages their team independently -``` -✅ Decentralized management -✅ Fast onboarding -✅ Scales to thousands of users +An Organization is the highest level of isolation, typically mapped to a business unit, a customer, or a region. Organizations cannot see each other's data or keys, each carries its own budget and allowed-model list, and each is administered by its own org admins who manage only the teams inside it. Organizations are an enterprise feature. -### Self-Service Capabilities +### Teams -**Team Admins Can:** -- Add/remove team members -- Create API keys for team members -- Update team budgets (within org limits) -- Configure team member permissions -- View team usage and spend +A Team is a logical grouping of users who work together, and it is the primary tenant boundary in open source. A team has its own budget and rate limits, its own admins, its own model access controls, and its own service account keys for shared workloads. When a team sits inside an organization it inherits that organization's constraints and cannot exceed the org budget or reach models the org does not allow. -**Org Admins Can:** -- Create new teams within their organization -- Assign team admins -- View organization-wide spend -- Manage users across their teams +### Users -**Platform Admins Can:** -- Create organizations -- Assign org admins -- Set organization-level policies -- View platform-wide analytics +A User is an individual who belongs to one or more teams and creates or uses keys. Spend is tracked per user, and what a user can do is governed by their role, which ranges from a plain internal user through team and org admins up to the platform-wide proxy admin. Removing a user deletes the keys they personally own. ---- +### Keys (Virtual Keys) -## Scalability +A Virtual Key is what authenticates a request and ties it to a tenant for spend tracking. A key can be scoped to a user, to a team (a service account key that survives member turnover), or to both. For the full breakdown of key types and when to use each, see [Service Accounts](./service_accounts.md). -LiteLLM's architecture scales from small teams to enterprise deployments: +## Roles and Delegation -### Small Team (10-100 users) -- Single organization -- Few teams (5-10) -- Proxy admins manage everything +Isolation only works if administration can be delegated along the same hierarchy. LiteLLM ships roles at two altitudes: platform-wide roles (`proxy_admin`, `proxy_admin_viewer`, `internal_user`) that apply everywhere, and scoped roles (`org_admin`, `team_admin`) that grant control over a single organization or team. A proxy admin creates organizations and assigns org admins, an org admin creates teams within their organization and assigns team admins, and a team admin manages their own team's members, budgets, and keys without touching anything else. That chain is what lets the platform onboard thousands of users without every change routing through a central admin. For the complete role matrix, per-role capabilities, and configurable team-member permissions, see [Access Control](./access_control.md), and for how internal users onboard and manage their own keys see [Internal User Self-Serve](./self_serve.md). -### Mid-Size (100-1,000 users) -- Multiple organizations -- Many teams (50+) -- Org admins delegate to team admins +## Spend and Budgets -### Enterprise (1,000+ users) -- Many organizations (departments/regions) -- Hundreds of teams -- Fully delegated admin structure -- Centralized observability and billing +Spend flows up the hierarchy, so every request's cost is attributed to its key, its user, its team, and its organization at once. Budgets can be set at each level and are enforced inward: a team budget cannot exceed its organization's, a user budget cannot exceed the team's, and a request is blocked once any level along its path is over budget. This is what makes per-tenant chargeback and showback possible from a shared instance. See [Team Budgets](./team_budgets.md) for configuring budgets across the hierarchy and [Cost Tracking](./cost_tracking.md) for how spend is attributed and reported. -**Key Scalability Features:** -- No architectural changes needed as you grow -- Database-backed (PostgreSQL) for reliability -- Horizontal scaling support -- Efficient spend tracking and logging +## Common Tenancy Patterns ---- +The same four levels express several real-world shapes. These are illustrations of how the hierarchy maps onto an organization, not setup guides. -## Security & Isolation +### Enterprise Departments -### Tenant Isolation +A large enterprise gives each department its own tenant. With Organizations, Engineering, Marketing, and Sales are separate organizations, each holding several teams (Backend, Frontend, ML, and so on) that manage their own budgets under a department-wide cap. In open source the same separation is expressed with teams alone (an Engineering Backend team, a Marketing Content team, and so on), trading the department-level rollup for a flatter structure. Either way each group owns its budget, department or team leads act as admins, and finance keeps cross-department cost visibility. -Each tenant (organization) is isolated: -- ✅ Cannot view other organizations' data -- ✅ Cannot access other organizations' keys -- ✅ Cannot exceed their budget limits -- ✅ Cannot access models not in their allowed list +### Multi-Customer SaaS -### Authentication Security +A SaaS provider that embeds LLM features gives each customer a tenant so that usage, billing, and data stay isolated. With Organizations, each customer is an organization holding Production, Development, and QA teams, where production runs on service account keys that survive employee turnover. In open source each customer's teams live side by side without the organization wrapper. The isolation guarantee is the same: one customer can never see another's data or spend, and each is billed on its own usage. -- Master key for platform admins -- Virtual keys with scoped permissions -- SSO integration support -- JWT authentication -- IP allowlisting +### Environment Separation -### Audit & Compliance - -- All API calls logged with user/team/org context -- Spend tracking for chargeback/showback -- Admin actions audited -- Integration with observability tools - -[Learn more about Security](../data_security) - ---- - -## Getting Started - -:::info Enterprise vs. Open Source Setup -The steps below show the **full enterprise hierarchy** with Organizations. - -For **open source**, skip Steps 1-2 and start directly with **Step 3** (creating teams). Teams can function as your top-level tenant boundary without Organizations. -::: - -### Step 1: Set Up Organizations ✨ Enterprise - -Create your first organization: - -```bash -curl --location 'http://0.0.0.0:4000/organization/new' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "organization_alias": "engineering_department", - "models": ["gpt-4", "gpt-4o", "claude-3-5-sonnet"], - "max_budget": 10000 - }' -``` - -### Step 2: Add an Organization Admin ✨ Enterprise - -```bash -curl -X POST 'http://0.0.0.0:4000/organization/member_add' \ - -H 'Authorization: Bearer sk-1234' \ - -H 'Content-Type: application/json' \ - -d '{ - "organization_id": "org-123", - "member": { - "role": "org_admin", - "user_id": "admin@company.com" - } - }' -``` - -### Step 3: Create Teams ✅ Open Source - -**For Enterprise:** Organization admin creates team within their organization -**For Open Source:** Proxy admin creates team directly (no `organization_id` needed) - -```bash -# Enterprise: Org admin creates team in their organization -curl --location 'http://0.0.0.0:4000/team/new' \ - --header 'Authorization: Bearer sk-org-admin-key' \ - --header 'Content-Type: application/json' \ - --data '{ - "team_alias": "ml_team", - "organization_id": "org-123", - "max_budget": 5000 - }' - -# Open Source: Proxy admin creates team directly -curl --location 'http://0.0.0.0:4000/team/new' \ - --header 'Authorization: Bearer sk-1234' \ - --header 'Content-Type: application/json' \ - --data '{ - "team_alias": "ml_team", - "max_budget": 5000 - }' -``` - -### Step 4: Add Team Admin - -```bash -curl -X POST 'http://0.0.0.0:4000/team/member_add' \ - -H 'Authorization: Bearer sk-org-admin-key' \ - -H 'Content-Type: application/json' \ - -d '{ - "team_id": "team-456", - "member": { - "role": "admin", - "user_id": "team-lead@company.com" - } - }' -``` - -### Step 5: Team Admin Manages Their Team - -```bash -# Team admin adds members -curl -X POST 'http://0.0.0.0:4000/team/member_add' \ - -H 'Authorization: Bearer sk-team-admin-key' \ - -H 'Content-Type: application/json' \ - -d '{ - "team_id": "team-456", - "member": { - "role": "user", - "user_id": "developer@company.com" - } - }' - -# Team admin creates keys for members -curl --location 'http://0.0.0.0:4000/key/generate' \ - --header 'Authorization: Bearer sk-team-admin-key' \ - --header 'Content-Type: application/json' \ - --data '{ - "user_id": "developer@company.com", - "team_id": "team-456" - }' -``` - ---- - -## Use Case Examples - -### Example 1: Chargeback Model - -**Goal**: Each business unit pays for their own LLM usage - -**Setup:** -1. Create organization per business unit -2. Set budgets based on allocated budgets -3. Track spend per organization -4. Generate monthly reports for finance - -**Result**: Finance can charge back costs to respective departments with accurate attribution. - ---- - -### Example 2: Customer-Facing AI Product - -**Goal**: Provide LLM capabilities to customers with isolation and cost tracking - -**Setup:** -1. Create organization per customer -2. Use service account keys for production workloads -3. Track spend per customer organization -4. Set rate limits per customer tier - -**Result**: Bill customers accurately, prevent noisy neighbors, maintain isolation. - ---- - -### Example 3: Development vs. Production - -**Goal**: Separate development and production environments with different policies - -**Setup:** -1. Create "Development" and "Production" teams -2. Development: Generous budgets, all models, user keys -3. Production: Strict budgets, approved models only, service account keys -4. Different rate limits per environment - -**Result**: Developers can experiment freely without impacting production budget or reliability. - ---- - -## Best Practices - -### 1. Organization Design - -- ✅ Map organizations to cost centers or customers -- ✅ Set realistic budgets with buffer for growth -- ✅ Assign 1-2 org admins per organization -- ❌ Don't create too many organizations (adds management overhead) - -### 2. Team Structure - -- ✅ Keep teams aligned with actual working groups -- ✅ Use service account keys for production -- ✅ Give team admins enough permissions to self-serve -- ❌ Don't create single-user teams (use user-only keys instead) - -### 3. Key Management - -- ✅ Use descriptive key names -- ✅ Rotate keys regularly -- ✅ Delete unused keys -- ✅ Use appropriate key type for use case -- ❌ Don't share keys across users/teams - -### 4. Budget Management - -- ✅ Set budgets at multiple levels (org → team → user) -- ✅ Monitor spend regularly -- ✅ Alert before budget exhaustion -- ❌ Don't set budgets too tight (may block legitimate usage) - -### 5. Delegation - -- ✅ Assign org admins for large organizations -- ✅ Assign team admins for active teams -- ✅ Configure team member permissions appropriately -- ❌ Don't make everyone a proxy admin - ---- - -## Monitoring & Observability - -LiteLLM provides comprehensive monitoring: - -- **Spend Tracking**: Real-time spend by org/team/user/key -- **Usage Analytics**: Request counts, token usage, model usage -- **Admin UI**: Visual dashboard for all metrics -- **Logging**: Detailed logs with tenant context -- **Alerting**: Budget alerts, rate limit alerts, error alerts - -[Learn more about Logging](./logging) - ---- - -## Comparison with Other Approaches - -| Approach | Pros | Cons | LiteLLM Advantage | -|----------|------|------|-------------------| -| **Separate instances per tenant** | Strong isolation | High operational overhead, cost inefficient | Single instance, same isolation, 90% cost reduction | -| **Single shared pool** | Simple setup | No cost attribution, no access control | Full attribution, granular access control | -| **API key prefixes** | Basic separation | Manual tracking, no hierarchy, no RBAC | Automatic tracking, hierarchical, full RBAC | -| **External auth layer** | Flexible | Complex integration, no built-in budgets | Native integration, built-in budgets | - ---- - -## FAQ - -**Q: Can users belong to multiple teams?** -A: Yes, users can be members of multiple teams and have different keys for each team. - -**Q: What happens when a user leaves?** -A: User-specific keys are deleted, but team service account keys remain active. - -**Q: Can team budgets exceed organization budget?** -A: No, the system enforces that team budgets cannot exceed their organization's budget. - -**Q: How granular is the cost tracking?** -A: Every API call is tracked with organization, team, user, and key context. - -**Q: Can I have teams without organizations?** -A: Yes! Teams work independently in **open source** without needing Organizations. Organizations are an **enterprise feature** that adds an additional hierarchy layer on top of teams. - -**Q: Is there a limit to hierarchy depth?** -A: The hierarchy is: Organization → Team → User → Key (4 levels). This covers most use cases. - -**Q: How do I migrate from flat structure to hierarchical?** -A: You can gradually create organizations and teams, then move existing users/keys into them. - ---- +A single company separates Production, Staging, and Development into distinct teams so that experimentation cannot spend against or destabilize production. Production and staging lean on service account keys with strict rate limits and an approved model list, while development uses more permissive user keys for testing. Because each environment is its own budget and model boundary, development traffic can never draw down the production budget. ## Related Documentation -- [User Management Hierarchy](./user_management_heirarchy) - Visual hierarchy overview -- [Access Control (RBAC)](./access_control) - Detailed role permissions -- [Team Budgets](./team_budgets) - Budget management guide -- [Virtual Keys](./virtual_keys) - API key management -- [Admin UI](./ui) - Visual dashboard for management - ---- - -## Summary - -LiteLLM solves multi-tenant architecture challenges through: - -1. **Hierarchical Structure**: Organizations → Teams → Users → Keys -2. **Granular RBAC**: Platform-wide and tenant-scoped roles -3. **Cost Attribution**: Spend tracking at every level -4. **Delegation**: Org admins and team admins self-manage -5. **Isolation**: Strong tenant boundaries -6. **Scalability**: Handles 10 to 10,000+ users with same architecture - -### Open Source vs. Enterprise - -**Open Source** (Teams + Users + Keys): -- ✅ Teams as primary tenant boundary -- ✅ Team admins manage their teams -- ✅ Virtual keys with team/user tracking -- ✅ Budget and rate limits per team -- ✅ Spend tracking and logging - -**Enterprise** (Adds Organizations layer): -- ✨ Organizations for top-level tenant isolation -- ✨ Organization admins manage multiple teams -- ✨ Organization-level budgets and model access -- ✨ Hierarchical delegation and reporting - -This makes LiteLLM ideal for: -- ✅ Enterprises with multiple departments -- ✅ SaaS providers with multiple customers -- ✅ Organizations needing cost chargeback/showback -- ✅ Teams requiring self-service LLM access -- ✅ Any multi-tenant LLM deployment - -[Start with LiteLLM Proxy →](./quick_start) +- [Access Control (RBAC)](./access_control.md) - roles, permissions, and onboarding organizations +- [Service Accounts](./service_accounts.md) - virtual key types and shared production keys +- [Team Budgets](./team_budgets.md) - budgets across the hierarchy +- [Cost Tracking](./cost_tracking.md) - spend attribution and reporting +- [Internal User Self-Serve](./self_serve.md) - how users onboard and manage their own keys +- [Logging](./logging.md) - monitoring spend and usage with tenant context +- [Admin UI](./ui.md) - visual dashboard for managing tenants diff --git a/docs/proxy/prod.md b/docs/proxy/prod.md index 48f497066..63fea0542 100644 --- a/docs/proxy/prod.md +++ b/docs/proxy/prod.md @@ -1,192 +1,154 @@ +--- +title: Production Best Practices +description: Checklist for running LiteLLM in production; configuration, sizing and workers, Redis, and database and migrations. +--- + import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Image from '@theme/IdealImage'; -# ⚡ Best Practices for Production +# Production Best Practices -## 1. Use this config.yaml -Use this config.yaml in production (with your own LLMs) +Work through this page before going live. It covers the production configuration, machine sizing and worker strategy, Redis, and database and migrations; each section stands alone, so you can also use it as a review checklist for an existing deployment. For deeper container tuning such as alternative servers, TLS at the proxy, keepalive, and loading config from object storage, see [Server Tuning](./server_tuning.md). -```yaml -model_list: - - model_name: fake-openai-endpoint - litellm_params: - model: openai/fake - api_key: fake-key - api_base: https://exampleopenaiendpoint-production.up.railway.app/ +## Configuration -general_settings: - master_key: sk-1234 # enter your own master key, ensure it starts with 'sk-' - alerting: ["slack"] # Setup slack alerting - get alerts on LLM exceptions, Budget Alerts, Slow LLM Responses - proxy_batch_write_at: 60 # Batch write spend updates every 60s - database_connection_pool_limit: 10 # connection pool limit per worker process. Total connections = limit × workers × instances. Calculate: MAX_DB_CONNECTIONS / (instances × workers). Default: 10. +### Set a master key - # OPTIONAL Best Practices - disable_error_logs: True # turn off writing LLM Exceptions to DB - allow_requests_on_db_unavailable: True # Only USE when running LiteLLM on your VPC. Allow requests to still be processed even if the DB is unavailable. We recommend doing this if you're running LiteLLM on VPC that cannot be accessed from the public internet. +The master key is the proxy admin credential: it authenticates admin API calls and is the Admin UI login password. Set it as an env var (it must start with `sk-`), keep it in your secret manager, and rotate it with the [master key rotation flow](./master_key_rotations.md). -litellm_settings: - request_timeout: 600 # raise Timeout error if call takes longer than 600 seconds. Default value is 6000seconds if not set - set_verbose: False # Switch off Debug Logging, ensure your logs do not have any debugging on - json_logs: true # Get debug logs in json format -``` -:::warning Multiple instances - -If running multiple LiteLLM instances (e.g., Kubernetes pods), remember each instance multiplies your total connections. Example: 3 instances × 4 workers × 10 connections = 120 total connections. - -::: - -Set slack webhook url in your env -```shell -export SLACK_WEBHOOK_URL="example-slack-webhook-url" -``` - -Turn off FASTAPI's default info logs ```bash -export LITELLM_LOG="ERROR" +export LITELLM_MASTER_KEY="sk-" ``` -:::info - -Need Help or want dedicated support ? Talk to a founder [here](https://enterprise.litellm.ai/demo). +### Turn on alerting -::: +Get notified about LLM exceptions, slow or hanging requests, budget crossings, database exceptions, outages, and weekly spend reports. In the Admin UI go to **Settings** then **Logging & Alerts**, open the **Alerting Types** tab, toggle the alert types you want, paste your Slack webhook URL, and click **Test Alerts** to confirm delivery. Thresholds and report frequency live in the **Alerting Settings** tab next to it. +Alerting Types tab in the Admin UI with per-alert toggles and Slack webhook fields -## 2. Recommended Machine Specifications +To bake it into config instead, set `alerting: ["slack"]` under `general_settings` and export `SLACK_WEBHOOK_URL` in the environment. -For optimal performance in production, we recommend the following resource configuration. +### Batch spend writes -**1. Memory `requests` and `limits`** +Write spend updates to the database every 60 seconds instead of on every request; at production traffic, per-request writes become a database hot spot. ```yaml -resources: - requests: - cpu: "1" # should be 1*num_workers - memory: "4Gi" # should be 4*num_workers - limits: - cpu: "1" - memory: "4Gi" +general_settings: + proxy_batch_write_at: 60 ``` -**2. HPA thresholds** +Above roughly 1000 requests per second, also route these writes through Redis with the [Redis transaction buffer](./db_deadlocks.md) to prevent connection exhaustion and deadlocks. + +### Bound database connections + +Cap the connection pool per worker process so your instances cannot exhaust the database. Size it as `MAX_DB_CONNECTIONS / (instances × workers)`; the default is 10. ```yaml -targetCPUUtilizationPercentage: 60 -targetMemoryUtilizationPercentage: 80 +general_settings: + database_connection_pool_limit: 10 ``` +:::warning Multiple instances -## 3. Choose your server: Uvicorn vs. Gunicorn - -LiteLLM Proxy runs on [Uvicorn](https://uvicorn.dev/) by default. Passing `--run_gunicorn` instead starts [Gunicorn](https://gunicorn.org/) as a process manager that supervises [Uvicorn worker processes](https://uvicorn.dev/deployment/#gunicorn) (`uvicorn.workers.UvicornWorker`). In both cases your application code still runs on Uvicorn; the difference is which process manages and recycles the workers. +Each instance multiplies your total connections: 3 instances × 4 workers × 10 connections = 120 total connections against your database. -| | Uvicorn (default) | Gunicorn (`--run_gunicorn`) | -|---|---|---| -| **When to use** | Recommended for almost all deployments, especially Kubernetes with one worker per pod. | Choose when you run **multiple workers in a single container** and want a mature process manager to supervise and recycle them. | -| **Worker recycling** | Uvicorn's [`limit_max_requests`](https://uvicorn.dev/settings/#resource-limits). | Gunicorn's [`max_requests`](https://gunicorn.org/reference/settings/#max_requests), the battle-tested mechanism Gunicorn has shipped for years. | -| **Process supervision** | Uvicorn's built-in multiprocess manager. | Gunicorn's [arbiter](https://gunicorn.org/design/#arbiter), which restarts workers one at a time as they exit. | +::: -:::tip Recommendation +### Keep error logs out of the database -On Kubernetes, run **one Uvicorn worker per pod** and scale **horizontally** (more pods) rather than vertically (more workers per pod). One process per pod keeps latency predictable under load, lets the Horizontal Pod Autoscaler use the [thresholds above](#2-recommended-machine-specifications) accurately, and makes rolling restarts hitless because Kubernetes drains one pod at a time. Reach for Gunicorn only when you must pack multiple workers into one container. +LLM exceptions are written to the database by default. Under sustained provider errors this bloats the spend logs table; send exceptions to your logging stack (see [alerting](#turn-on-alerting) and [logging callbacks](./logging.md)) instead. -::: +```yaml +general_settings: + disable_error_logs: True +``` -### 3a. Recommended: one Uvicorn worker per pod +### Set a request timeout -This is the default server, so you only need to set `--num_workers 1` (the default is already `1`): +Fail requests that hang instead of holding connections open; the default is 6000 seconds. -```shell -CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "1"] +```yaml +litellm_settings: + request_timeout: 600 ``` -### 3b. Recycle workers with `--max_requests_before_restart` +### Production logging -If you observe gradual memory growth under sustained load, recycle each worker after a fixed number of requests to bound memory usage. `--max_requests_before_restart` maps to Uvicorn's [`limit_max_requests`](https://uvicorn.dev/settings/#resource-limits) (default server) and to Gunicorn's [`max_requests`](https://gunicorn.org/reference/settings/#max_requests) under `--run_gunicorn`. Configure it via CLI flag or environment variable: +Switch off debug logging, emit JSON logs, and silence FastAPI's per-request info logs: -```shell -# CLI -CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "1", "--max_requests_before_restart", "10000"] +```yaml +litellm_settings: + set_verbose: False + json_logs: true +``` -# or ENV (for deployment manifests / containers) -export MAX_REQUESTS_BEFORE_RESTART=10000 +```bash +export LITELLM_LOG="ERROR" ``` -:::tip +### Disable load_dotenv -When you run **multiple workers in one container** and rely on `--max_requests_before_restart`, prefer `--run_gunicorn`. Gunicorn's [`max_requests`](https://gunicorn.org/reference/settings/#max_requests) recycling is more mature than Uvicorn's, and its [arbiter](https://gunicorn.org/design/#arbiter) restarts workers one at a time so the pod keeps serving traffic while a worker is replaced. +Set `export LITELLM_MODE="PRODUCTION"`. This disables `load_dotenv()`, which would otherwise automatically load credentials from a local `.env`. -::: +### Set the salt key -```shell -# Multiple workers in one container, with Gunicorn-managed recycling -CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "4", "--run_gunicorn", "--max_requests_before_restart", "10000"] +If you use the database, set a salt key for encrypting and decrypting stored variables. Do not change it after adding a model; it encrypts your LLM API key credentials, and changing it makes them unreadable. Use a [password generator](https://1password.com/password-generator/) to get a random hash. + +```bash +export LITELLM_SALT_KEY="sk-1234" ``` -When several workers boot together and serve a similar amount of traffic, they reach the request threshold at almost the same time and recycle in lockstep, dropping a chunk of capacity at once. Add `--max_requests_before_restart_jitter` to offset each worker's threshold by a random amount in `[0, jitter]` so restarts stagger instead of synchronizing. It maps to Uvicorn's [`limit_max_requests_jitter`](https://uvicorn.dev/settings/#resource-limits) (requires `uvicorn>=0.41.0`) and Gunicorn's [`max_requests_jitter`](https://gunicorn.org/reference/settings/#max_requests_jitter), and has no effect without `--max_requests_before_restart`. +[**See Code**](https://github.com/BerriAI/litellm/blob/036a6821d588bd36d170713dcf5a72791a694178/litellm/proxy/common_utils/encrypt_decrypt_utils.py#L15) -```shell -# Stagger recycling so workers don't all restart at once -CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "4", "--run_gunicorn", "--max_requests_before_restart", "10000", "--max_requests_before_restart_jitter", "1000"] -``` +## Sizing and workers -### 3c. Keep restarts hitless +### Machine specifications -A restart is "hitless" when in-flight requests finish before the process exits, so no client sees a dropped connection. Two cases matter in production: +For optimal performance in production, we recommend the following resource configuration. -**Worker recycling (from `--max_requests_before_restart`).** Both servers stop accepting new connections on the recycled worker and let outstanding requests drain before it exits, then a replacement worker starts. Gunicorn additionally guarantees in-flight requests up to its [`graceful_timeout`](https://gunicorn.org/reference/settings/#graceful_timeout) (30s by default) on [`SIGTERM`](https://gunicorn.org/signals/). With one worker per pod, recycling briefly reduces that pod's capacity, which is why we recommend scaling horizontally so the load balancer can route around it. +**1. Memory `requests` and `limits`** -**Rolling deploys and pod restarts (Kubernetes).** Make restarts hitless at the orchestration layer rather than relying on the server alone: +```yaml +resources: + requests: + cpu: "1" # should be 1*num_workers + memory: "4Gi" # should be 4*num_workers + limits: + cpu: "1" + memory: "4Gi" +``` -- Use a [`RollingUpdate`](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-update-deployment) strategy (the Deployment default) so new pods become Ready before old pods are terminated. -- Keep a [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/) on `/health/readiness` so Kubernetes only sends traffic to pods that can serve it, and stops routing to a pod as soon as termination begins. -- Set [`terminationGracePeriodSeconds`](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination) to comfortably exceed your longest expected request (LiteLLM's request timeout defaults to 600s; see [Section 1](#1-use-this-configyaml)). On termination Kubernetes sends `SIGTERM`, and both Uvicorn and Gunicorn shut down [gracefully](https://uvicorn.dev/deployment/) by draining in-flight requests before exiting. -- Optionally add a small [`preStop` hook](https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks) (for example `sleep 5`) to give the load balancer time to deregister the pod before the server begins shutting down, eliminating the brief window where traffic can still arrive at a terminating pod. +**2. HPA thresholds** -```yaml title="Kubernetes Deployment snippet for hitless rolling restarts" -spec: - strategy: - type: RollingUpdate - rollingUpdate: - maxUnavailable: 0 # never drop below desired replica count - maxSurge: 1 # add one new pod at a time - template: - spec: - terminationGracePeriodSeconds: 620 # > your longest request (request_timeout: 600) - containers: - - name: litellm - readinessProbe: - httpGet: - path: /health/readiness - port: 4000 - lifecycle: - preStop: - exec: - command: ["sh", "-c", "sleep 5"] +```yaml +targetCPUUtilizationPercentage: 60 +targetMemoryUtilizationPercentage: 80 ``` +### Workers and scaling -## 4. Use Redis 'port','host', 'password'. NOT 'redis_url' +Run one Uvicorn worker per pod and scale horizontally (more pods) rather than vertically (more workers per pod). This is the default, so you only need `--num_workers 1`; one process per pod keeps latency predictable, lets the Horizontal Pod Autoscaler use the [thresholds above](#machine-specifications) accurately, and makes rolling restarts hitless because Kubernetes drains one pod at a time. -If you decide to use Redis, DO NOT use 'redis_url'. We recommend using redis port, host, and password params. +```shell +CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "1"] +``` -`redis_url`is 80 RPS slower +If you see gradual memory growth under sustained load, recycle each worker after a fixed number of requests with `--max_requests_before_restart` to bound memory usage. -This is still something we're investigating. Keep track of it [here](https://github.com/BerriAI/litellm/issues/3188) +```shell +CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "1", "--max_requests_before_restart", "10000"] +``` -### Redis Version Requirement +For packing multiple workers into one container, alternative servers (Gunicorn, Hypercorn, Granian), staggering recycles with jitter, hitless rolling restarts on Kubernetes, terminating TLS at the proxy, keepalive tuning, and loading `config.yaml` from S3 or GCS, see [Server Tuning](./server_tuning.md). -| Component | Minimum Version | -|-----------|-----------------| -| Redis | 7.0+ | +## Redis -Recommended to do this for prod: +Run Redis (7.0 or newer) as soon as you run more than one proxy instance. It shares rate limit counters, router state, and the response cache across instances; without it, each instance enforces limits independently and cache hits stay local to the instance that served the request. ```yaml router_settings: routing_strategy: simple-shuffle # (default) - recommended for best performance - # redis_url: "os.environ/REDIS_URL" redis_host: os.environ/REDIS_HOST redis_port: os.environ/REDIS_PORT redis_password: os.environ/REDIS_PASSWORD @@ -200,53 +162,45 @@ litellm_settings: password: os.environ/REDIS_PASSWORD ``` -> **WARNING** -**Usage-based routing is not recommended for production due to performance impacts.** Use `simple-shuffle` (default) for optimal performance in high-traffic scenarios. +Keep the default `simple-shuffle` routing strategy for high-traffic deployments; usage-based routing adds Redis lookups to the request path. -## 5. Disable 'load_dotenv' +## Database and migrations -Set `export LITELLM_MODE="PRODUCTION"` - -This disables the load_dotenv() functionality, which will automatically load your environment credentials from the local `.env`. - -## 6. If running LiteLLM on VPC, gracefully handle DB unavailability +### Gracefully handle DB unavailability When running LiteLLM on a VPC (and inaccessible from the public internet), you can enable graceful degradation so that request processing continues even if the database is temporarily unavailable. - **WARNING: Only do this if you're running LiteLLM on VPC, that cannot be accessed from the public internet.** -#### Configuration - ```yaml showLineNumbers title="litellm config.yaml" general_settings: allow_requests_on_db_unavailable: True ``` -#### Expected Behavior - When `allow_requests_on_db_unavailable` is set to `true`, LiteLLM will handle errors as follows: | Type of Error | Expected Behavior | Details | |---------------|-------------------|----------------| -| Prisma Errors | ✅ Request will be allowed | Covers issues like DB connection resets or rejections from the DB via Prisma, the ORM used by LiteLLM. | -| Httpx Errors | ✅ Request will be allowed | Occurs when the database is unreachable, allowing the request to proceed despite the DB outage. | -| Pod Startup Behavior | ✅ Pods start regardless | LiteLLM Pods will start even if the database is down or unreachable, ensuring higher uptime guarantees for deployments. | -| Health/Readiness Check | ✅ Always returns 200 OK | The /health/readiness endpoint returns a 200 OK status to ensure that pods remain operational even when the database is unavailable. -| LiteLLM Budget Errors or Model Errors | ❌ Request will be blocked | Triggered when the DB is reachable but the authentication token is invalid, lacks access, or exceeds budget limits. | - +| Prisma Errors | Request will be allowed | Covers issues like DB connection resets or rejections from the DB via Prisma, the ORM used by LiteLLM. | +| Httpx Errors | Request will be allowed | Occurs when the database is unreachable, allowing the request to proceed despite the DB outage. | +| Pod Startup Behavior | Pods start regardless | LiteLLM Pods will start even if the database is down or unreachable, ensuring higher uptime guarantees for deployments. | +| Health/Readiness Check | Always returns 200 OK | The /health/readiness endpoint returns a 200 OK status to ensure that pods remain operational even when the database is unavailable. | +| LiteLLM Budget Errors or Model Errors | Request will be blocked | Triggered when the DB is reachable but the authentication token is invalid, lacks access, or exceeds budget limits. | [More information about what the Database is used for here](db_info) -## 7. Use Helm PreSync Hook for Database Migrations [BETA] +### Run migrations from the Helm PreSync hook -To ensure only one service manages database migrations, use our [Helm PreSync hook for Database Migrations](https://github.com/BerriAI/litellm/blob/main/deploy/charts/litellm-helm/templates/migrations-job.yaml). This ensures migrations are handled during `helm upgrade` or `helm install`, while LiteLLM pods explicitly disable migrations. +:::info +The Helm PreSync hook flow is in beta. +::: +To ensure only one service manages database migrations, use our [Helm PreSync hook for Database Migrations](https://github.com/BerriAI/litellm/blob/main/deploy/charts/litellm-helm/templates/migrations-job.yaml). This ensures migrations are handled during `helm upgrade` or `helm install`, while LiteLLM pods explicitly disable migrations. 1. **Helm PreSync Hook**: - The Helm PreSync hook is configured in the chart to run database migrations during deployments. - The hook always sets `DISABLE_SCHEMA_UPDATE=false`, ensuring migrations are executed reliably. - + Reference Settings to set on ArgoCD for `values.yaml` ```yaml @@ -257,7 +211,7 @@ To ensure only one service manages database migrations, use our [Helm PreSync ho 2. **LiteLLM Pods**: - Set `DISABLE_SCHEMA_UPDATE=true` in LiteLLM pod configurations to prevent them from running migrations. - + Example configuration for LiteLLM pod: ```yaml env: @@ -265,46 +219,14 @@ To ensure only one service manages database migrations, use our [Helm PreSync ho value: "true" ``` +### Use prisma migrate deploy -## 8. Set LiteLLM Salt Key - -If you plan on using the DB, set a salt key for encrypting/decrypting variables in the DB. - -Do not change this after adding a model. It is used to encrypt / decrypt your LLM API Key credentials - -We recommend - https://1password.com/password-generator/ password generator to get a random hash for litellm salt key. - -```bash -export LITELLM_SALT_KEY="sk-1234" -``` - -[**See Code**](https://github.com/BerriAI/litellm/blob/036a6821d588bd36d170713dcf5a72791a694178/litellm/proxy/common_utils/encrypt_decrypt_utils.py#L15) - - -## 9. Use `prisma migrate deploy` - -Use this to handle db migrations across LiteLLM versions in production - - - +Use this to handle db migrations across LiteLLM versions in production: ```bash USE_PRISMA_MIGRATE="True" ``` - - - - -```bash -litellm -``` - - - - -Benefits: - The migrate deploy command: - **Does not** issue a warning if an already applied migration is missing from migration history @@ -312,8 +234,7 @@ The migrate deploy command: - **Does not** reset the database or generate artifacts (such as Prisma Client) - **Does not** rely on a shadow database - -### How does LiteLLM handle DB migrations in production? +How LiteLLM ships migrations: 1. A new migration file is written to our `litellm-proxy-extras` package. [See all](https://github.com/BerriAI/litellm/tree/main/litellm-proxy-extras/litellm_proxy_extras/migrations) @@ -321,26 +242,22 @@ The migrate deploy command: 3. When you upgrade to a new version of LiteLLM, the migration file is applied to the database. [See code](https://github.com/BerriAI/litellm/blob/52b35cd8093b9ad833987b24f494586a1e923209/litellm-proxy-extras/litellm_proxy_extras/utils.py#L42) - -### Read-only File System +### Read-only file system Running LiteLLM with `readOnlyRootFilesystem: true` is a Kubernetes security best practice that prevents container processes from writing to the root filesystem. LiteLLM fully supports this configuration. -#### Quick Fix for Permission Errors - If you see a `Permission denied` error, it means the LiteLLM pod is running with a read-only file system. LiteLLM needs writable directories for: - **Database migrations**: Set `LITELLM_MIGRATION_DIR="/path/to/writable/directory"` - **Admin UI**: Set `LITELLM_UI_PATH="/path/to/writable/directory"` - **UI assets/logos**: Set `LITELLM_ASSETS_PATH="/path/to/writable/directory"` -#### Complete Read-Only Filesystem Setup (Kubernetes) - -For production deployments with enhanced security, use this configuration: - **Option 1: Using EmptyDir Volumes with InitContainer (Recommended)** This approach copies the pre-built UI from the Docker image to writable emptyDir volumes at pod startup. +
+Full Deployment manifest (initContainer, env, securityContext, volumes) + ```yaml apiVersion: apps/v1 kind: Deployment @@ -419,6 +336,8 @@ spec: sizeLimit: 64Mi ``` +
+ **Option 2: Without UI (API-only deployment)** If you don't need the admin UI, you can run with minimal configuration: @@ -435,7 +354,7 @@ securityContext: The proxy will log a warning about the UI but API endpoints will work normally. -#### Environment Variables for Read-Only Filesystems +Environment variables for read-only filesystems: | Variable | Purpose | Default | |----------|---------|---------| @@ -445,23 +364,38 @@ The proxy will log a warning about the UI but API endpoints will work normally. | `PRISMA_BINARY_CACHE_DIR` | Prisma binary cache | System default | | `XDG_CACHE_HOME` | General cache directory | System default | -#### Important Notes +Notes: always set `LITELLM_MIGRATION_DIR` to a writable emptyDir path, and set `PRISMA_BINARY_CACHE_DIR` and `XDG_CACHE_HOME` to writable paths. If using a custom `server_root_path`, you must pre-process UI files in your Dockerfile as the proxy cannot modify files at runtime with a read-only filesystem. The UI is automatically detected as pre-restructured if it contains a `.litellm_ui_ready` marker file (created by the official Docker images). -1. **Migrations**: Always set `LITELLM_MIGRATION_DIR` to a writable emptyDir path -2. **Prisma Cache**: Set `PRISMA_BINARY_CACHE_DIR` and `XDG_CACHE_HOME` to writable paths -3. **Server Root Path**: If using a custom `server_root_path`, you must pre-process UI files in your Dockerfile as the proxy cannot modify files at runtime with read-only filesystem -4. **Automatic Detection**: The UI is automatically detected as pre-restructured if it contains a `.litellm_ui_ready` marker file (created by the official Docker images) +## Verify production readiness -## Extras -### Expected Performance in Production +### Expected performance -See benchmarks [here](../benchmarks#performance-metrics) +See benchmarks [here](../benchmarks#performance-metrics). -### Verifying Debugging logs are off +### Confirm debug logging is off + +You should only see the following level of details in logs on the proxy server: -You should only see the following level of details in logs on the proxy server ```shell # INFO: 192.168.2.205:11774 - "POST /chat/completions HTTP/1.1" 200 OK # INFO: 192.168.2.205:34717 - "POST /chat/completions HTTP/1.1" 200 OK # INFO: 192.168.2.205:29734 - "POST /chat/completions HTTP/1.1" 200 OK ``` + +## Deployment FAQ + +**Q: Is Postgres the only supported database, or do you support other ones (like Mongo)?** + +A: We explored MySQL but that was hard to maintain and led to bugs for customers. Currently, PostgreSQL is our primary supported database for production deployments. + +Because LiteLLM talks to the database through Prisma over the PostgreSQL wire protocol, any Postgres-wire-compatible distributed SQL database works as a drop-in replacement. [YugabyteDB](https://www.yugabyte.com/) is used in production this way; point `DATABASE_URL` at its YSQL endpoint (`postgresql://:@:/`) and LiteLLM runs its migrations and queries unchanged. This is a good fit if you need horizontal scale or multi-region high availability beyond what a single Postgres instance provides. + +**Q: If there is Postgres downtime, how does LiteLLM react? Does it fail-open or is there API downtime?** + +A: You can gracefully handle DB unavailability if it's on your VPC; see [Gracefully handle DB unavailability](#gracefully-handle-db-unavailability) above. + +:::info + +Need help or want dedicated support? Talk to a founder [here](https://enterprise.litellm.ai/demo). + +::: diff --git a/docs/proxy/server_tuning.md b/docs/proxy/server_tuning.md new file mode 100644 index 000000000..5c299e350 --- /dev/null +++ b/docs/proxy/server_tuning.md @@ -0,0 +1,192 @@ +--- +title: Server Tuning +description: Optional deep tuning for the LiteLLM Proxy container; alternative ASGI servers, worker recycling, hitless restarts, TLS, keepalive, and loading config from object storage. +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Server Tuning + +Reach for this page only when the defaults are not enough. Most deployments should run one Uvicorn worker per pod and scale horizontally, as described in the [production checklist](./prod.md#sizing-and-workers). The options below matter when you pack multiple workers into one container, terminate TLS at the proxy, serve HTTP/2, or cannot mount a config file on your host. See the [CLI reference](./cli.md) for every flag. + +## Uvicorn vs. Gunicorn + +LiteLLM Proxy runs on [Uvicorn](https://uvicorn.dev/) by default. Passing `--run_gunicorn` instead starts [Gunicorn](https://gunicorn.org/) as a process manager that supervises [Uvicorn worker processes](https://uvicorn.dev/deployment/#gunicorn) (`uvicorn.workers.UvicornWorker`). In both cases your application code still runs on Uvicorn; the difference is which process manages and recycles the workers. + +| | Uvicorn (default) | Gunicorn (`--run_gunicorn`) | +|---|---|---| +| **When to use** | Recommended for almost all deployments, especially Kubernetes with one worker per pod. | Choose when you run **multiple workers in a single container** and want a mature process manager to supervise and recycle them. | +| **Worker recycling** | Uvicorn's [`limit_max_requests`](https://uvicorn.dev/settings/#resource-limits). | Gunicorn's [`max_requests`](https://gunicorn.org/reference/settings/#max_requests), the battle-tested mechanism Gunicorn has shipped for years. | +| **Process supervision** | Uvicorn's built-in multiprocess manager. | Gunicorn's [arbiter](https://gunicorn.org/design/#arbiter), which restarts workers one at a time as they exit. | + +:::tip Recommendation + +On Kubernetes, run **one Uvicorn worker per pod** and scale **horizontally** (more pods) rather than vertically (more workers per pod). One process per pod keeps latency predictable under load, lets the Horizontal Pod Autoscaler use the [thresholds in the production checklist](./prod.md#machine-specifications) accurately, and makes rolling restarts hitless because Kubernetes drains one pod at a time. Reach for Gunicorn only when you must pack multiple workers into one container. + +::: + +### Recycle workers + +If you observe gradual memory growth under sustained load, recycle each worker after a fixed number of requests to bound memory usage. `--max_requests_before_restart` maps to Uvicorn's [`limit_max_requests`](https://uvicorn.dev/settings/#resource-limits) (default server) and to Gunicorn's [`max_requests`](https://gunicorn.org/reference/settings/#max_requests) under `--run_gunicorn`. Configure it via CLI flag or environment variable: + +```shell +# CLI +CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "1", "--max_requests_before_restart", "10000"] + +# or ENV (for deployment manifests / containers) +export MAX_REQUESTS_BEFORE_RESTART=10000 +``` + +:::tip + +When you run **multiple workers in one container** and rely on `--max_requests_before_restart`, prefer `--run_gunicorn`. Gunicorn's [`max_requests`](https://gunicorn.org/reference/settings/#max_requests) recycling is more mature than Uvicorn's, and its [arbiter](https://gunicorn.org/design/#arbiter) restarts workers one at a time so the pod keeps serving traffic while a worker is replaced. + +::: + +```shell +# Multiple workers in one container, with Gunicorn-managed recycling +CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "4", "--run_gunicorn", "--max_requests_before_restart", "10000"] +``` + +When several workers boot together and serve a similar amount of traffic, they reach the request threshold at almost the same time and recycle in lockstep, dropping a chunk of capacity at once. Add `--max_requests_before_restart_jitter` to offset each worker's threshold by a random amount in `[0, jitter]` so restarts stagger instead of synchronizing. It maps to Uvicorn's [`limit_max_requests_jitter`](https://uvicorn.dev/settings/#resource-limits) (requires `uvicorn>=0.41.0`) and Gunicorn's [`max_requests_jitter`](https://gunicorn.org/reference/settings/#max_requests_jitter), and has no effect without `--max_requests_before_restart`. + +```shell +# Stagger recycling so workers don't all restart at once +CMD ["--port", "4000", "--config", "./proxy_server_config.yaml", "--num_workers", "4", "--run_gunicorn", "--max_requests_before_restart", "10000", "--max_requests_before_restart_jitter", "1000"] +``` + +### Keep restarts hitless + +A restart is "hitless" when in-flight requests finish before the process exits, so no client sees a dropped connection. Two cases matter in production: + +**Worker recycling (from `--max_requests_before_restart`).** Both servers stop accepting new connections on the recycled worker and let outstanding requests drain before it exits, then a replacement worker starts. Gunicorn additionally guarantees in-flight requests up to its [`graceful_timeout`](https://gunicorn.org/reference/settings/#graceful_timeout) (30s by default) on [`SIGTERM`](https://gunicorn.org/signals/). With one worker per pod, recycling briefly reduces that pod's capacity, which is why we recommend scaling horizontally so the load balancer can route around it. + +**Rolling deploys and pod restarts (Kubernetes).** Make restarts hitless at the orchestration layer rather than relying on the server alone: + +- Use a [`RollingUpdate`](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-update-deployment) strategy (the Deployment default) so new pods become Ready before old pods are terminated. +- Keep a [readiness probe](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/) on `/health/readiness` so Kubernetes only sends traffic to pods that can serve it, and stops routing to a pod as soon as termination begins. +- Set [`terminationGracePeriodSeconds`](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination) to comfortably exceed your longest expected request (LiteLLM's request timeout defaults to 600s; see the [recommended config](./prod.md#set-a-request-timeout)). On termination Kubernetes sends `SIGTERM`, and both Uvicorn and Gunicorn shut down [gracefully](https://uvicorn.dev/deployment/) by draining in-flight requests before exiting. +- Optionally add a small [`preStop` hook](https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks) (for example `sleep 5`) to give the load balancer time to deregister the pod before the server begins shutting down, eliminating the brief window where traffic can still arrive at a terminating pod. + +```yaml title="Kubernetes Deployment snippet for hitless rolling restarts" +spec: + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 # never drop below desired replica count + maxSurge: 1 # add one new pod at a time + template: + spec: + terminationGracePeriodSeconds: 620 # > your longest request (request_timeout: 600) + containers: + - name: litellm + readinessProbe: + httpGet: + path: /health/readiness + port: 4000 + lifecycle: + preStop: + exec: + command: ["sh", "-c", "sleep 5"] +``` + +## TLS at the proxy + +For TLS terminated by the proxy itself (rather than your load balancer), pass the key and cert paths: + +```shell +docker run docker.litellm.ai/berriai/litellm:latest \ + --ssl_keyfile_path ssl_test/keyfile.key \ + --ssl_certfile_path ssl_test/certfile.crt +``` + +## HTTP/2 with Hypercorn + +To serve HTTP/2, build an image with hypercorn installed and pass `--run_hypercorn`: + +```shell +FROM docker.litellm.ai/berriai/litellm:latest +WORKDIR /app +COPY config.yaml . +RUN chmod +x ./docker/entrypoint.sh +EXPOSE 4000/tcp +RUN uv add hypercorn +CMD ["--port", "4000", "--config", "config.yaml"] +``` + +```shell +docker run \ + -v $(pwd)/proxy_config.yaml:/app/config.yaml \ + -p 4000:4000 \ + -e DATABASE_URL=postgresql://:@:/ \ + -e LITELLM_MASTER_KEY="sk-1234" \ + your_custom_docker_image \ + --config /app/config.yaml \ + --run_hypercorn +``` + +## Granian ASGI server [Beta] + +:::info Beta feature +`--run_granian` is in **beta**. Uvicorn is still the default server. Try Granian when you need more gateway throughput or see instability under load with uvicorn; report issues on [GitHub](https://github.com/BerriAI/litellm/issues). +::: + +[Granian](https://github.com/emmett-framework/granian) is a Rust-backed ASGI server. In LiteLLM benchmarks it showed a 10 to 20 RPS improvement over uvicorn with the same worker count, steadier latency under sustained load, and lower error rates (see [PR #26027](https://github.com/BerriAI/litellm/pull/26027)). Scale throughput with `--num_workers`. + +```shell +docker run docker.litellm.ai/berriai/litellm:latest \ + --config /app/config.yaml \ + --port 4000 \ + --run_granian \ + --num_workers 4 +``` + +Both `--ssl_certfile_path` and `--ssl_keyfile_path` are required when enabling TLS with Granian. Not supported with Granian: `--max_requests_before_restart` (use Gunicorn for per-request worker recycling) and `--ciphers` (Hypercorn only). See [CLI server backend options](/docs/proxy/cli#server-backend-options). + +## Keepalive timeout + +Defaults to 5 seconds; between requests, connections must receive new data within this period or be disconnected. + +```shell +docker run docker.litellm.ai/berriai/litellm:latest \ + --keepalive_timeout 75 +``` + +Or set `KEEPALIVE_TIMEOUT=75` as an env var. + +## Load config.yaml from S3 or GCS + +Use this if you cannot mount a config file on your deployment service (AWS Fargate, Railway, etc.). LiteLLM reads `config.yaml` from the bucket at startup. + + + + +```shell +docker run --name litellm-proxy \ + -e DATABASE_URL= \ + -e LITELLM_CONFIG_BUCKET_TYPE="gcs" \ + -e LITELLM_CONFIG_BUCKET_NAME="litellm-proxy" \ + -e LITELLM_CONFIG_BUCKET_OBJECT_KEY="proxy_config.yaml" \ + -p 4000:4000 \ + docker.litellm.ai/berriai/litellm-database:latest +``` + + + + +```shell +docker run --name litellm-proxy \ + -e DATABASE_URL= \ + -e LITELLM_CONFIG_BUCKET_NAME="litellm-proxy" \ + -e LITELLM_CONFIG_BUCKET_OBJECT_KEY="litellm_proxy_config.yaml" \ + -p 4000:4000 \ + docker.litellm.ai/berriai/litellm-database:latest +``` + + + + +## Disable pulling live model prices + +Set `LITELLM_LOCAL_MODEL_COST_MAP="True"` to use the bundled [model prices file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) instead of fetching it at startup, if you see long cold starts or have network egress restrictions. diff --git a/docs/proxy/shared_health_check.md b/docs/proxy/shared_health_check.md index c9c975c79..ddfe45f1d 100644 --- a/docs/proxy/shared_health_check.md +++ b/docs/proxy/shared_health_check.md @@ -307,4 +307,4 @@ general_settings: - [Background Health Checks](./health.md#background-health-checks) - [Redis Caching](./caching.md) - [High Availability Setup](./db_deadlocks.md) -- [Health Check Endpoints](./health.md#health-endpoints) +- [Health Check Endpoints](./health.md#other-health-endpoints) diff --git a/docs/proxy/spend_logs_deletion.md b/docs/proxy/spend_logs_deletion.md index 24f30a0e5..ffe11ad50 100644 --- a/docs/proxy/spend_logs_deletion.md +++ b/docs/proxy/spend_logs_deletion.md @@ -108,7 +108,7 @@ This would allow up to 200,000 logs to be deleted in one run. At high request volume (millions of rows per day), retention via `DELETE` becomes a problem. Deleting rows does not return disk to the operating system; it leaves dead tuples ("tombstones") that autovacuum has to reclaim later. When writes outpace autovacuum, the table keeps growing on disk even though the logical row count is bounded, and `LiteLLM_SpendLogs` can reach hundreds of GB in a month. -The fix is native Postgres range partitioning on `startTime`. With a partitioned table, retention drops whole partitions with `DROP TABLE`, an instant metadata operation that frees disk immediately, with no tombstones and no vacuum. When LiteLLM detects that `LiteLLM_SpendLogs` is partitioned, the same cleanup job automatically switches from batched deletes to dropping expired partitions, and it pre-creates upcoming partitions on each run so writes always have a partition to land in. +The fix is native Postgres range partitioning on `startTime`. With a partitioned table, retention drops whole partitions with `DROP TABLE`, an instant metadata operation that frees disk immediately, with no tombstones and no vacuum. With `general_settings.use_spend_logs_partitioning: true` set and the table actually partitioned, the same cleanup job switches from batched deletes to dropping expired partitions, and it pre-creates upcoming partitions on each run so writes always have a partition to land in; both conditions are required, detection alone does not flip the behavior. This is opt-in. The default schema is not partitioned, so existing deployments are unaffected until you convert the table. diff --git a/docs/proxy/ui_credentials.md b/docs/proxy/ui_credentials.md deleted file mode 100644 index f10f2631f..000000000 --- a/docs/proxy/ui_credentials.md +++ /dev/null @@ -1,59 +0,0 @@ -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Adding LLM Credentials - -You can add LLM provider credentials on the UI. Once you add credentials you can reuse them when adding new models - -## Add a credential + model - -### 1. Navigate to LLM Credentials page - -Go to Models -> LLM Credentials -> Add Credential - - - -### 2. Add credentials - -Select your LLM provider, enter your API Key and click "Add Credential" - -**Note: Credentials are based on the provider, if you select Vertex AI then you will see `Vertex Project`, `Vertex Location` and `Vertex Credentials` fields** - - - - -### 3. Use credentials when adding a model - -Go to Add Model -> Existing Credentials -> Select your credential in the dropdown - - - - -## Create a Credential from an existing model - -Use this if you have already created a model and want to store the model credentials for future use - -### 1. Select model to create a credential from - -Go to Models -> Select your model -> Credential -> Create Credential - - - -### 2. Use new credential when adding a model - -Go to Add Model -> Existing Credentials -> Select your credential in the dropdown - - - -## Usage Tracking - -Models attached to a reusable credential are automatically tracked in the Usage page. Each request is tagged `Credential: ` and appears in the **Tag** view, so you can filter spend and usage by credential without any extra configuration. See [Credential Usage Tracking](./credential_usage_tracking.md) for details. - -## Frequently Asked Questions - - -How are credentials stored? -Credentials in the DB are encrypted/decrypted using `LITELLM_SALT_KEY`, if set. If not, then they are encrypted using `LITELLM_MASTER_KEY`. These keys should be kept secret and not shared with others. - - diff --git a/docs/proxy/ui_store_model_db_setting.md b/docs/proxy/ui_store_model_db_setting.md deleted file mode 100644 index 4b0bc690f..000000000 --- a/docs/proxy/ui_store_model_db_setting.md +++ /dev/null @@ -1,92 +0,0 @@ -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Store Model in DB Settings - -Enable or disable storing model definitions in the database directly from the Admin UI—no config file edits or proxy restart required. This is especially useful for cloud deployments where updating the config is difficult or requires a long release process. - -## Overview - -Previously, the `store_model_in_db` setting had to be configured in `proxy_config.yaml` under `general_settings`. Changing it required editing the config and restarting the proxy, which was problematic for cloud users who don't have direct access to the config file or who want to avoid the downtime caused by restarts. - - - -**Store Model in DB Settings** lets you: - -- **Enable or disable storing models in the database** – Control whether model definitions are cached in your database (useful for reducing config file size and improving scalability) -- **Apply changes immediately** – No proxy restart needed; settings take effect for new model operations as soon as you save - -:::warning UI overrides config -Settings changed in the UI **override** the values in your config file. For example, if `store_model_in_db` is set to `false` in `general_settings`, enabling it in the UI will still persist model definitions to the database. Use the UI when you want runtime control without redeploying. -::: - -## How Store Model in DB Works - -When `store_model_in_db` is enabled, the LiteLLM proxy stores model definitions in the database instead of relying solely on your `proxy_config.yaml`. This provides several benefits: - -- **Reduced config size** – Move model definitions out of YAML for easier maintenance -- **Scalability** – Database storage scales better than large YAML files -- **Dynamic updates** – Models can be added or updated without editing config files -- **Persistence** – Model definitions persist across proxy instances and restarts - -The setting applies to all new model operations from the moment you save it. - -## How to Configure Store Model in DB in the UI - -### 1. Access Models + Endpoints Settings - -Navigate to the Admin UI (e.g. `http://localhost:4000/ui` or your `PROXY_BASE_URL/ui`) and go to the **Models + Endpoints** page. - -![](https://colony-recorder.s3.amazonaws.com/files/2026-02-22/55bc71f5-730f-4b2c-8539-8a4f46b8bd10/ascreenshot_0f7ba8f1c2694e94938996fd1b4adfcc_text_export.jpeg) - -### 2. Open Settings - -Click **Models + Endpoints** from the navigation menu. - -![](https://colony-recorder.s3.amazonaws.com/files/2026-02-22/55bc71f5-730f-4b2c-8539-8a4f46b8bd10/ascreenshot_fc2b9e4812a9480087f4eb350fa0a792_text_export.jpeg) - -### 3. Click the Settings Icon - -Look for the settings (gear) icon on the Models + Endpoints page to open the configuration panel. - -![](https://colony-recorder.s3.amazonaws.com/files/2026-02-22/7b394364-c281-4db8-8cad-ee322c76c935/ascreenshot_d7c8a6b234bc4e4d92aa7f09aefb13d3_text_export.jpeg) - -### 4. Enable or Disable Store Model in DB - -Toggle the **Store Model in DB** setting based on your preference: - -- **Enabled**: Model definitions will be stored in the database -- **Disabled**: Models are read from the config file only - -![](https://colony-recorder.s3.amazonaws.com/files/2026-02-22/54a263ec-ad67-4b16-ba9f-2be57c3e4cb8/ascreenshot_501abda2a6c847f79d085efce814265d_text_export.jpeg) - -### 5. Save Settings - -Click **Save Settings** to apply the change. No proxy restart is required; the new setting takes effect immediately for subsequent model operations. - -![](https://colony-recorder.s3.amazonaws.com/files/2026-02-22/7d13559a-d4e4-41f7-993b-cb20fbfa1f6e/ascreenshot_3245f3c5bd0d43cb96c5f5ff0ccb461d_text_export.jpeg) - -## Use Cases - -### Cloud and Managed Deployments - -When the proxy runs in a managed or cloud environment, config may be in a separate repo, require a long release cycle, or be controlled by another team. Using the UI lets you change the `store_model_in_db` setting without going through a deployment process. - -### Reducing Configuration Complexity - -For large deployments with hundreds of models, storing model definitions in the database reduces the size and complexity of your `proxy_config.yaml`, making it easier to maintain and version control. - -### Dynamic Model Management - -Enable `store_model_in_db` to support dynamic model additions and updates without editing your config file. Teams can manage models through the UI or API without needing to redeploy the proxy. - -### Zero-Downtime Updates - -Change the setting from the UI and have it take effect immediately—perfect for production environments where downtime must be minimized. - -## Related Documentation - -- [Admin UI Overview](./ui.md) – General guide to the LiteLLM Admin UI -- [Models and Endpoints](./model_management.md) – Managing models and API endpoints -- [Config Settings](./config_settings.md) – `store_model_in_db` in `general_settings` diff --git a/docs/proxy/user_management_heirarchy.md b/docs/proxy/user_management_heirarchy.md deleted file mode 100644 index 21b0aa63b..000000000 --- a/docs/proxy/user_management_heirarchy.md +++ /dev/null @@ -1,19 +0,0 @@ -import Image from '@theme/IdealImage'; - - -# User Management Hierarchy - - - -LiteLLM supports a hierarchy of users, teams, organizations, and budgets. - -- Organizations can have multiple teams. [API Reference](https://litellm-api.up.railway.app/#/organization%20management) -- Teams can have multiple users. [API Reference](https://litellm-api.up.railway.app/#/team%20management) -- Users can have multiple keys, and be on multiple teams. [API Reference](https://litellm-api.up.railway.app/#/budget%20management) -- Keys can belong to either a team or a user. [API Reference](https://litellm-api.up.railway.app/#/end-user%20management) - - -:::info - -See [Access Control](./access_control) for more details on roles and permissions. -::: \ No newline at end of file diff --git a/docs/proxy/virtual_keys.md b/docs/proxy/virtual_keys.md index c74aa75ff..309d5876d 100644 --- a/docs/proxy/virtual_keys.md +++ b/docs/proxy/virtual_keys.md @@ -8,7 +8,7 @@ Track Spend, and control model access via virtual keys for the proxy :::info - 🔑 [UI to Generate, Edit, Delete Keys (with SSO)](https://docs.litellm.ai/docs/proxy/ui) -- [Deploy LiteLLM Proxy with Key Management](https://docs.litellm.ai/docs/proxy/deploy#deploy-with-database) +- [Deploy LiteLLM Proxy with Key Management](https://docs.litellm.ai/docs/proxy/deploy#provision-the-data-stores) - [Dockerfile.database for LiteLLM Proxy + Key Management](https://github.com/BerriAI/litellm/blob/main/docker/Dockerfile.database) diff --git a/docs/router_architecture.md b/docs/router_architecture.md deleted file mode 100644 index 13e9e411c..000000000 --- a/docs/router_architecture.md +++ /dev/null @@ -1,24 +0,0 @@ -import Image from '@theme/IdealImage'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Router Architecture (Fallbacks / Retries) - -## High Level architecture - - - -### Request Flow - -1. **User Sends Request**: The process begins when a user sends a request to the LiteLLM Router endpoint. All unified endpoints (`.completion`, `.embeddings`, etc) are supported by LiteLLM Router. - -2. **function_with_fallbacks**: The initial request is sent to the `function_with_fallbacks` function. This function wraps the initial request in a try-except block, to handle any exceptions - doing fallbacks if needed. This request is then sent to the `function_with_retries` function. - - -3. **function_with_retries**: The `function_with_retries` function wraps the request in a try-except block and passes the initial request to a base litellm unified function (`litellm.completion`, `litellm.embeddings`, etc) to handle LLM API calling. `function_with_retries` handles any exceptions - doing retries on the model group if needed (i.e. if the request fails, it will retry on an available model within the model group). - -4. **litellm.completion**: The `litellm.completion` function is a base function that handles the LLM API calling. It is used by `function_with_retries` to make the actual request to the LLM API. - -## Legend - -**model_group**: A group of LLM API deployments that share the same `model_name`, are part of the same `model_group`, and can be load balanced across. \ No newline at end of file diff --git a/docs/troubleshoot/rollback.md b/docs/troubleshoot/rollback.md index 26f16d5c4..ccc801ffc 100644 --- a/docs/troubleshoot/rollback.md +++ b/docs/troubleshoot/rollback.md @@ -26,9 +26,9 @@ If you are on a managed database (e.g., AWS RDS, GCP Cloud SQL), create a snapsh Before reverting, review these items: -- **`LITELLM_SALT_KEY`**: Do **not** change this value during rollback. It is used to encrypt/decrypt your LLM API Key credentials stored in the database. Changing it will make existing credentials unreadable. See [Best Practices for Production](../proxy/prod#8-set-litellm-salt-key). +- **`LITELLM_SALT_KEY`**: Do **not** change this value during rollback. It is used to encrypt/decrypt your LLM API Key credentials stored in the database. Changing it will make existing credentials unreadable. See [Best Practices for Production](../proxy/prod#set-the-salt-key). - **`config.yaml`**: If you added settings specific to the newer version, the older version may not recognize them. Review your config and remove or comment out any settings that were introduced in the version you are rolling back from. -- **`DISABLE_SCHEMA_UPDATE`**: If you use the [Helm PreSync hook for migrations](../proxy/prod#7-use-helm-presync-hook-for-database-migrations-beta) with `DISABLE_SCHEMA_UPDATE=true` on your pods, migrations will **not** auto-run on restart. You will need to handle migration cleanup manually (see Step 5) or re-run the PreSync hook against the older chart version. +- **`DISABLE_SCHEMA_UPDATE`**: If you use the [Helm PreSync hook for migrations](../proxy/prod#run-migrations-from-the-helm-presync-hook) with `DISABLE_SCHEMA_UPDATE=true` on your pods, migrations will **not** auto-run on restart. You will need to handle migration cleanup manually (see Step 5) or re-run the PreSync hook against the older chart version. ## 4. Revert Application Version @@ -53,7 +53,7 @@ helm rollback [revision-number] If you are rolling back to a version that did not have a specific migration, you may need to resolve the migration state in the database. -> LiteLLM uses `prisma migrate deploy` for production (enabled via `USE_PRISMA_MIGRATE=True`). If a migration partially failed or you are reverting code that expects an older schema, you need to clean up the migration history in the `_prisma_migrations` table. See [Best Practices for Production](../proxy/prod#9-use-prisma-migrate-deploy). +> LiteLLM uses `prisma migrate deploy` for production (enabled via `USE_PRISMA_MIGRATE=True`). If a migration partially failed or you are reverting code that expects an older schema, you need to clean up the migration history in the `_prisma_migrations` table. See [Best Practices for Production](../proxy/prod#use-prisma-migrate-deploy). ### Option A — Delete stale migration entries (recommended) diff --git a/docs/tutorials/openweb_ui.md b/docs/tutorials/openweb_ui.md index 38f1ec382..f6d314f0a 100644 --- a/docs/tutorials/openweb_ui.md +++ b/docs/tutorials/openweb_ui.md @@ -34,7 +34,7 @@ On LiteLLM, you can create Organizations, Teams, Users and Virtual Keys. For thi - `User` - A User is an individual user (employee, developer, eg. `krrish@litellm.ai`) - `Virtual Key` - A Virtual Key is an API Key that allows you to authenticate to LiteLLM Proxy. A Virtual Key is associated with a User or Team. -Once the Team is created, you can invite Users to the Team. You can read more about LiteLLM's User Management [here](https://docs.litellm.ai/docs/proxy/user_management_heirarchy). +Once the Team is created, you can invite Users to the Team. You can read more about LiteLLM's User Management [here](https://docs.litellm.ai/docs/proxy/multi_tenant_architecture#the-tenancy-hierarchy). ### 2.2 Create a Team on LiteLLM diff --git a/docusaurus.config.js b/docusaurus.config.js index e2dcbf41e..3ae03fc6d 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -95,6 +95,34 @@ const config = { from: '/docs/proxy/control_plane_and_data_plane', to: '/docs/proxy/multi_region', }, + { + from: '/docs/proxy/deploy_cloud', + to: '/docs/proxy/deploy', + }, + { + from: '/docs/proxy/microservices_helm', + to: '/docs/proxy/deploy#deploy-with-helm', + }, + { + from: '/docs/proxy/ui_credentials', + to: '/docs/proxy/model_management#reusable-provider-credentials', + }, + { + from: '/docs/proxy/ui_store_model_db_setting', + to: '/docs/proxy/model_management#database-vs-configyaml-models', + }, + { + from: '/docs/router_architecture', + to: '/docs/proxy/architecture#the-router-fallbacks-and-retries', + }, + { + from: '/docs/proxy/image_handling', + to: '/docs/proxy/architecture#image-url-handling', + }, + { + from: '/docs/proxy/user_management_heirarchy', + to: '/docs/proxy/multi_tenant_architecture#the-tenancy-hierarchy', + }, ], }, ], diff --git a/img/image_handling.png b/img/image_handling.png deleted file mode 100644 index bd5620691..000000000 Binary files a/img/image_handling.png and /dev/null differ diff --git a/img/litellm_gateway.png b/img/litellm_gateway.png deleted file mode 100644 index f453a2bf9..000000000 Binary files a/img/litellm_gateway.png and /dev/null differ diff --git a/img/litellm_user_heirarchy.png b/img/litellm_user_heirarchy.png deleted file mode 100644 index 591b36add..000000000 Binary files a/img/litellm_user_heirarchy.png and /dev/null differ diff --git a/img/router_architecture.png b/img/router_architecture.png deleted file mode 100644 index 195834185..000000000 Binary files a/img/router_architecture.png and /dev/null differ diff --git a/img/ui_add_credential.png b/img/ui_add_credential.png new file mode 100644 index 000000000..e2a61659b Binary files /dev/null and b/img/ui_add_credential.png differ diff --git a/img/ui_add_model_form.png b/img/ui_add_model_form.png deleted file mode 100644 index ad5aaac34..000000000 Binary files a/img/ui_add_model_form.png and /dev/null differ diff --git a/img/ui_alerting_types.png b/img/ui_alerting_types.png new file mode 100644 index 000000000..2a2db8d09 Binary files /dev/null and b/img/ui_alerting_types.png differ diff --git a/img/ui_create_key_flow.gif b/img/ui_create_key_flow.gif deleted file mode 100644 index 97c5e6a12..000000000 Binary files a/img/ui_create_key_flow.gif and /dev/null differ diff --git a/img/ui_create_key_modal.png b/img/ui_create_key_modal.png deleted file mode 100644 index e6e44f3ef..000000000 Binary files a/img/ui_create_key_modal.png and /dev/null differ diff --git a/img/ui_health_status.png b/img/ui_health_status.png new file mode 100644 index 000000000..354ed103e Binary files /dev/null and b/img/ui_health_status.png differ diff --git a/img/ui_model_detail.png b/img/ui_model_detail.png new file mode 100644 index 000000000..56df2439e Binary files /dev/null and b/img/ui_model_detail.png differ diff --git a/img/ui_models_table.png b/img/ui_models_table.png new file mode 100644 index 000000000..45f84876b Binary files /dev/null and b/img/ui_models_table.png differ diff --git a/img/ui_quickstart_add_model.png b/img/ui_quickstart_add_model.png new file mode 100644 index 000000000..488767f47 Binary files /dev/null and b/img/ui_quickstart_add_model.png differ diff --git a/img/ui_quickstart_create_key.png b/img/ui_quickstart_create_key.png new file mode 100644 index 000000000..d4ff41c17 Binary files /dev/null and b/img/ui_quickstart_create_key.png differ diff --git a/img/ui_quickstart_flow.gif b/img/ui_quickstart_flow.gif new file mode 100644 index 000000000..efac124d5 Binary files /dev/null and b/img/ui_quickstart_flow.gif differ diff --git a/img/ui_quickstart_login.png b/img/ui_quickstart_login.png new file mode 100644 index 000000000..b776acccd Binary files /dev/null and b/img/ui_quickstart_login.png differ diff --git a/img/ui_quickstart_models_list.png b/img/ui_quickstart_models_list.png new file mode 100644 index 000000000..b8ac699e2 Binary files /dev/null and b/img/ui_quickstart_models_list.png differ diff --git a/img/ui_quickstart_playground.png b/img/ui_quickstart_playground.png new file mode 100644 index 000000000..ff4dcd492 Binary files /dev/null and b/img/ui_quickstart_playground.png differ diff --git a/release_notes/v1.59.8-stable/index.md b/release_notes/v1.59.8-stable/index.md index 023f284ad..e9f7dd678 100644 --- a/release_notes/v1.59.8-stable/index.md +++ b/release_notes/v1.59.8-stable/index.md @@ -125,8 +125,8 @@ Get a 7 day free trial for LiteLLM Enterprise [here](https://litellm.ai/#trial). 1. Cleanup pricing-only model names from wildcard route list - prevent bad health checks 2. Allow specifying a health check model for wildcard routes - https://docs.litellm.ai/docs/proxy/health#wildcard-routes -3. New ‘health_check_timeout ‘ param with default 1min upperbound to prevent bad model from health check to hang and cause pod restarts. [Start Here](../../docs/proxy/health#health-check-timeout) -4. Datadog - add data dog service health check + expose new `/health/services` endpoint. [Start Here](../../docs/proxy/health#healthservices) +3. New ‘health_check_timeout ‘ param with default 1min upperbound to prevent bad model from health check to hang and cause pod restarts. [Start Here](../../docs/proxy/health#health-check-tuning-reference) +4. Datadog - add data dog service health check + expose new `/health/services` endpoint. [Start Here](../../docs/proxy/health#other-health-endpoints) ## Performance / Reliability improvements diff --git a/release_notes/v1.63.11-stable/index.md b/release_notes/v1.63.11-stable/index.md index 3273f9a8e..0de7647dc 100644 --- a/release_notes/v1.63.11-stable/index.md +++ b/release_notes/v1.63.11-stable/index.md @@ -103,7 +103,7 @@ Here's a Demo Instance to test changes: ### Re-Use Credentials on UI -You can now onboard LLM provider credentials on LiteLLM UI. Once these credentials are added you can re-use them when adding new models [Getting Started](https://docs.litellm.ai/docs/proxy/ui_credentials) +You can now onboard LLM provider credentials on LiteLLM UI. Once these credentials are added you can re-use them when adding new models [Getting Started](https://docs.litellm.ai/docs/proxy/model_management#reusable-provider-credentials) diff --git a/release_notes/v1.63.14/index.md b/release_notes/v1.63.14/index.md index d34b2c7b3..88531196f 100644 --- a/release_notes/v1.63.14/index.md +++ b/release_notes/v1.63.14/index.md @@ -121,7 +121,7 @@ Here's a Demo Instance to test changes: - Passthrough Endpoints - support returning api-base on pass-through endpoints Response Headers [Docs](../../docs/proxy/response_headers#litellm-specific-headers) - SSL - support reading ssl security level from env var - Allows user to specify lower security settings [Get Started](../../docs/guides/security_settings) - Credentials - only poll Credentials table when `STORE_MODEL_IN_DB` is True [PR](https://github.com/BerriAI/litellm/pull/9376) -- Image URL Handling - new architecture doc on image url handling [Docs](../../docs/proxy/image_handling) +- Image URL Handling - new architecture doc on image url handling [Docs](../../docs/proxy/architecture#image-url-handling) - OpenAI - bump to pip install "openai==1.68.2" [PR](https://github.com/BerriAI/litellm/commit/e85e3bc52a9de86ad85c3dbb12d87664ee567a5a) - Gunicorn - security fix - bump gunicorn==23.0.0 [PR](https://github.com/BerriAI/litellm/commit/7e9fc92f5c7fea1e7294171cd3859d55384166eb) diff --git a/release_notes/v1.65.4-stable/index.md b/release_notes/v1.65.4-stable/index.md index 80d703e11..27cc9263a 100644 --- a/release_notes/v1.65.4-stable/index.md +++ b/release_notes/v1.65.4-stable/index.md @@ -151,7 +151,7 @@ To test this out, just go to Experimental > New Usage > Activity. - Use Redis for PodLock Manager instead of PG (ensures no deadlocks occur) [PR](https://github.com/BerriAI/litellm/pull/9715) - v2 DB Deadlock Reduction Architecture – Add Max Size for In-Memory Queue + Backpressure Mechanism [PR](https://github.com/BerriAI/litellm/pull/9759) -2. Prisma Migrations [Get Started](../../docs/proxy/prod#9-use-prisma-migrate-deploy) +2. Prisma Migrations [Get Started](../../docs/proxy/prod#use-prisma-migrate-deploy) - connects litellm proxy to litellm's prisma migration files - Handle db schema updates from new `litellm-proxy-extras` sdk 3. Redis - support password for sync sentinel clients [PR](https://github.com/BerriAI/litellm/pull/9622) diff --git a/release_notes/v1.81.14/index.md b/release_notes/v1.81.14/index.md index 92c22bc0e..ea69122a8 100644 --- a/release_notes/v1.81.14/index.md +++ b/release_notes/v1.81.14/index.md @@ -45,7 +45,7 @@ pip install litellm==1.81.14 - **Guardrail Garden** — [Browse built-in and partner guardrails by use case — competitor blocking, topic filtering, GDPR, prompt injection, and more. Pick a template, customize it, attach it to a team or key.](../../docs/proxy/guardrails/policy_templates) - **Compliance Playground** — [Test any guardrail policy against your own traffic before it goes live. See precision, recall, and false positive rate — so you know how it'll behave in production.](../../docs/proxy/guardrails/policy_templates) - **3 new zero-cost built-in guardrails** — [Competitor name blocker, topic blocker, and insults filter — all gateway-level, <0.1ms latency, no external API, configurable per-team or key](../../docs/proxy/guardrails) -- **Store Model in DB Settings via UI** - [Configure model storage directly in the Admin UI without editing config files or restarting the proxy—perfect for cloud deployments](../../docs/proxy/ui_store_model_db_setting) +- **Store Model in DB Settings via UI** - [Configure model storage directly in the Admin UI without editing config files or restarting the proxy—perfect for cloud deployments](../../docs/proxy/model_management#database-vs-configyaml-models) - **Claude Sonnet 4.6 — day 0** — [Full support across Anthropic and Vertex AI: reasoning, computer use, prompt caching, 200K context](../../docs/providers/anthropic) - **20+ performance optimizations** — Faster routing, lower logging overhead, reduced cost-calculator latency, and connection pool fixes — meaningfully less CPU and latency on every request diff --git a/release_notes/v1.82.0/index.md b/release_notes/v1.82.0/index.md index 09967d588..27ae7b30d 100644 --- a/release_notes/v1.82.0/index.md +++ b/release_notes/v1.82.0/index.md @@ -42,7 +42,7 @@ pip install litellm==1.82.0 ## Key Highlights - **Realtime API guardrails** — [Full guardrails support for `/v1/realtime` WebSocket sessions with pre/post-call enforcement, voice transcription hooks, session termination policies, and Vertex AI Gemini Live support](../../docs/proxy/guardrails) - [PR #22152](https://github.com/BerriAI/litellm/pull/22152), [PR #22153](https://github.com/BerriAI/litellm/pull/22153), [PR #22161](https://github.com/BerriAI/litellm/pull/22161), [PR #22165](https://github.com/BerriAI/litellm/pull/22165) -- **Projects Management** — [New Projects UI with full CRUD, project-scoped virtual keys, and admin opt-in toggle — organize teams and keys by project](../../docs/proxy/ui_store_model_db_setting) - [PR #22315](https://github.com/BerriAI/litellm/pull/22315), [PR #22360](https://github.com/BerriAI/litellm/pull/22360), [PR #22373](https://github.com/BerriAI/litellm/pull/22373), [PR #22412](https://github.com/BerriAI/litellm/pull/22412) +- **Projects Management** — [New Projects UI with full CRUD, project-scoped virtual keys, and admin opt-in toggle — organize teams and keys by project](../../docs/proxy/model_management#database-vs-configyaml-models) - [PR #22315](https://github.com/BerriAI/litellm/pull/22315), [PR #22360](https://github.com/BerriAI/litellm/pull/22360), [PR #22373](https://github.com/BerriAI/litellm/pull/22373), [PR #22412](https://github.com/BerriAI/litellm/pull/22412) - **Guardrail ecosystem expansion** — [Noma v2, Lakera v2 post-call, Singapore regulatory policies (PDPA + MAS), employment discrimination blockers, code execution blocker, guardrail policy versioning, and production monitoring](../../docs/proxy/guardrails) - [PR #21400](https://github.com/BerriAI/litellm/pull/21400), [PR #21783](https://github.com/BerriAI/litellm/pull/21783), [PR #21948](https://github.com/BerriAI/litellm/pull/21948) - **OpenAI Codex 5.3 — day 0** — [Full support for `gpt-5.3-codex` on OpenAI and Azure, plus `gpt-audio-1.5` and `gpt-realtime-1.5` model coverage](../../docs/providers/openai) - [PR #22035](https://github.com/BerriAI/litellm/pull/22035) - **10+ performance optimizations** — Streaming hot-path fixes, Redis pipeline batching, database task batching, ModelResponse init skip, and router cache improvements — lower latency and CPU on every request diff --git a/release_notes/v1.83.10/index.md b/release_notes/v1.83.10/index.md index b986a88ed..a2d42b5c8 100644 --- a/release_notes/v1.83.10/index.md +++ b/release_notes/v1.83.10/index.md @@ -98,7 +98,7 @@ pip install litellm==1.83.10 - **Who is affected:** Anyone who entered literal `os.environ/SECRET_NAME` strings in the UI or API and expected the proxy to substitute the host environment at runtime. -- **What to use instead:** Provider API keys and similar secrets should be stored with [**Reusable Credentials**](../../docs/proxy/ui_credentials.md) and attached to models (for example via `litellm_credential_name`). For observability callbacks (Langfuse, LangSmith, etc.), set keys and endpoints in proxy `config.yaml` or in environment variables the process reads at startup—not as `os.environ/…` strings inside per-request metadata. +- **What to use instead:** Provider API keys and similar secrets should be stored with [**Reusable Credentials**](../../docs/proxy/model_management#reusable-provider-credentials) and attached to models (for example via `litellm_credential_name`). For observability callbacks (Langfuse, LangSmith, etc.), set keys and endpoints in proxy `config.yaml` or in environment variables the process reads at startup—not as `os.environ/…` strings inside per-request metadata. --- diff --git a/sidebars.js b/sidebars.js index 3ca548938..32885b515 100644 --- a/sidebars.js +++ b/sidebars.js @@ -398,7 +398,7 @@ const sidebars = { slug: "/simple_proxy", }, items: [ - { type: "doc", id: "proxy/docker_quick_start", label: "Getting Started Tutorial" }, + { type: "doc", id: "proxy/docker_quick_start", label: "Docker Quickstart" }, { type: "category", label: "Agent & MCP Gateway", @@ -463,23 +463,28 @@ const sidebars = { type: "category", label: "Setup & Deployment", items: [ - "proxy/quick_start", - "proxy/cli", - "proxy/debugging", - "proxy/error_diagnosis", "proxy/deploy", - "proxy/deploy_cloud", - "proxy/microservices_helm", - "proxy/docker_image_security", - "proxy/health", - "proxy/master_key_rotations", - "proxy/model_management", "proxy/prod", + "proxy/server_tuning", + "proxy/db_deadlocks", "proxy/multi_region", - "proxy/worker_startup_hooks", - "proxy/release_cycle", + "proxy/db_read_replica", + "proxy/high_availability_control_plane", + "proxy/health", + "proxy/model_management", + "proxy/master_key_rotations", ], }, + { + type: "category", + label: "CLI", + items: ["proxy/quick_start", "proxy/cli"], + }, + { + type: "category", + label: "Troubleshooting", + items: ["proxy/debugging", "proxy/error_diagnosis"], + }, { "type": "link", "label": "Demo LiteLLM Cloud", @@ -506,10 +511,8 @@ const sidebars = { type: "category", label: "Models", items: [ - "proxy/ui_credentials", "proxy/ai_hub", "proxy/model_compare_ui", - "proxy/ui_store_model_db_setting", "proxy/ui/routing_groups", ] }, @@ -556,16 +559,8 @@ const sidebars = { items: [ "proxy/architecture", "proxy/multi_tenant_architecture", - "proxy/high_availability_control_plane", - "proxy/db_deadlocks", - "proxy/db_info", - "proxy/db_read_replica", - "proxy/image_handling", "proxy/key_auth_arch", - "proxy/jwt_auth_arch", - "proxy/spend_logs_deletion", - "proxy/user_management_heirarchy", - "router_architecture" + "proxy/db_info", ], }, { @@ -580,6 +575,7 @@ const sidebars = { "proxy/virtual_keys", "proxy/token_auth", "proxy/jwt_key_mapping", + "proxy/jwt_auth_arch", "proxy/service_accounts", "proxy/access_control", "proxy/cli_sso", @@ -653,6 +649,7 @@ const sidebars = { "proxy/call_hooks", "proxy/agentic_loop_hook", "proxy/rules", + "proxy/worker_startup_hooks", ] }, "proxy/management_cli", @@ -727,6 +724,7 @@ const sidebars = { "proxy/provider_discounts", "proxy/sync_models_github", "proxy/billing", + "proxy/spend_logs_deletion", ], }, { @@ -1249,7 +1247,9 @@ const sidebars = { "migration", "data_security", "proxy/security_encryption_faq", + "proxy/docker_image_security", "migration_policy", + "proxy/release_cycle", "load_test_advanced", "load_test_sdk", "load_test_rpm", diff --git a/src/components/CloudArchitecture/ConceptDiagrams.tsx b/src/components/CloudArchitecture/ConceptDiagrams.tsx new file mode 100644 index 000000000..8827ce8ad --- /dev/null +++ b/src/components/CloudArchitecture/ConceptDiagrams.tsx @@ -0,0 +1,295 @@ +import React from 'react'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import styles from './styles.module.css'; + +/* Shared primitives, mirrored from CloudArchitecture.tsx */ + +function Icon({ file, className }: { file: string; className?: string }) { + return ( + + ); +} + +function Clients({ label = 'Clients (OpenAI SDK, LangChain, curl)' }: { label?: string }) { + return ( +
+
+ + + + +
+ {label} +
+ ); +} + +function Node({ + icon, + title, + subtitle, + accent, + small, +}: { + icon: string; + title: string; + subtitle?: string; + accent?: 'blue' | 'green'; + small?: boolean; +}) { + const cls = [ + styles.node, + accent === 'blue' ? styles.nodeAccent : '', + accent === 'green' ? styles.nodeGreen : '', + small ? styles.nodeSmall : '', + ].join(' '); + return ( +
+ +
+ {title} + {subtitle && {subtitle}} +
+
+ ); +} + +function StepNode({ + n, + title, + subtitle, + accent, +}: { + n?: number; + title: string; + subtitle?: string; + accent?: 'blue' | 'green'; +}) { + const cls = [ + styles.node, + styles.nodeSmall, + accent === 'blue' ? styles.nodeAccent : '', + accent === 'green' ? styles.nodeGreen : '', + ].join(' '); + return ( +
+ {n !== undefined && {n}} +
+ {title} + {subtitle && {subtitle}} +
+
+ ); +} + +function PillsNode({ + title, + subtitle, + pills, +}: { + title: string; + subtitle?: string; + pills: string[]; +}) { + return ( +
+
+
+ {title} + {subtitle && {subtitle}} +
+
+
+ {pills.map((p) => ( + + {p} + + ))} +
+
+ ); +} + +function ConnectorDown({ label }: { label?: string }) { + if (!label) return
; + return ( +
+ {label} +
+
+ ); +} + +function Branch({ legs }: { legs: number }) { + const positions = + legs === 2 ? ['30%', '70%'] : legs === 3 ? ['20%', '50%', '80%'] : ['50%']; + return ( +
+
+
+ {positions.map((p) => ( +
+ ))} +
+ ); +} + +function Box({ + name, + badge, + badgeColor, + children, +}: { + name: string; + badge?: string; + badgeColor?: 'blue' | 'green' | 'orange'; + children: React.ReactNode; +}) { + const badgeCls = + badgeColor === 'green' + ? styles.badgeGreen + : badgeColor === 'orange' + ? styles.badgeOrange + : styles.badgeBlue; + return ( +
+
+ {name} + {badge && {badge}} +
+ {children} +
+ ); +} + +/* ────────────────────── Life of a Request ────────────────────── */ + +export function RequestFlowDiagram() { + return ( +
+
+ + + + + + + +
+ + +
+ + + + +
+ + +
+ + After the response is returned to the client, spend logging, rate-limit accounting, and + logging callbacks all run as asynchronous background tasks; no database write sits in + the request path. + +
+
+
+ ); +} + +/* ────────────────────── Router: fallbacks and retries ────────────────────── */ + +export function RouterFlowDiagram() { + return ( +
+
+ + + + + + + + + +
+ + Retries stay inside the model group that failed; fallbacks leave it for the next group + in your fallbacks configuration. + +
+
+
+ ); +} + +/* ────────────────────── Image URL handling ────────────────────── */ + +export function ImageFlowDiagram() { + return ( +
+
+ + + + +
+ + + + + + + + +
+
+
+ ); +} + +/* ────────────────────── Tenancy hierarchy ────────────────────── */ + +export function TenancyDiagram() { + return ( +
+
+ +
+ + + + + + + + + + +
+
+
+ + Every request's spend is attributed to its key, user, team, and organization at once, + and budgets are enforced at each level; a request is blocked when any level on its path + is over budget. Teams are the top-level boundary in open source; Organizations add the + outer layer and are an enterprise feature. + +
+
+
+ ); +} diff --git a/src/components/CloudArchitecture/index.tsx b/src/components/CloudArchitecture/index.tsx index 50c2c2dd1..76a4446ca 100644 --- a/src/components/CloudArchitecture/index.tsx +++ b/src/components/CloudArchitecture/index.tsx @@ -3,3 +3,9 @@ export { CloudArchitectureSelector, MultiRegionArchitecture, } from './CloudArchitecture'; +export { + RequestFlowDiagram, + RouterFlowDiagram, + ImageFlowDiagram, + TenancyDiagram, +} from './ConceptDiagrams'; diff --git a/src/components/CloudArchitecture/styles.module.css b/src/components/CloudArchitecture/styles.module.css index 857672bba..f2b7c2a93 100644 --- a/src/components/CloudArchitecture/styles.module.css +++ b/src/components/CloudArchitecture/styles.module.css @@ -500,3 +500,17 @@ gap: 0.6rem; } } + +.stepChip { + width: 26px; + height: 26px; + border-radius: 50%; + background: var(--ca-accent); + color: #fff; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: 700; + flex-shrink: 0; +}