Tutoriales de VPS
Despliegue de LobeHub (LobeChat) 2.x en un VPS (2026): tutorial completo de Docker, PostgreSQL, almacenamiento de objetos, inicio de sesión y HTTPS
Este tutorial sigue la arquitectura actual de LobeHub 2.x y explica con claridad la configuración del VPS, Docker Compose, la base de datos, el almacenamiento de objetos, el inicio de sesión, HTTPS, las actualizaciones y las copias de seguridad.

Si quieres reunir OpenAI, Claude, Gemini, OpenRouter y modelos locales en una misma interfaz de chat, LobeHub es hoy una de las opciones más populares. Antes se llamaba LobeChat y, a partir de la versión 2.x, cambiaron el nombre del proyecto, las imágenes, el sistema de inicio de sesión y la estructura de despliegue. Muchos tutoriales antiguos que circulan por internet todavía usan lobehub/lobe-chat, NextAuth o comandos de un solo contenedor, y copiarlos tal cual suele dejarte atascado en el inicio de sesión, la base de datos y la subida de archivos.
Esta guía despliega la versión estable v2.2.12 de julio de 2026. El Docker Compose oficial no es solo un contenedor web, sino que también incluye PostgreSQL, Redis, RustFS y SearxNG. El objetivo tampoco es "que la página abra y ya está", sino dejar completos a la vez el dominio, HTTPS, la persistencia de datos, las restricciones de registro, las actualizaciones y las copias de seguridad.
Primero, las conclusiones:
- Si solo te conectas a API de modelos externos, un VPS de 2 núcleos y 4 GB puede servir como punto de partida para uso personal;
- Para varios usuarios, o si subes muchos documentos o bases de conocimiento, se recomiendan 4 núcleos, 8 GB y más de 80 GB de disco;
- Un VPS de CPU normal sirve para ejecutar la interfaz de LobeHub, pero no para ejecutar directamente modelos locales grandes de 7B o 14B;
- Si no quieres mantener la base de datos, el almacenamiento de objetos, el inicio de sesión y las copias de seguridad, usar LobeHub Cloud directamente te ahorrará mucho tiempo.
En julio de 2026, el repositorio oficial ya se trasladó a lobehub/lobehub, y la imagen de Docker es lobehub/lobehub. La versión estable actual es v2.2.12.
Los componentes principales de un despliegue en servidor incluyen:
| Componente | Función | ¿Requiere persistencia? |
|---|---|---|
| LobeHub | Interfaz web, API, Agents y lógica de la base de conocimiento | Configuración gestionada por variables de entorno |
| PostgreSQL | Usuarios, sesiones, Agents, metadatos de archivos | Obligatorio |
| Redis | Almacenamiento de sesiones y caché | Recomendado |
| RustFS | Almacenamiento de objetos compatible con S3 para archivos subidos | Obligatorio |
| SearXNG | Búsqueda web | Conservar según necesidad |
Lo que más se malinterpreta aquí es el "autoalojamiento". Lo que autoalojas es la aplicación LobeHub y la capa de datos. Si te conectas a OpenAI, Anthropic, Google u OpenRouter, los prompts y las solicitudes se siguen enviando al proveedor correspondiente. Solo cuando los modelos también se ejecutan en servicios de inferencia que tú controlas, como Ollama o vLLM, las solicitudes de los modelos no salen de tu entorno.
Lo siguiente son puntos de partida para el despliegue, no promesas de concurrencia. El uso real dependerá del número de usuarios, la cantidad de documentos, la búsqueda web, el crecimiento de la base de datos y dónde se ejecuten los modelos.
| Escenario | Punto de partida recomendado | Notas |
|---|---|---|
| Un solo usuario, solo API externas | 2 núcleos, 4 GB, SSD de 40 GB | El Compose completo funciona, pero no añadas otros servicios pesados |
| 3–10 usuarios, subidas de documentos ocasionales | 4 núcleos, 8 GB, SSD de 80 GB | Deja margen para PostgreSQL, Redis y RustFS |
| Muchas bases de conocimiento y archivos | 4 núcleos, 8 GB o más, almacenamiento de objetos independiente | Los archivos, índices y copias de seguridad consumen disco de forma continua |
| Ejecutar modelos grandes en local | Servidor GPU independiente | Aunque un VPS de CPU pueda cargarlos, la velocidad suele ser poco práctica |
Si aún no has decidido la configuración, puedes empezar por Cómo elegir la configuración de un VPS. Esta guía despliega una pila de servicios completa, así que 1 núcleo y 1 GB queda fuera del rango recomendado.
Tener clara la topología te facilitará mucho la resolución de problemas después:
浏览器
├─ https://ai.example.com -> Caddy -> LobeHub:3210
└─ https://s3.example.com -> Caddy -> RustFS:9000
LobeHub
├─ PostgreSQL:5432
├─ Redis:6379
├─ RustFS:9000
├─ SearXNG:8080
└─ OpenAI / Anthropic / Gemini / OpenRouter / 自建模型 API
PostgreSQL y Redis no deberían exponerse a internet. La API S3 de RustFS necesita ser accesible desde el navegador, así que un subdominio dedicado es lo más claro; el puerto de administración 9001 solo debe enlazarse a localhost y accederse mediante un túnel SSH cuando sea necesario.
Este artículo usa Ubuntu 24.04, Docker Engine, Compose v2 y Caddy. Primero prepara dos registros DNS, ambos apuntando a la IP pública del VPS:
ai.example.com
s3.example.com
Actualiza el sistema e instala las herramientas básicas:
sudo apt update
sudo apt install -y ca-certificates curl git openssl ufw
Instala Docker desde el repositorio oficial:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo docker version
sudo docker compose version
Abre solo SSH, HTTP y HTTPS en el firewall:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Si estás operando por una sesión SSH remota, asegúrate de permitir OpenSSH antes de activar UFW; una vez que la conexión actual sea estable, activa las demás reglas del firewall.
La rama por defecto del repositorio oficial se actualiza muy rápido, así que no ejecutes una instancia de producción directamente sobre canary. Primero descarga la versión estable v2.2.12 en local:
cd /tmp
git clone --depth 1 --branch v2.2.12 \
https://github.com/lobehub/lobehub.git lobehub-v2.2.12
sudo mkdir -p /opt/lobehub
sudo chown "$USER":"$USER" /opt/lobehub
cd /opt/lobehub
Ejecuta el script de inicialización oficial que descargaste en local y dile explícitamente que lea la configuración de v2.2.12:
bash /tmp/lobehub-v2.2.12/docker-compose/setup.sh \
-l zh_CN \
--url https://raw.githubusercontent.com/lobehub/lobehub/v2.2.12
Elige el despliegue con dominio e introduce ai.example.com y s3.example.com. El script descargará docker-compose.yml, .env, la configuración del bucket de RustFS y la configuración de SearXNG, y preparará KEY_VAULTS_SECRET, AUTH_SECRET, la contraseña de la base de datos y la contraseña de RustFS.
No pegues las contraseñas que muestra la terminal en chats, tickets o repositorios Git. Cuando termine la inicialización, haz primero una copia de seguridad de .env y restringe los permisos:
chmod 600 .env
cp .env ".env.initial-$(date +%F-%H%M%S)"
chmod 600 .env.initial-*
El JWKS_KEY del ejemplo oficial es solo un valor de muestra. Siguiendo las indicaciones del script de inicialización, crea un nuevo conjunto de claves en la página oficial de generación de JWKS y luego reemplaza JWKS_KEY en .env. No te saltes este paso.
Por comodidad de depuración, el ejemplo oficial declara puertos del host para PostgreSQL, Redis y RustFS. En un VPS público conviene restringirlo:
- LobeHub:
127.0.0.1:3210:3210 - PostgreSQL: elimina
5432:5432 - Redis: elimina
6379:6379 - API de RustFS:
127.0.0.1:9000:9000 - Administración de RustFS:
127.0.0.1:9001:9001
Al mismo tiempo, fija la imagen de LobeHub a la versión estable verificada en esta guía:
services:
lobe:
image: lobehub/lobehub:v2.2.12
ports:
- "127.0.0.1:3210:3210"
postgresql:
# 删除 ports,数据库只走 lobe-network
redis:
# 删除 ports,Redis 只走 lobe-network
rustfs:
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9001:9001"
Revisa las direcciones externas en .env:
APP_URL=https://ai.example.com
INTERNAL_APP_URL=http://localhost:3210
S3_ENDPOINT=https://s3.example.com
En un despliegue con Compose, INTERNAL_APP_URL debe mantener la dirección interna del contenedor. S3_ENDPOINT no debe incluir la ruta del bucket ni ningún otro sufijo, de lo contrario los archivos subidos no se abrirán. RustFS usa path-style y el Compose oficial ya establece S3_ENABLE_PATH_STYLE=1.
Tras modificarlo, valida primero, no lo inicies directamente:
sudo docker compose config >/tmp/lobehub-compose-rendered.yml
grep -nE "image:|published:|DATABASE_URL|S3_ENDPOINT" \
/tmp/lobehub-compose-rendered.yml
Confirma que el resultado renderizado no escribe secretos por accidente en registros públicos y que no hay 0.0.0.0:5432 ni 0.0.0.0:6379.
Descarga la imagen e inicia:
cd /opt/lobehub
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
El primer arranque debe esperar la comprobación de estado de PostgreSQL, la inicialización de RustFS y las migraciones de la base de datos. Revisa los registros:
sudo docker compose logs --tail=200 lobe postgresql rustfs rustfs-init
Prueba LobeHub primero en local:
curl -I http://127.0.0.1:3210
sudo ss -lntp | grep -E ":3210|:5432|:6379|:9000|:9001"
Normalmente solo 3210, 9000 y 9001 están enlazados a 127.0.0.1, y 5432 y 6379 no deberían aparecer en la lista de puertos públicos a la escucha.
Instala Caddy:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key |
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt |
sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
Edita /etc/caddy/Caddyfile:
ai.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3210
}
s3.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:9000
}
Valida y recarga:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://ai.example.com
curl -I https://s3.example.com
Caddy solicitará los certificados automáticamente. Si falla, comprueba primero si el DNS ya apunta al VPS actual y luego revisa journalctl -u caddy -n 100. Para una configuración y resolución de problemas más completas, consulta Guía completa para usar Caddy como proxy inverso en un VPS.
LobeHub 2.x usa Better Auth. El inicio de sesión con correo y contraseña está activado por defecto y, si no cambias nada, una instancia pública podría permitir que desconocidos se registren.
La forma más sencilla de restringir una instancia personal es permitir solo tu propio correo en .env:
[email protected]
Esta variable solo restringe qué direcciones pueden iniciar sesión o registrarse; no verifica la propiedad del correo. El restablecimiento de contraseña, los enlaces mágicos o la verificación por correo también requieren configurar SMTP.
Si tu equipo usa GitHub, Google, Keycloak u otro SSO de forma uniforme, puedes desactivar el correo y la contraseña:
AUTH_DISABLE_EMAIL_PASSWORD=1
AUTH_SSO_PROVIDERS=github
AUTH_GITHUB_ID=your-github-oauth-client-id
AUTH_GITHUB_SECRET=your-github-oauth-client-secret
Si fallan las devoluciones de llamada de OAuth, comprueba primero si APP_URL coincide exactamente con el dominio al que se accede en el navegador, incluido https://. El NEXT_PUBLIC_AUTH_URL de los tutoriales antiguos está obsoleto y seguir configurándolo provocará fallos de despliegue.
Después de modificar .env, reconstruye el contenedor de la aplicación:
sudo docker compose up -d --force-recreate lobe
sudo docker compose logs --tail=100 lobe
Las claves de API de modelos se pueden escribir en .env o configurar en los ajustes de LobeHub tras iniciar sesión. En instancias de equipo es mejor que un administrador las gestione de forma centralizada, para evitar que cada persona las pegue repetidamente.
Por ejemplo, para conectar OpenAI:
OPENAI_API_KEY=your-openai-api-key
Si usas OpenRouter, LiteLLM u otro servicio compatible con OpenAI, configura la Base URL y la Key según las variables oficiales del proveedor, y no reutilices nombres de variables antiguos por intuición. Si primero quieres unificar varios upstreams en un solo punto de entrada, puedes combinarlo con Montar una puerta de enlace API LLM unificada con LiteLLM en un VPS.
Tras los cambios, reconstruye LobeHub y comprueba tres cosas en la web:
- La lista de modelos carga;
- Una conversación nueva recibe respuestas completas;
- Tras refrescar la página o volver a iniciar sesión, la conversación sigue existiendo.
"La lista de modelos está vacía" normalmente no es un fallo del frontend, sino una API Key, Base URL, lista de modelos permitidos o configuración de proxy de red incorrectas. Revisa directamente los registros de la aplicación:
sudo docker compose logs -f --tail=200 lobe
Sube una imagen pequeña y un documento de prueba, y confirma que los archivos siguen siendo accesibles tras refrescar la página. Si falla, revisa en orden:
curl -I https://s3.example.com
sudo docker compose ps rustfs rustfs-init
sudo docker compose logs --tail=200 rustfs rustfs-init lobe
grep -E "S3_ENDPOINT|RUSTFS_|S3_ENABLE_PATH_STYLE" .env
Los problemas habituales son:
S3_ENDPOINTsigue siendohttp://localhost:9000, así que el navegador no puede acceder en absoluto;- Se añadió por error la ruta del bucket al Endpoint;
- El subdominio de RustFS no tiene HTTPS;
- El puerto 9000 está bloqueado por el firewall o el proxy inverso;
- El Access Key y el Secret Key de
.envno coinciden con los valores de Compose.
No expongas el 9000 directamente a internet solo para ahorrar esfuerzo. Pasar por un subdominio HTTPS dedicado es más fácil de controlar y no provoca errores de contenido mixto en el navegador.
No configures producción para descargar automáticamente latest cada pocos minutos. LobeHub se actualiza rápido y las migraciones de la base de datos también cambian. El proceso seguro es:
cd /opt/lobehub
# 1. 记录当前镜像
sudo docker compose images
# 2. 完成下一节的备份
# 3. 把 docker-compose.yml 中的镜像改成已确认的新版本
sudo docker compose pull lobe
sudo docker compose up -d lobe
# 4. 查看迁移和启动日志
sudo docker compose logs --tail=300 lobe postgresql
Si tras la actualización aparece un error de migración de la base de datos, no reinicies repetidamente sobrescribiendo la situación. Guarda los registros y confirma las notas de migración de las versiones antigua y nueva; cuando necesites revertir, restaura la imagen antigua y la copia de seguridad de la base de datos previa a la actualización. Cambiar solo la etiqueta de la imagen hacia atrás y seguir usando una base de datos ya migrada por la nueva versión puede no funcionar correctamente.
Una restauración completa requiere al menos:
- Datos de PostgreSQL;
- Archivos de objetos de RustFS;
- Datos de Redis (si quieres conservar el estado de la caché de sesiones);
.env, JWKS, Caddyfile y configuración de Compose;- La versión de imagen en uso.
Crea un directorio de copias de seguridad y exporta la base de datos:
cd /opt/lobehub
mkdir -p "backups/$(date +%F)"
sudo docker compose exec -T postgresql \
pg_dump -U postgres -d lobechat -Fc \
>"backups/$(date +%F)/lobehub-postgres.dump"
cp .env docker-compose.yml bucket.config.json searxng-settings.yml \
"backups/$(date +%F)/"
sudo cp /etc/caddy/Caddyfile "backups/$(date +%F)/Caddyfile"
sudo chown -R "$USER":"$USER" backups
chmod 600 "backups/$(date +%F)/.env"
El nombre de base de datos por defecto es lobechat; si cambiaste LOBE_DB_NAME, el comando de exportación también debe cambiar.
RustFS y Redis usan volúmenes de Docker. Primero consulta los nombres reales de los volúmenes:
sudo docker volume ls | grep lobehub
En una breve ventana de inactividad, detén las escrituras y luego empaqueta los volúmenes:
sudo docker compose stop lobe
sudo docker run --rm \
-v lobehub_rustfs-data:/source:ro \
-v "$PWD/backups/$(date +%F)":/backup \
alpine tar -czf /backup/rustfs-data.tar.gz -C /source .
sudo docker run --rm \
-v lobehub_redis_data:/source:ro \
-v "$PWD/backups/$(date +%F)":/backup \
alpine tar -czf /backup/redis-data.tar.gz -C /source .
sudo docker compose up -d
Si docker volume ls muestra nombres distintos, sustituye el comando por los resultados reales. Cuando termine la copia de seguridad, sincroniza el directorio a otra máquina o al almacenamiento de objetos; si las copias de seguridad están en el mismo disco del VPS que los datos de producción, desaparecerán junto con la máquina si esta falla.
Antes de restaurar, ensaya primero en un VPS de prueba. Ejemplo de restauración de la base de datos:
cat lobehub-postgres.dump |
sudo docker compose exec -T postgresql \
pg_restore -U postgres -d lobechat --clean --if-exists
Restaura primero .env y las claves, luego PostgreSQL y los archivos de objetos, y por último inicia LobeHub. Si las claves cambian, aunque la base de datos y los archivos estén presentes, puede que el inicio de sesión falle o que las credenciales guardadas no se puedan descifrar.
Para un proceso de copia de seguridad externa más completo, continúa con Simulacro de copia de seguridad y restauración en un VPS.
sudo docker compose ps
curl -I http://127.0.0.1:3210
sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -n 100 --no-pager
Si el 3210 es accesible en local pero el dominio no, el problema suele estar en DNS, Caddy o el firewall. Si el 3210 tampoco es accesible en local, revisa los registros de LobeHub.
sudo docker compose ps postgresql
sudo docker compose logs --tail=200 postgresql lobe
sudo docker compose exec postgresql \
pg_isready -U postgres -d lobechat
Céntrate en revisar POSTGRES_PASSWORD, LOBE_DB_NAME y el DATABASE_URL renderizado. No abras el 5432 a todo internet solo para depurar.
Revisa APP_URL, AUTH_SECRET, la hora del sistema y las cookies del navegador. Tras cambiar el dominio de HTTP a HTTPS, reconstruye el contenedor de LobeHub para que las variables de entorno surtan efecto realmente:
timedatectl status
grep "^APP_URL=" .env
grep -q "^AUTH_SECRET=." .env && echo "AUTH_SECRET 已设置"
sudo docker compose up -d --force-recreate lobe
No publiques el valor de AUTH_SECRET en registros públicos.
sudo docker compose logs --tail=400 lobe postgresql
sudo docker compose images
Confirma si cruzaste una versión mayor, si falló la migración de la base de datos o si la nueva imagen requiere nuevas variables de entorno. Conserva primero los registros y los datos existentes, y luego decide si continuar la migración o revertir desde la copia de seguridad.
- Tanto
ai.example.comcomos3.example.comson HTTPS; - PostgreSQL y Redis no escuchan en la red pública;
-
.envtiene permisos 600 y las claves no se han subido a Git; -
AUTH_ALLOWED_EMAILSo el SSO ya restringen el registro de desconocidos; - Se han verificado la lista de modelos, la persistencia de conversaciones y la subida de imágenes y documentos;
- La imagen de LobeHub está fijada a una versión confirmada;
- PostgreSQL, RustFS, la configuración y las claves tienen copias de seguridad externas;
- Se ha completado al menos una restauración en un entorno de prueba.
El valor del autoalojamiento de LobeHub es poner el chat, los Agents, los archivos y el punto de entrada multimodelo en una pila de servicios que tú controlas. El coste también es directo: tú eres responsable de la base de datos, el almacenamiento de objetos, el inicio de sesión y las actualizaciones. Para uso personal, empezar con 2 núcleos y 4 GB está bien; para uso formal en equipo, completa primero las restricciones de registro, la copia de seguridad y restauración, y la reversión de actualizaciones, y luego invita a otras personas.