Browse Source

add new cookbook: litellm

main
Nicolas Massé 4 weeks ago
parent
commit
2c9f6fc8f2
  1. 12
      cookbooks/litellm/Makefile
  2. 92
      cookbooks/litellm/README.md
  3. 24
      cookbooks/litellm/config/examples/config.env
  4. 24
      cookbooks/litellm/config/examples/config.yaml
  5. 62
      cookbooks/litellm/litellm.container
  6. 7
      cookbooks/litellm/litellm.image
  7. 13
      cookbooks/litellm/litellm.target
  8. 5
      cookbooks/litellm/other/postgresql/litellm.sql
  9. 16
      cookbooks/litellm/other/traefik/litellm.yaml
  10. 9
      cookbooks/litellm/overlay.bu

12
cookbooks/litellm/Makefile

@ -0,0 +1,12 @@
##
## Makefile for LiteLLM quadlet
##
DEPENDENCIES = postgresql traefik
# LiteLLM quadlet is mapped to the 10024 user (litellm) and 10000 group (itix-svc)
PROJECT_UID = 10024
PROJECT_GID = 10000
# Include common Makefile
include ../../scripts/common.mk

92
cookbooks/litellm/README.md

@ -0,0 +1,92 @@
# Podman Quadlet: LiteLLM
## Overview
[LiteLLM](https://docs.litellm.ai/) is an LLM gateway (proxy server) that exposes
100+ LLM providers behind a single, OpenAI-compatible API, with authentication,
budgets, rate limiting and a management UI.
This cookbook:
- Runs LiteLLM in **proxy mode** using the **non-root** container image
(`ghcr.io/berriai/litellm-non_root`), which runs as UID/GID `65534`.
UID/GID mapping remaps it to the dedicated `litellm` user (`10024`) and the
`itix-svc` group (`10000`) on the host.
- Reads its behaviour from a configuration file (`config.yaml`).
- Reads secrets and passwords (master key, UI credentials, database URL) from a
separate `config.env` file injected as environment variables.
- Redirects the root path (`/`) to the Admin UI (`/ui`) and serves the API docs
under `/docs`.
- Uses PostgreSQL as its backend (requires the `postgresql` cookbook) to persist
keys, models and spend logs.
- Is published through Traefik (requires the `traefik` cookbook).
## Prerequisites
- The `postgresql` cookbook must be installed and running.
- The `traefik` cookbook must be installed and running.
- Configuration files `/etc/quadlets/litellm/config.yaml` and
`/etc/quadlets/litellm/config.env` must exist (copied from the examples).
## Configuration
- `config.yaml` — proxy configuration (`model_list`, `general_settings`, ...).
See <https://docs.litellm.ai/docs/proxy/config_settings>.
- `config.env` — secrets injected as environment variables:
| Variable | Purpose |
| -------------------- | ----------------------------------------------- |
| `LITELLM_MASTER_KEY` | Master key for the proxy (must start with `sk-`)|
| `UI_USERNAME` | Username to sign in on the Admin UI |
| `UI_PASSWORD` | Password to sign in on the Admin UI |
| `DATABASE_URL` | PostgreSQL connection string |
The root redirect (`ROOT_REDIRECT_URL=/ui`) and docs path (`DOCS_URL=/docs`)
are set directly in the Quadlet file.
## Ports
- TCP `4000`: LiteLLM proxy / Admin UI (bound on `127.0.0.1`, exposed through
Traefik).
## UID / GID
- User `litellm`: UID `10024`
- Group `itix-svc`: GID `10000`
- Inside the container the process runs as `65534:65534` (mapped to the host
IDs above).
## Usage
In a separate terminal, follow the logs.
```sh
sudo make tail-logs
```
Install the Podman Quadlets and start LiteLLM.
```sh
sudo make clean install
```
You should see the **litellm.service** waiting for PostgreSQL to be available,
then running its database migrations and starting up.
Verify LiteLLM is running using its liveness endpoint:
```sh
curl -sSf http://127.0.0.1:4000/health/liveliness
```
Then browse to the service through Traefik (the root path redirects to `/ui`):
```sh
curl --resolve litellm:80:127.0.0.1 -L http://litellm/
```
Finally, remove the quadlets, their configuration and their data.
```sh
sudo make uninstall clean
```

24
cookbooks/litellm/config/examples/config.env

@ -0,0 +1,24 @@
##
## LiteLLM secrets and passwords
## https://docs.litellm.ai/docs/proxy/ui
##
## This file holds sensitive values and is installed with 0600 root:root
## permissions. Podman reads it on the host and injects the variables into the
## container environment.
##
# Master key used to authenticate against the proxy server (must start with sk-)
LITELLM_MASTER_KEY=sk-secret1234
# Admin UI credentials
UI_USERNAME=admin
UI_PASSWORD=admin
# PostgreSQL connection (provided by the postgresql cookbook on localhost)
DATABASE_URL=postgresql://litellm:litellm@localhost:5432/litellm
# Store models and keys managed through the UI in the database
STORE_MODEL_IN_DB=True
# Provider API keys referenced from config.yaml (os.environ/...) go here too
#OPENAI_API_KEY="sk-..."

24
cookbooks/litellm/config/examples/config.yaml

@ -0,0 +1,24 @@
##
## LiteLLM Proxy configuration
## https://docs.litellm.ai/docs/proxy/config_settings
##
## Secrets (master key, UI credentials, database URL) are NOT set here.
## They are injected as environment variables from config.env.
##
model_list:
# Declare your models here, or add them through the Admin UI (they will be
# persisted in the database thanks to `store_model_in_db`).
#
# - model_name: gpt-4o
# litellm_params:
# model: openai/gpt-4o
# api_key: os.environ/OPENAI_API_KEY
general_settings:
# Persist models and credentials added through the Admin UI in the database.
store_model_in_db: true
litellm_settings:
# Drop parameters unsupported by the target provider instead of failing.
drop_params: true

62
cookbooks/litellm/litellm.container

@ -0,0 +1,62 @@
[Unit]
Description=LiteLLM Proxy Server
Documentation=https://docs.litellm.ai/docs/proxy/deploy
After=network.target
# Only start if LiteLLM has been configured
ConditionPathExists=/etc/quadlets/litellm/config.env
ConditionPathExists=/etc/quadlets/litellm/config.yaml
# Start/stop this unit when the target is started/stopped
PartOf=litellm.target
[Container]
ContainerName=litellm
Image=litellm.image
AutoUpdate=registry
# The non-root image runs as the "nobody" user (UID/GID 65534)
User=65534
Group=65534
# UID/GID mapping to map the nobody (65534) user inside the container to the
# dedicated litellm user (10024) / itix-svc group (10000) on the host
UIDMap=0:1000000:65535
UIDMap=+65534:10024:1
GIDMap=0:1000000:65535
GIDMap=+65534:10000:1
# Network configuration
Network=host
# Run in proxy mode with the provided configuration file
Exec=--config /app/config.yaml
# Redirect the root path (/) to the Admin UI and expose the docs under /docs
Environment=ROOT_REDIRECT_URL=/ui
Environment=DOCS_URL=/docs
# Secrets and passwords (master key, UI credentials, database URL)
EnvironmentFile=/etc/quadlets/litellm/config.env
# Volume mounts
Volume=/etc/quadlets/litellm/config.yaml:/app/config.yaml:ro,z
# Health check
HealthCmd=python3 -c 'import urllib.request; urllib.request.urlopen("http://127.0.0.1:4000/health/liveliness")'
HealthInterval=30s
HealthTimeout=10s
HealthStartPeriod=60s
HealthRetries=3
[Service]
Restart=always
RestartSec=10
TimeoutStartSec=300
TimeoutStopSec=30
# Wait for PostgreSQL to be ready on localhost
ExecStartPre=/bin/sh -c 'exec 2>/dev/null; for try in $(seq 0 12); do if ! /bin/true 5<> /dev/tcp/127.0.0.1/5432; then echo "Waiting for PostgreSQL to be available..."; sleep 5; else exit 0; fi; done; exit 1'
[Install]
WantedBy=litellm.target

7
cookbooks/litellm/litellm.image

@ -0,0 +1,7 @@
[Unit]
Description=podman pull ghcr.io/berriai/litellm-non_root
Documentation=https://docs.litellm.ai/docs/proxy/docker_image_security
[Image]
# Non-root variant of the LiteLLM image (runs as UID/GID 65534)
Image=ghcr.io/berriai/litellm-non_root:main-stable

13
cookbooks/litellm/litellm.target

@ -0,0 +1,13 @@
[Unit]
Description=LiteLLM Service Target
Documentation=man:systemd.target(5)
Requires=postgresql.target litellm.service
After=postgresql.target litellm.service
# Allow isolation - can stop/start this target independently
AllowIsolate=yes
# Only start if LiteLLM has been configured
ConditionPathExists=/etc/quadlets/litellm/config.env
[Install]
WantedBy=multi-user.target

5
cookbooks/litellm/other/postgresql/litellm.sql

@ -0,0 +1,5 @@
-- Initialization script for LiteLLM database and user
CREATE USER litellm WITH PASSWORD 'litellm';
CREATE DATABASE litellm OWNER litellm;
GRANT ALL PRIVILEGES ON DATABASE litellm TO litellm;
ALTER ROLE litellm SET client_encoding TO 'utf8';

16
cookbooks/litellm/other/traefik/litellm.yaml

@ -0,0 +1,16 @@
http:
routers:
litellm:
rule: "Host(`litellm`)"
entryPoints:
- http
#- https
middlewares:
service: "litellm"
#tls:
# certResolver: le
services:
litellm:
loadBalancer:
servers:
- url: "http://127.0.0.1:4000"

9
cookbooks/litellm/overlay.bu

@ -0,0 +1,9 @@
variant: fcos
version: 1.4.0
passwd:
users:
- name: litellm
uid: 10024
gecos: LiteLLM
home_dir: /var/lib/quadlets/litellm
primary_group: itix-svc
Loading…
Cancel
Save