
LiteLLM Proxy Server est une passerelle API qui unifie l'accès à plus de 100 LLM (OpenAI, Anthropic, Ollama, Azure...) via une interface compatible OpenAI. En entreprise, il résout trois problèmes majeurs : centraliser les clés API, contrôler les coûts (budgets par équipe), et restreindre l'accès (modèles autorisés, rate limits).
Ce guide vous accompagne de l'installation jusqu'à la mise en production. À la fin, vous saurez :
- Déployer un proxy local avec Docker et Ollama
- Créer des utilisateurs, équipes et clés virtuelles
- Limiter l'accès par modèle, budget et rate limit
- Monitorer la consommation en temps réel
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Architecture : comment LiteLLM s'insère entre vos applications et les LLM
- Lab Docker : proxy fonctionnel avec Ollama (gratuit, local)
- Gestion des accès : utilisateurs, équipes, clés virtuelles
- Restrictions : modèles autorisés, budgets, rate limits (RPM/TPM)
- Production : Docker Compose avec PostgreSQL et persistance
Pourquoi LiteLLM Proxy ?
Section intitulée « Pourquoi LiteLLM Proxy ? »Le problème du multi-provider
Section intitulée « Le problème du multi-provider »Sans passerelle, chaque application détient ses propres clés API et les intègre à sa configuration. Le problème n'est pas technique mais organisationnel : personne ne sait combien de clés circulent, ni ce que chacune consomme, ni comment en révoquer une sans redéployer le service qui l'utilise. Le tableau ci-dessous met en regard cette situation et ce qu'apporte une passerelle unique.
| Sans proxy | Avec LiteLLM Proxy |
|---|---|
| Clés API éparpillées dans le code | Une seule clé par équipe |
| Impossible de suivre les coûts | Budget par user/team/clé |
| Dépendance à un fournisseur | Fallback automatique |
| Pas de rate limiting centralisé | RPM/TPM par clé |
Open Source vs Enterprise
Section intitulée « Open Source vs Enterprise »| Fonctionnalité | Open Source | Enterprise (250$/mois) |
|---|---|---|
| 100+ LLM supportés | ✅ | ✅ |
| Clés virtuelles | ✅ | ✅ |
| Budgets & rate limits | ✅ | ✅ |
| Interface web | ✅ | ✅ |
| SSO/OIDC | ❌ | ✅ |
| Métriques Prometheus | ❌ | ✅ |
| Support SLA | ❌ | ✅ |
Lab : proxy local avec Ollama
Section intitulée « Lab : proxy local avec Ollama »Nous allons créer un lab complet sans clé API payante. Ollama exécute les modèles localement, LiteLLM Proxy les expose via une API compatible OpenAI.
Architecture du lab
Section intitulée « Architecture du lab »Trois conteneurs et un service hôte composent le lab. Ollama tourne sur la machine hôte et sert les modèles ; LiteLLM Proxy s'intercale et expose une API compatible OpenAI ; PostgreSQL persiste les clés, les utilisateurs et les compteurs de dépense. Le point à retenir sur le schéma est le sens des flèches : vos applications ne parlent jamais directement au fournisseur de modèles, elles parlent au proxy, qui seul détient les identifiants et applique les quotas.
Prérequis
Section intitulée « Prérequis »- Docker installé
- Ollama installé (ollama.ai)
- 4 Go de RAM disponibles pour les modèles
Étape 1 : Démarrer Ollama
Section intitulée « Étape 1 : Démarrer Ollama »Ollama doit écouter sur toutes les interfaces pour être accessible depuis Docker :
# Arrêter Ollama s'il tournepkill ollama
# Redémarrer en écoutant sur toutes les interfacesOLLAMA_HOST=0.0.0.0 ollama serve &
# Vérifiercurl -s http://localhost:11434/api/tags | jq '.models[].name'Étape 2 : Télécharger des modèles
Section intitulée « Étape 2 : Télécharger des modèles »Deux modèles suffisent pour ce lab, et les prendre très petits est délibéré : l'objectif est de valider le routage, les clés et les quotas, pas la qualité des réponses. qwen2:0.5b tient en 352 Mo et répond en quelques centaines de millisecondes sur un CPU récent, llama3.2:1b sert de second modèle pour vérifier que les restrictions par clé distinguent bien deux cibles différentes.
# Modèle léger pour les tests (352 Mo)ollama pull qwen2:0.5b
# Modèle plus capable (1.3 Go)ollama pull llama3.2:1b
# Vérifier les modèles disponiblesollama listSortie attendue :
NAME ID SIZE MODIFIEDllama3.2:1b baf6a787fdff 1.3 GB 2 minutes agoqwen2:0.5b 6f48b936a09f 352 MB 3 minutes agoÉtape 3 : Créer le fichier de configuration
Section intitulée « Étape 3 : Créer le fichier de configuration »Créez un dossier pour le lab :
mkdir -p ~/Projets/litellm-lab/configcd ~/Projets/litellm-labCréez le fichier config/proxy-config.yaml :
# LiteLLM Proxy Server - Configuration Labmodel_list: # Modèle principal - model_name: llama litellm_params: model: ollama/llama3.2:1b api_base: http://host.docker.internal:11434
# Modèle secondaire (plus rapide) - model_name: qwen litellm_params: model: ollama/qwen2:0.5b api_base: http://host.docker.internal:11434
# Alias pour compatibilité OpenAI - model_name: gpt-3.5-turbo litellm_params: model: ollama/qwen2:0.5b api_base: http://host.docker.internal:11434
- model_name: gpt-4 litellm_params: model: ollama/llama3.2:1b api_base: http://host.docker.internal:11434
general_settings: master_key: os.environ/LITELLM_MASTER_KEY json_logs: true
router_settings: routing_strategy: simple-shuffle num_retries: 2 timeout: 120Étape 4 : Lancer PostgreSQL
Section intitulée « Étape 4 : Lancer PostgreSQL »LiteLLM Proxy démarre sans base de données, mais perd alors toute notion d'utilisateur, de clé virtuelle et de dépense : la gestion des accès nécessite PostgreSQL. Le conteneur est lancé ici avec un mot de passe en clair parce qu'il s'agit d'un lab local ; en production, ce mot de passe vient d'un fichier d'environnement non versionné et le port 5432 n'est pas publié sur l'hôte.
docker run -d --name litellm-postgres \ -e POSTGRES_USER=litellm \ -e POSTGRES_PASSWORD=litellm_secure_pwd \ -e POSTGRES_DB=litellm \ -p 5432:5432 \ postgres:16-alpineVérification :
docker ps | grep litellm-postgres# Doit afficher le conteneur en cours d'exécutionÉtape 5 : Lancer LiteLLM Proxy
Section intitulée « Étape 5 : Lancer LiteLLM Proxy »Quatre paramètres de cette commande méritent votre attention. LITELLM_MASTER_KEY est la clé d'administration : elle crée toutes les autres clés et ne doit jamais être distribuée à une application. DATABASE_URL pointe vers le PostgreSQL lancé à l'étape précédente, sans quoi le proxy démarre mais perd clés et compteurs à chaque redémarrage. --add-host donne au conteneur une route vers Ollama sur l'hôte. Enfin, la configuration est montée en lecture seule (:ro) : le proxy n'a aucune raison de réécrire son propre fichier de modèles.
docker run -d --name litellm-proxy \ -p 4000:4000 \ -v $(pwd)/config/proxy-config.yaml:/app/config.yaml:ro \ -e LITELLM_MASTER_KEY=sk-litellm-lab-2026-demo \ -e DATABASE_URL="postgresql://litellm:litellm_secure_pwd@172.17.0.1:5432/litellm" \ -e UI_USERNAME=admin \ -e UI_PASSWORD=AdminSecure2026 \ --add-host=host.docker.internal:host-gateway \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml --port 4000Vérifier les logs :
docker logs litellm-proxy --tail 20Sortie attendue :
██╗ ██╗████████╗███████╗██╗ ██╗ ███╗ ███╗ ██║ ██║╚══██╔══╝██╔════╝██║ ██║ ████╗ ████║ ...INFO: Application startup complete.INFO: Uvicorn running on http://0.0.0.0:4000Étape 6 : Tester le proxy
Section intitulée « Étape 6 : Tester le proxy »Deux vérifications enchaînées, dans cet ordre. /v1/models confirme que le proxy a lu sa configuration : les quatre noms retournés sont ceux déclarés dans model_list, pas ceux d'Ollama. Puis /v1/chat/completions prouve que la chaîne complète fonctionne jusqu'au modèle. Si la première commande répond et pas la seconde, le problème est entre le conteneur et Ollama, pas dans la configuration du proxy.
# Lister les modèles disponiblescurl -s http://localhost:4000/v1/models \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" | jq '.data[].id'Sortie attendue :
"llama""qwen""gpt-3.5-turbo""gpt-4"# Tester une complétioncurl -s http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" \ -d '{ "model": "qwen", "messages": [{"role": "user", "content": "Dis bonjour en une phrase"}], "max_tokens": 30 }' | jq '.choices[0].message.content'Sortie attendue :
"Bonjour! Comment puis-je vous aider aujourd'hui?"Gestion des utilisateurs et équipes
Section intitulée « Gestion des utilisateurs et équipes »LiteLLM propose une hiérarchie à 3 niveaux : Utilisateurs → Équipes → Clés. Chaque niveau peut avoir ses propres restrictions.
Créer un utilisateur
Section intitulée « Créer un utilisateur »L'utilisateur porte l'identité et le budget d'une personne. Deux champs pilotent tout le reste : max_budget fixe le plafond de dépense en dollars et budget_duration la fenêtre sur laquelle il se réinitialise (30d ici). Le champ models restreint d'emblée les modèles atteignables, ce qui vaut mieux que de l'imposer clé par clé ensuite. Le bloc metadata est libre : il ressort dans les rapports de dépense et sert à ventiler les coûts par équipe ou par projet.
curl -s http://localhost:4000/user/new \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" \ -d '{ "user_id": "alice@example.com", "user_email": "alice@example.com", "max_budget": 5.0, "budget_duration": "30d", "models": ["qwen"], "metadata": {"role": "developer", "department": "engineering"} }' | jq '{user_id, max_budget, models}'Sortie :
{ "user_id": "alice@example.com", "max_budget": 5.0, "models": ["qwen"]}Créer une équipe
Section intitulée « Créer une équipe »L'équipe agrège les dépenses de plusieurs utilisateurs et porte les limites de débit partagées, ici 60 requêtes et 100 000 tokens par minute. Notez la valeur retournée : LiteLLM génère un team_id en UUID que vous devrez reporter dans les créations de clés. Le team_alias est le nom lisible affiché dans l'interface, il ne s'utilise pas comme identifiant dans l'API.
curl -s http://localhost:4000/team/new \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" \ -d '{ "team_alias": "ml-team", "max_budget": 50.0, "budget_duration": "30d", "models": ["qwen", "llama"], "tpm_limit": 100000, "rpm_limit": 60, "metadata": {"project": "ml-pipeline"} }' | jq '{team_id, team_alias, max_budget, rpm_limit}'Sortie :
{ "team_id": "0b71f785-5fec-48c0-a76d-87d3289fafb4", "team_alias": "ml-team", "max_budget": 50.0, "rpm_limit": 60}Gestion des clés virtuelles
Section intitulée « Gestion des clés virtuelles »Les clés virtuelles permettent de distribuer des accès sans partager la master key.
Créer une clé avec restrictions
Section intitulée « Créer une clé avec restrictions »La clé est ce que vous distribuez réellement à une application. Elle est retournée une seule fois en clair, la base ne conserve ensuite qu'une empreinte : perdre la valeur oblige à en régénérer une. Le key_alias sert à la retrouver dans l'interface sans connaître sa valeur, ce qui en fait le seul moyen pratique de révoquer la bonne clé le jour où une application se comporte mal.
curl -s http://localhost:4000/key/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" \ -d '{ "key_alias": "dev-team-key", "max_budget": 10.0, "budget_duration": "30d", "models": ["qwen", "llama"], "metadata": {"team": "dev", "project": "demo"} }' | jq '{key, max_budget, models}'Sortie :
{ "key": "sk-Li3j_hWPrxs5MY3m0DBAJg", "max_budget": 10.0, "models": ["qwen", "llama"]}Tester les restrictions de modèle
Section intitulée « Tester les restrictions de modèle »Cette clé est limitée à qwen et llama. Testons l'accès à gpt-4 :
curl -s http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-Li3j_hWPrxs5MY3m0DBAJg" \ -d '{"model": "gpt-4", "messages": [{"role": "user", "content": "test"}]}' \ | jq '.error'Sortie (accès refusé) :
{ "message": "key not allowed to access model. This key can only access models=['qwen', 'llama']. Tried to access gpt-4", "type": "key_model_access_denied", "code": "401"}Créer une clé liée à un utilisateur et une équipe
Section intitulée « Créer une clé liée à un utilisateur et une équipe »Rattacher la clé à un user_id et à un team_id permet d'imputer chaque appel aux deux niveaux à la fois. La conséquence pratique est celle décrite dans l'encadré ci-dessus : la clé s'arrête au plafond le plus bas des trois, ici les 2 dollars de la clé, même si l'équipe dispose encore de 48 dollars de budget.
curl -s http://localhost:4000/key/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" \ -d '{ "key_alias": "alice-personal-key", "user_id": "alice@example.com", "team_id": "0b71f785-5fec-48c0-a76d-87d3289fafb4", "max_budget": 2.0 }' | jq '{key, user_id, team_id, max_budget}'Rate limiting (RPM/TPM)
Section intitulée « Rate limiting (RPM/TPM) »Le rate limiting protège contre les abus et contrôle la consommation.
Créer une clé avec rate limit strict
Section intitulée « Créer une clé avec rate limit strict »Les valeurs choisies ici sont volontairement absurdes, 2 requêtes et 100 tokens par minute, pour rendre le blocage observable en trois commandes. En production, dimensionnez rpm_limit sur le débit nominal de l'application majoré d'une marge, et tpm_limit sur le budget mensuel divisé par le nombre de minutes ouvrées, faute de quoi la limite se déclenchera en pleine journée de pointe.
curl -s http://localhost:4000/key/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" \ -d '{ "key_alias": "rate-limited-key", "rpm_limit": 2, "tpm_limit": 100, "models": ["qwen"] }' | jq '{key, rpm_limit, tpm_limit}'Sortie :
{ "key": "sk-9MwdeGpwsUJ9z0NPftXz4A", "rpm_limit": 2, "tpm_limit": 100}Tester le rate limiting
Section intitulée « Tester le rate limiting »La vérification consiste à dépasser volontairement la limite. Trois requêtes envoyées coup sur coup contre une clé limitée à 2 requêtes par minute doivent produire deux réponses puis une erreur. Ce qu'il faut observer dans la sortie, c'est la forme du refus : LiteLLM ne coupe pas la connexion, il renvoie un message d'erreur structuré indiquant la limite atteinte et l'heure de réinitialisation, ce que votre application doit savoir interpréter pour réessayer plus tard.
KEY="sk-9MwdeGpwsUJ9z0NPftXz4A"for i in 1 2 3; do echo "=== Requête $i ===" curl -s http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $KEY" \ -d '{"model": "qwen", "messages": [{"role": "user", "content": "1"}], "max_tokens": 5}' \ | jq -c '{ok: .choices[0].message.content, error: .error.message}'doneSortie :
=== Requête 1 ==={"ok":"Hello! It seems like","error":null}=== Requête 2 ==={"ok":"Hello! How can I","error":null}=== Requête 3 ==={"ok":null,"error":"Rate limit exceeded... Current limit: 2, Remaining: 0. Limit resets at: ..."}Monitoring de la consommation
Section intitulée « Monitoring de la consommation »Consulter les dépenses par tag
Section intitulée « Consulter les dépenses par tag »L'endpoint /spend/tags agrège les dépenses selon les tags posés sur les requêtes ou hérités des métadonnées de clé. C'est la donnée à extraire pour une refacturation interne : elle est stable, horodatée et exportable, alors que les graphiques de l'interface ne se copient pas dans un tableur. Sur un lab qui vient de démarrer, la réponse est un tableau vide, ce qui est normal tant qu'aucun appel facturé n'a eu lieu.
curl -s http://localhost:4000/spend/tags \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" | jq .Voir les statistiques globales
Section intitulée « Voir les statistiques globales »Accédez à l'interface web http://localhost:4000/ui pour visualiser :
- Dépenses par modèle, utilisateur, équipe
- Graphiques de consommation dans le temps
- Alertes de dépassement de budget
Production : Docker Compose
Section intitulée « Production : Docker Compose »Pour un déploiement de production, passez à Docker Compose avec persistance. Trois différences avec le lab comptent vraiment. Les images sont épinglées par digest plutôt que par tag, car main-latest suit chaque fusion sur la branche principale et rendrait votre proxy imprévisible ; relevez le digest courant avec docker buildx imagetools inspect <image> avant de le figer, et remontez-le sciemment. Le depends_on avec condition: service_healthy évite le démarrage en échec du proxy tant que la base n'accepte pas de connexion. Enfin, la configuration est montée en lecture seule et aucun secret n'est écrit dans le fichier, tout passe par le .env décrit juste après.
services: postgres: image: postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777 container_name: litellm-db environment: POSTGRES_USER: litellm POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} POSTGRES_DB: litellm volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U litellm"] interval: 5s timeout: 5s retries: 5
litellm: image: ghcr.io/berriai/litellm:main-stable@sha256:a1745e629abfb17d434426ff48b115f54f4f4c4a0f5af241de569e93c63c411e container_name: litellm-proxy ports: - "4000:4000" environment: LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY} DATABASE_URL: postgresql://litellm:${POSTGRES_PASSWORD:-changeme}@postgres:5432/litellm UI_USERNAME: ${UI_USERNAME:-admin} UI_PASSWORD: ${UI_PASSWORD} OPENAI_API_KEY: ${OPENAI_API_KEY:-} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} volumes: - ./config/proxy-config.yaml:/app/config.yaml:ro depends_on: postgres: condition: service_healthy command: ["--config", "/app/config.yaml", "--port", "4000"] restart: unless-stopped
volumes: postgres_data:Le fichier .env porte l'intégralité des valeurs sensibles et ne doit jamais être versionné : ajoutez-le à .gitignore avant même de le créer. Générez la master key avec openssl rand -hex 32 plutôt que de la choisir à la main, et restreignez les droits du fichier avec chmod 600 .env pour qu'il ne soit lisible que par le compte qui lance Compose.
Fichier .env :
LITELLM_MASTER_KEY=sk-your-secure-master-key-herePOSTGRES_PASSWORD=your-secure-db-passwordUI_USERNAME=adminUI_PASSWORD=YourSecureUIPassword!OPENAI_API_KEY=sk-...ANTHROPIC_API_KEY=sk-ant-...Lancement :
docker compose up -ddocker compose logs -f litellmDépannage
Section intitulée « Dépannage »Problèmes courants
Section intitulée « Problèmes courants »Les deux premières lignes sont les seules qui empêchent le proxy de démarrer, les trois autres se produisent une fois qu'il tourne. Une confusion revient souvent : Authentication Error vient de la master key, alors que key not allowed to access model vient d'une clé virtuelle correctement authentifiée mais restreinte. La première est un problème de configuration, la seconde le fonctionnement attendu.
| Symptôme | Cause probable | Solution |
|---|---|---|
Cannot connect to host localhost:11434 | Ollama écoute sur 127.0.0.1 | Lancer avec OLLAMA_HOST=0.0.0.0 |
Unable to find Prisma binaries | Installation pip sans Docker | Utiliser l'image Docker officielle |
Rate limit exceeded | Limite atteinte | Attendre le reset ou augmenter la limite |
key not allowed to access model | Modèle non autorisé | Ajouter le modèle à la clé |
Authentication Error | Master key incorrecte | Vérifier LITELLM_MASTER_KEY |
Commandes de diagnostic
Section intitulée « Commandes de diagnostic »Prenez ces quatre commandes dans l'ordre : elles vont du plus général au plus précis. Les logs disent si le processus a démarré, la vérification PostgreSQL si la persistance répond, la liste des clés si l'état applicatif est cohérent, et le health check si le proxy joint réellement les modèles déclarés. C'est cette dernière qui distingue un proxy en bonne santé d'un proxy qui répond mais dont tous les backends sont injoignables.
# Logs du proxydocker logs litellm-proxy --tail 100
# Vérifier la connexion PostgreSQLdocker exec litellm-proxy psql $DATABASE_URL -c "SELECT 1"
# Lister toutes les clés (tokens hachés)curl -s http://localhost:4000/key/list \ -H "Authorization: Bearer sk-litellm-lab-2026-demo" | jq .
# Health checkcurl -s http://localhost:4000/health | jq .Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- LiteLLM Proxy unifie l'accès à 100+ LLM via une API compatible OpenAI
- Hiérarchie 3 niveaux : User → Team → Key, chacun avec ses restrictions
- Restrictions par clé : modèles autorisés, budget, rate limits (RPM/TPM)
- Docker recommandé pour éviter les problèmes de dépendances (Prisma)
- PostgreSQL requis pour la persistance des clés, users et métriques
- Production : HTTPS obligatoire, master key sécurisée, backups
Pour aller plus loin
Section intitulée « Pour aller plus loin »- vLLM : haute performance : Le backend GPU à placer derrière le proxy pour un débit sérieux.
- Le socle self-hosted : Le proxy remis dans une stack complète, avec Ollama et Qdrant.
- Observabilité des LLM : Mesurer le coût, la latence et la qualité de ce que le proxy voit passer.
Ressources
Section intitulée « Ressources »- Documentation officielle : docs.litellm.ai
- GitHub : github.com/BerriAI/litellm
- Swagger API : http://localhost:4000 (après démarrage du proxy)
- Communauté Discord : Support communautaire actif