Tutoriales de VPS
Desplegar una puerta de enlace API LLM unificada LiteLLM en un VPS (2026): Docker, claves virtuales, control de presupuesto y guía de enrutamiento multimodelo
Este tutorial explica cómo autoalojar LiteLLM Proxy en un VPS y unificar OpenAI, Claude, Gemini, DeepSeek, OpenRouter y otros modelos tras una interfaz compatible con OpenAI. Cubre el despliegue con Docker Compose, el enrutamiento de modelos en config.yaml, claves virtuales, presupuestos de equipo, PostgreSQL, Prometheus, HTTPS con Caddy, copias de seguridad y actualizaciones, y errores comunes.

He visto a muchos equipos empezar simplemente escribiendo una clave de OpenAI en el proyecto y, a medida que conectaban más y más modelos, las facturas se volvían cada vez más caóticas.
Una interfaz llama a OpenAI, otra llama a Claude, otra llama a Gemini, y alguien añade temporalmente DeepSeek, OpenRouter, Azure OpenAI. Al final, las claves API están por todas partes en el código y nadie puede decir con claridad cuánto gastó cada proyecto.
LiteLLM resuelve exactamente este problema.
Puede unificar un montón de proveedores de modelos tras una interfaz compatible con OpenAI. Tu aplicación solo necesita solicitar una dirección, por ejemplo:
https://llm.example.com/v1/chat/completions
Si luego se reenvía a OpenAI, Claude, Gemini, DeepSeek o se rota entre varias claves, lo gestiona LiteLLM.
Este artículo está escrito para el autoalojamiento en VPS: cómo ejecutarlo con Docker Compose, cómo configurar config.yaml, cómo hacer claves virtuales, control de presupuesto, HTTPS, copias de seguridad y en qué se diferencia realmente de One-API / New-API.
Si solo usas tú una clave de OpenAI, LiteLLM puede ser algo redundante.
Pero en cuanto aparece cualquiera de las siguientes situaciones, resulta muy valioso:
| Escenario | Por qué es adecuado LiteLLM |
|---|---|
| Un proyecto necesita varios modelos | Unificado al formato OpenAI, menos código que cambiar |
| Un equipo comparte las API de modelos | Se emite una clave virtual a cada persona, control de presupuesto sencillo |
| Quieres hacer fallback | Si un modelo cae, se cambia automáticamente a otro |
| Quieres contabilizar el gasto | Ver el consumo por clave, usuario y modelo |
| Quieres un punto de entrada unificado | Exponer solo una dirección de puerta de enlace API |
Mi propio criterio es simple:
- Uso personal con una sola clave: no es necesario
- Varios proyectos, varios modelos, varios miembros: muy necesario
- Quieres construir una plataforma interna de API de IA: merece la pena desplegarlo
No es una interfaz de chat ni una plataforma de aplicaciones de IA. Se parece más a una puerta de enlace API de LLM.
LiteLLM en sí no es pesado; lo que realmente consume recursos es PostgreSQL, Prometheus, la concurrencia de solicitudes y el volumen de registros.
| Uso | Configuración de VPS sugerida |
|---|---|
| Pruebas personales | 1 núcleo / 1GB / 20GB SSD |
| Uso compartido de un equipo pequeño | 2 núcleos / 4GB / 40GB SSD |
| Uso en producción con varios proyectos | 4 núcleos / 8GB / 80GB SSD |
Si solo haces de proxy y no ejecutas modelos locales, 2C4G es básicamente suficiente.
No lo mezcles con Ollama al calcular recursos. LiteLLM es una puerta de enlace de reenvío y no se encarga de la inferencia local. Lo que conectas son API remotas como OpenAI, DeepSeek o Claude, así que su propia presión de CPU no es alta.
No te apresures a copiar el Compose.
Hay tres cosas en LiteLLM que debes decidir desde el principio:
LITELLM_MASTER_KEYLITELLM_SALT_KEY- Las reglas de nombres de modelos en
config.yaml
MASTER_KEY es la clave de administrador y debe empezar por sk-.
SALT_KEY es más importante; se usa para cifrar las claves API de los modelos en la base de datos. La documentación oficial también advierte: tras añadir modelos, no cambies este valor a la ligera. Si lo cambias, es posible que las credenciales cifradas antiguas ya no se puedan descifrar.
Así que no escribas:
LITELLM_SALT_KEY=sk-1234
En su lugar, genera un valor aleatorio más largo:
openssl rand -hex 32
Y luego escríbelo en .env.
Este artículo usa Ubuntu / Debian como ejemplo.
apt update && apt upgrade -y
apt install -y ca-certificates curl gnupg ufw nano
Instalar Docker:
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Confirmar:
docker --version
docker compose version
mkdir -p /opt/litellm
cd /opt/litellm
Generar dos claves:
echo "sk-$(openssl rand -hex 32)"
echo "sk-$(openssl rand -hex 32)"
Una para LITELLM_MASTER_KEY, otra para LITELLM_SALT_KEY.
Crear .env:
cat > .env << 'EOF'
LITELLM_MASTER_KEY="sk-replace-with-master-key"
LITELLM_SALT_KEY="sk-replace-with-long-salt-key"
OPENAI_API_KEY="sk-replace-with-openai-key"
DEEPSEEK_API_KEY="replace-with-deepseek-key"
POSTGRES_PASSWORD="replace-with-postgres-password"
EOF
Si por ahora no usas OpenAI o DeepSeek, puedes dejarlas vacías de momento, pero MASTER_KEY y SALT_KEY deben rellenarse con cuidado.
config.yaml es el núcleo de LiteLLM.
Determina:
- Cómo se llaman los modelos de cara al exterior
- A qué proveedor se reenvía realmente
- De dónde se lee la clave API
- Cómo se configuran la base de datos y los ajustes del backend
Crear el archivo:
nano config.yaml
Escribir una versión mínima funcional:
model_list:
- model_name: gpt-4o-mini
litellm_params:
model: openai/gpt-4o-mini
api_key: os.environ/OPENAI_API_KEY
- model_name: deepseek-chat
litellm_params:
model: deepseek/deepseek-chat
api_key: os.environ/DEEPSEEK_API_KEY
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
database_url: "postgresql://litellm:${POSTGRES_PASSWORD}@db:5432/litellm"
store_model_in_db: true
litellm_settings:
request_timeout: 600
set_verbose: false
json_logs: true
Lo más fácil de confundir aquí es:
model_name: gpt-4o-mini
Este es el nombre que expones al exterior.
model: openai/gpt-4o-mini
Este es el proveedor y modelo que LiteLLM reconoce internamente.
Es decir, puedes exponer un nombre unificado al exterior:
company-fast-model
Pero detrás se conecta realmente a DeepSeek, OpenAI u otro proveedor.
Crear docker-compose.yml:
services:
db:
image: postgres:16
container_name: litellm-db
restart: unless-stopped
environment:
POSTGRES_DB: litellm
POSTGRES_USER: litellm
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./postgres-data:/var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U litellm -d litellm"]
interval: 10s
timeout: 5s
retries: 5
litellm:
image: ghcr.io/berriai/litellm-database:main-stable
container_name: litellm
restart: unless-stopped
depends_on:
db:
condition: service_healthy
env_file:
- .env
volumes:
- ./config.yaml:/app/config.yaml:ro
command: ["--config", "/app/config.yaml", "--port", "4000"]
ports:
- "127.0.0.1:4000:4000"
Fíjate en que he vinculado tanto 4000 como 5432 a 127.0.0.1.
Muchos ejemplos, por comodidad, exponen los servicios directamente a internet. No hagas eso en producción. Pon Caddy o Nginx delante de LiteLLM, y mucho menos expongas la base de datos directamente.
Iniciar:
docker compose up -d
Ver el estado:
docker compose ps
docker logs litellm --tail=100
Prueba local:
curl http://127.0.0.1:4000/health
Si la comprobación de estado es normal, puedes continuar configurando HTTPS.
Supongamos que el dominio es:
llm.example.com
Añade un registro A en el DNS apuntando a la IP de tu VPS.
Instalar Caddy:
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' > /etc/apt/sources.list.d/caddy-stable.list
apt update
apt install -y caddy
Editar la configuración:
nano /etc/caddy/Caddyfile
Escribir:
llm.example.com {
reverse_proxy 127.0.0.1:4000
}
Comprobar y recargar:
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
Acceder desde el navegador:
https://llm.example.com/ui
Inicia sesión en el panel de administración con tu LITELLM_MASTER_KEY.
Abrir solo SSH, 80 y 443:
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status
No abras 4000 y 5432:
ufw deny 4000/tcp
ufw deny 5432/tcp
Si necesitas que sistemas internos lo llamen, se recomienda usar Tailscale, WireGuard o Cloudflare Tunnel, y no dejar el panel de administración expuesto a internet.
Solicitar LiteLLM en formato compatible con OpenAI:
curl https://llm.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-your-master-key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "用一句话解释什么是 VPS"}
]
}'
Si quieres probar DeepSeek:
curl https://llm.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-your-master-key" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-chat",
"messages": [
{"role": "user", "content": "给我一个 Docker Compose 备份建议"}
]
}'
Siempre que la aplicación ya soporte la API de OpenAI, en la mayoría de los casos basta con cambiar base_url por tu dirección de LiteLLM y funcionará.
Por ejemplo:
OPENAI_BASE_URL=https://llm.example.com/v1
OPENAI_API_KEY=sk-your-virtual-key-or-master-key
Lo que realmente hace valioso a LiteLLM no es el reenvío de proxy, sino las claves virtuales.
Puedes emitir claves distintas para distintos proyectos:
project-docs-botproject-customer-supportdeveloper-testmarketing-agent
Configurar cada clave por separado:
- Modelos disponibles
- Solicitudes por minuto
- Presupuesto mensual
- Fecha de caducidad
- Registros de uso
Esto es mucho más seguro que repartir la clave real de OpenAI entre todos.
En el uso real, yo las dividiría así:
| Clave | Uso | Restricción |
|---|---|---|
| dev-test | Depuración de desarrollo | Presupuesto pequeño, RPM bajo |
| prod-api | Servicio en línea | Presupuesto alto, solo para el backend |
| data-script | Scripts por lotes | Modelos limitados, concurrencia limitada |
| demo | Demostración temporal | Caduca en 1 día |
Cuando surge un problema, también es fácil investigarlo: quién exactamente agotó el dinero, qué proyecto tiene un volumen de solicitudes anómalo; basta con mirar la dimensión de la clave.
Si es solo para uso personal, puedes omitir Prometheus por ahora.
Si lo comparte un equipo, se recomienda añadirlo, porque tarde o temprano querrás saber:
- Cuánto volumen de solicitudes hay
- Qué modelo se usa más
- Si la latencia es alta
- Si se producen errores con frecuencia
Los ejemplos oficiales de LiteLLM usan prometheus.yml, y aquí hay un escollo: este archivo debe ser un archivo real.
Si lo montas directamente en Compose:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
Pero el archivo no existe localmente, Docker puede crearlo como directorio y Prometheus no arrancará.
Créalo primero:
cat > prometheus.yml << 'EOF'
global:
scrape_interval: 15s
scrape_configs:
- job_name: "litellm"
static_configs:
- targets: ["litellm:4000"]
EOF
Luego amplía el Compose. No expongas el panel de Prometheus directamente a internet; como mínimo añade Basic Auth o permite solo acceso desde la red interna.
Respalda al menos tres cosas:
/opt/litellm/.env
/opt/litellm/config.yaml
/opt/litellm/postgres-data
.env contiene claves, no lo pongas a la ligera en GitHub.
config.yaml puede ir a un repositorio Git privado, pero no codifiques claves API reales en él; intenta usar:
api_key: os.environ/OPENAI_API_KEY
La copia de seguridad de PostgreSQL puede hacerse así:
cd /opt/litellm
docker exec litellm-db pg_dump -U litellm litellm | gzip > litellm-db-$(date +%F).sql.gz
Luego sincroniza la copia de seguridad con el almacenamiento de objetos:
rclone copy litellm-db-$(date +%F).sql.gz r2:backup-bucket/litellm/
Si solo respaldas el Compose y no la base de datos, se perderán las claves virtuales, los registros de presupuesto y las estadísticas de uso.
Haz una copia de seguridad antes de actualizar:
cd /opt/litellm
docker exec litellm-db pg_dump -U litellm litellm | gzip > litellm-before-upgrade-$(date +%F).sql.gz
cp config.yaml config.yaml.bak.$(date +%F)
cp .env .env.bak.$(date +%F)
Luego descarga la nueva imagen:
docker compose pull
docker compose up -d
Revisa los registros:
docker logs litellm --tail=200
LiteLLM implica migraciones de base de datos. En producción no actualices en horas punta; es más estable verificarlo primero en una máquina de pruebas.
LiteLLM tiene requisitos de formato para la master key.
No escribas:
LITELLM_MASTER_KEY="my-password"
Escribe:
LITELLM_MASTER_KEY="sk-xxxxxxxx"
LITELLM_SALT_KEY se usa para cifrar y descifrar credenciales.
Después de añadir modelos y crear claves, no la cambies sin más. Antes de cambiarla, confirma que sabes cómo recuperarla, de lo contrario el contenido cifrado de la base de datos podría no descifrarse.
Si ves esto en el Compose:
ports:
- "5432:5432"
Sugiero cambiarlo a:
ports:
- "127.0.0.1:5432:5432"
O simplemente no lo mapees al host y deja que solo se acceda dentro de la red de Docker.
La solicitud usa model_name, no litellm_params.model.
Si la configuración es:
model_name: deepseek-chat
litellm_params:
model: deepseek/deepseek-chat
Entonces al solicitar, escribe:
"model": "deepseek-chat"
No:
"model": "deepseek/deepseek-chat"
Antes de iniciar, confirma:
ls -lah prometheus.yml
Debería ser un archivo, no un directorio.
Si ya se ha convertido en directorio:
rm -rf prometheus.yml
nano prometheus.yml
Y reinicia.
Estas herramientas suelen compararse juntas.
| Herramienta | Más adecuada para |
|---|---|
| One-API / New-API | Distribución orientada al usuario, gestión de canales, operación con panel |
| LiteLLM | Equipos de desarrollo, SDK/API unificado, enrutamiento y control de presupuesto |
| OpenRouter | No querer autoalojar y usar directamente un servicio de agregación gestionado |
Si eres administrador de un sitio y quieres emitir claves a usuarios, gestionar canales y ver saldos, New-API se parece más a un panel listo para usar.
Si eres un equipo de desarrollo y quieres que los proyectos internos pasen por un punto de entrada unificado compatible con OpenAI, LiteLLM es más cómodo.
No son completamente excluyentes. También puedes hacer que LiteLLM se conecte a un New-API upstream, o que todas las aplicaciones internas pasen por LiteLLM y que luego LiteLLM haga el fallback y el control de presupuesto.
Si yo mismo desplegara LiteLLM para un equipo pequeño, lo haría así:
- VPS: empezar con 2 núcleos y 4GB
- Despliegue: Docker Compose + PostgreSQL
- Entrada: Caddy HTTPS
- Puerto: 4000 escuchando solo en 127.0.0.1
- Base de datos: no expuesta a internet
- Claves: una clave virtual por proyecto
- Presupuesto: presupuesto pequeño para las claves de desarrollo, límites separados para las claves de producción
- Configuración:
config.yamlen un repositorio privado, claves API reales en.env - Copias de seguridad: respaldar a diario PostgreSQL,
.envyconfig.yaml
Lo que mejor le sienta a LiteLLM no es "quiero montar un sitio web de chat", sino "tengo varias aplicaciones que necesitan llamar a varios modelos, pero no quiero que cada aplicación gestione su propio conjunto de claves API y adaptaciones de modelos".
A medida que aumentan los proveedores de modelos, un punto de entrada unificado ahorrará cada vez más trabajo. Dedica ahora media hora a montar la puerta de enlace y, más adelante, al cambiar de modelo, añadir presupuestos o revisar facturas, te ahorrarás muchos problemas.