Por qué autoalojar LocalAI en un VPS
Mientras Ollama se centra en el texto, LocalAI apunta a una compatibilidad amplia con la API de OpenAI: expone /v1/chat/completions, /v1/embeddings, /v1/images/generations e incluso la transcripción de audio, en una sola API. Para un equipo que ya tiene código escrito contra el SDK de OpenAI, LocalAI es un reemplazo casi transparente: cambia la URL base y la clave, y el resto funciona. En un VPS obtiene esa polivalencia sin dependencia externa ni coste por llamada. Resulta especialmente pertinente cuando necesita a la vez generación de texto, vectores para RAG y, puntualmente, imágenes, sin multiplicar proveedores ni claves.
Los beneficios concretos de un LocalAI autoalojado
- Reemplazo directo de la API de OpenAI: ninguna reescritura del código cliente.
- Una sola API para el chat, los embeddings, las imágenes y el audio.
- Soporte de múltiples backends (llama.cpp, diffusers, whisper) bajo una interfaz unificada.
- Formatos de modelos abiertos (GGUF) descargables e intercambiables.
- Sin facturación por uso: un coste VPS fijo para todos los tipos de generación.
- Datos y generaciones conservados íntegramente en su servidor.
Requisitos de hardware y software
Como LocalAI es polivalente, sus necesidades dependen de las funciones activadas. Las cifras siguientes son mínimos medidos — un VPS más potente reduce los tiempos de respuesta sin cambiar la viabilidad.
Solo texto, CPU, modelo 7B (p. ej. Mistral-7B-GGUF): 8 GB de RAM, 4 vCPU, 30 GB de disco. A este tamaño, una llamada a /v1/chat/completions tarda entre 5 y 15 segundos según la cuantización (Q4 es el equilibrio estándar). Un modelo 3B cabe en 4 GB de RAM.
Texto + imágenes (7B + Stable Diffusion): 16 GB de RAM, GPU recomendada, 50 GB de disco. Sin GPU, generar una imagen tarda varios minutos en CPU — prefiera un VPS con GPU para un uso habitual y la opción SINGLE_ACTIVE_BACKEND=true para evitar la saturación al combinar chat e imágenes en el mismo host CPU.
Software requerido: Docker 24+ y Docker Compose v2 (docker compose sin guión), un subdominio dedicado (p. ej. ia.su-dominio.com), el puerto 443 abierto, un registro DNS apuntando a la IP del VPS.
Desplegar LocalAI con Docker Compose y HTTPS
Preparar la estructura de directorios
Por SSH:
mkdir -p /opt/localai/{models,config} && cd /opt/localai. La carpetamodelsrecibirá los archivos GGUF;configrecibirá los manifiestos YAML que describen cada modelo a LocalAI.Crear el archivo docker-compose.yaml
Cree
/opt/localai/docker-compose.yamlcon el siguiente contenido:services: localai: image: localai/localai:latest-cpu restart: unless-stopped ports: - "127.0.0.1:8080:8080" volumes: - ./models:/build/models - ./config:/build/models environment: - MODELS_PATH=/build/models - SINGLE_ACTIVE_BACKEND=true - API_KEY=su-clave-secreta healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/readyz"] interval: 30s retries: 3Reemplace
latest-cpuporlatest-gpu-nvidia-cuda-12si su VPS dispone de una GPU NVIDIA.API_KEYactiva la protección por token en todos los endpoints — sin esta variable, la API es accesible sin autenticación.Iniciar el contenedor
Ejecute
docker compose up -d, luego siga los logs de arranque:docker compose logs -f localai. Espere el mensajeLocalAI API is listening on [::]:8080antes de continuar.Descargar un primer modelo desde la galería
La galería de LocalAI agrupa más de 200 modelos preconfigurados. Para instalar Mistral-7B-Instruct cuantizado Q4:
curl http://127.0.0.1:8080/models/apply \ -H 'Authorization: Bearer su-clave-secreta' \ -d '{"id": "huggingface@thebloke__mistral-7b-instruct-v0.2-gguf/mistral-7b-instruct-v0.2.Q4_K_M.gguf"}'Siga el progreso:
curl http://127.0.0.1:8080/models/jobs/<job-id>. El GGUF se descarga en./models/y su manifiesto YAML se crea automáticamente en./config/.Añadir un modelo de embeddings
Para RAG, instale
all-MiniLM-L6-v2(84 MB, 256 MB de RAM):# config/all-minilm.yaml name: all-minilm backend: bert-embeddings parameters: model: all-MiniLM-L6-v2.ggufDescargue el GGUF manualmente en
./models/desde HuggingFace, luego reinicie:docker compose restart localai. Verifique concurl http://127.0.0.1:8080/v1/models.Activar Whisper para la transcripción de audio
Añada
config/whisper.yaml:name: whisper-1 backend: whisper parameters: model: whisper-base.enEl modelo whisper-base (~142 MB) se descarga automáticamente en la primera llamada. Pruebe con:
curl http://127.0.0.1:8080/v1/audio/transcriptions \ -H 'Authorization: Bearer su-clave-secreta' \ -F [email protected] -F model=whisper-1Configurar el reverse proxy Nginx y SSL
Cree
/etc/nginx/sites-available/localai:server { listen 443 ssl; server_name ia.su-dominio.com; ssl_certificate /etc/letsencrypt/live/ia.su-dominio.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ia.su-dominio.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_read_timeout 300s; proxy_send_timeout 300s; } }Obtenga el certificado con
certbot certonly --nginx -d ia.su-dominio.com, luegonginx -s reload. El timeout elevado es necesario para las inferencias largas en CPU.Probar la API vía HTTPS
Valide el despliegue completo:
curl https://ia.su-dominio.com/v1/chat/completions \ -H 'Authorization: Bearer su-clave-secreta' \ -H 'Content-Type: application/json' \ -d '{"model": "mistral-7b-instruct-v0.2.Q4_K_M", "messages": [{"role": "user", "content": "Hola"}]}'Una respuesta JSON con un campo
choicesconfirma que el despliegue funciona correctamente.
Active solo los backends que necesite. Cargar a la vez un modelo de chat, un modelo de embeddings y Stable Diffusion en un VPS CPU satura la RAM y hunde el rendimiento. Defina SINGLE_ACTIVE_BACKEND=true para mantener un único backend residente a la vez, y reserve la generación de imágenes a un VPS GPU si se convierte en un uso habitual.
Elegir y cargar sus modelos
LocalAI soporta varios formatos, pero el formato GGUF (producido por llama.cpp) es el estándar recomendado para CPU: está cuantizado (reduce el uso de RAM), es portable y está bien soportado por la galería.
GGUF vs otros formatos: los formatos GGUF son los únicos cargables directamente vía llama.cpp sin conversión previa. Los modelos Diffusers (imágenes) y ONNX (embeddings ligeros) tienen sus propios backends y no son intercambiables con los GGUF.
Galería vs descarga manual: la galería es la opción más sencilla — descarga el GGUF y genera el YAML de configuración automáticamente. Para un modelo no listado en la galería (un modelo ajustado, un GGUF personalizado), deposite el archivo en ./models/ y cree el YAML manualmente:
name: mi-modelo
backend: llama
parameters:
model: mi-modelo.Q4_K_M.gguf
context_size: 4096Listar los modelos cargados:
curl https://ia.su-dominio.com/v1/models \
-H 'Authorization: Bearer su-clave-secreta'Los modelos cuyo YAML está presente en ./config/ aparecen en la lista, incluso si su GGUF aún no se ha descargado — en ese caso, la primera llamada desencadena la descarga.
Conectar sus aplicaciones a LocalAI
Al ser LocalAI compatible con la API de OpenAI, migrar una aplicación existente se reduce a dos cambios: la URL base y la clave.
Python (openai SDK):
import openai
client = openai.OpenAI(
base_url="https://ia.su-dominio.com/v1",
api_key="su-clave-secreta"
)
response = client.chat.completions.create(
model="mistral-7b-instruct-v0.2.Q4_K_M",
messages=[{"role": "user", "content": "Resume este texto: ..."}]
)
print(response.choices[0].message.content)Node.js (openai SDK):
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://ia.su-dominio.com/v1',
apiKey: 'su-clave-secreta'
});
const completion = await client.chat.completions.create({
model: 'mistral-7b-instruct-v0.2.Q4_K_M',
messages: [{ role: 'user', content: 'Hola' }]
});
console.log(completion.choices[0].message.content);curl directo:
curl https://ia.su-dominio.com/v1/embeddings \
-H 'Authorization: Bearer su-clave-secreta' \
-H 'Content-Type: application/json' \
-d '{"model": "all-minilm", "input": "Texto a vectorizar"}'Las bibliotecas LangChain, LlamaIndex y la mayoría de los frameworks RAG aceptan un parámetro openai_api_base o base_url — el cambio es idéntico.
Solución de problemas: errores comunes
404 model not found o model not loaded: el nombre de modelo pasado en model: no coincide con ningún manifiesto YAML en ./config/. Compruebe con GET /v1/models: el nombre mostrado debe usarse exactamente tal cual. Si el modelo no aparece, verifique que el YAML esté en la carpeta montada y reinicie el contenedor.
Inferencia muy lenta o killed (OOM): el modelo supera la RAM disponible. Un modelo 7B Q4 requiere aproximadamente 6 GB de RAM libre en el momento de la carga. Compruebe con docker stats localai durante una inferencia. Soluciones: pasar a una cuantización más ligera (Q3_K_S o Q2_K), reducir el context_size en el YAML, o actualizar el VPS.
SINGLE_ACTIVE_BACKEND error: LocalAI está configurado con SINGLE_ACTIVE_BACKEND=true y una petición intenta cargar un segundo modelo mientras otro está activo. Es el comportamiento esperado en CPU. Espere a que termine la primera inferencia, o desactive la opción si su VPS tiene suficiente RAM para varios modelos simultáneos.
GPU no detectada (CUDA device not found): verifique que está usando la imagen latest-gpu-nvidia-cuda-12, que el driver NVIDIA está instalado en el host (nvidia-smi), y que el contenedor tiene acceso a la GPU (gpus: all en docker-compose.yaml bajo la clave deploy:). Sin estas tres condiciones, LocalAI vuelve silenciosamente a CPU.
401 Unauthorized: la variable API_KEY está definida en docker-compose.yaml pero la cabecera Authorization: Bearer <clave> está ausente o incorrecta en la llamada. Todos los endpoints, incluido /v1/models, requieren la cabecera en cuanto API_KEY está establecido.
LocalAI frente a Ollama frente a vLLM: ¿qué servidor LLM elegir?
Desplace la tabla
| LocalAI | Ollama | vLLM | |
|---|---|---|---|
| GPU requerida | No (CPU por defecto) | No (CPU por defecto) | Sí (GPU obligatoria) |
| API compatible con OpenAI | Sí (completa) | Sí (parcial) | Sí (completa) |
| Generación de imágenes | Sí (Stable Diffusion) | No | No |
| Transcripción de audio | Sí (Whisper) | No | No |
| Embeddings nativos | Sí | Sí | Sí |
| Biblioteca de modelos | Más de 200 modelos GGUF | Lista de modelos seleccionados | Modelos HuggingFace |
| Rendimiento (tokens/s, 7B) | ~10-20 CPU / ~80+ GPU | ~15-25 CPU / ~80+ GPU | ~150+ solo GPU |
| RAM (modelo 7B Q4) | ~6 GB | ~6 GB | ~14 GB (FP16) |
| Caso de uso principal | API unificada multimodal | Inferencia de texto simple | Producción de alto rendimiento |