faer.grok

Запускаем self-hosted database-версию LobeChat

LobeChat - очень классный UI для общения с LLM-моделями, как локально запущенными(через ollama например), так и с онлайн-провайдерами(Openrouter, OpenAI и тд). Мне же он был нужен из-за возможности рендеринга latex, так как Lmarena и Gemini AI Studio не умеют его рендерить и читать ответ модельки в их интерфейсе неудобно. Ладно, хватит хвалить, начнём делать!

Шаг 0. Установка Docker Compose

Инструкция тута: тык

Нужные файлы

Заведи какую-нибудь папку для этих файлов и создай файлы docker-compose.yml и .env в ней, ниже идут шаблоны этих файлов, сохрани их содержимое в этих файлах, в процессе подготовки LobeChat мы будем их заполнять.

docker-compose.yml

Будем запускать LobeChat с помощью Docker Compose. Для этого нам нужно будет сначала заполнить файлик docker-compose.yml, вот он:

name: lobe-chat-database
services:
lobe:
image: lobehub/lobe-chat-database
container_name: lobe-chat
ports:
- '4142:<выбери свободный локальный порт сервера>'
env_file:
- .env
restart: always

По факту тебе нужно просто выбрать какой-то локальный порт, он пригодится при настройке веб-сервера, остальное оставляй как есть.

Файлик .env

Для docker-compose.yml ещё нужен файлик конфигурации .env, вот он:

# Обязательный параметр: домен LobeChat для tRPC вызовов
# Убедись, что этот домен в белом списке в настройках CORS твоего NextAuth провайдера и S3-сервиса
APP_URL=https://<твой_домен>/

# Конфигурация Postgres
# Обязательный параметр: секретный ключ для шифрования приватной информации. Можно сгенерировать командой: openssl rand -base64 32
KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ=
# Обязательный параметр: строка подключения к БД Postgres
# Формат: postgresql://username:password@host:port/dbname
# Если запустил БДшку в Docker, то можешь использовать имя контейнера как хоста
DATABASE_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/lobe

# Конфигурация NEXT_AUTH
# Поддерживает auth0, Azure AD, GitHub, Authentik, Zitadel, Logto и тд
# Как называются переменные у других провайдеров: https://lobehub.com/docs/self-hosting/advanced/auth#next-auth
# Если у тебя есть ACCESS_CODE(пароль для админского доступа, была в конфиге версии LobeChat без БД), удали его. Мы используем NEXT_AUTH в качестве единственного способа аутентификации.
# Обязательный параметр: секретный ключ NextAuth, опять же генерируется командой: openssl rand -base64 32
NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg
# Обязательный параметр: Укажи наименования провайдера аутентификации(например, Logto, в туториале будем использовать его)
NEXT_AUTH_SSO_PROVIDERS=logto
# Обязательный параметр: NextAuth URL для коллбеков от провайдера
NEXTAUTH_URL=https://<твой_домен>/api/auth

# Конфигурация NextAuth провайдера(в нашем случае Logto)
# Для других провайдеров можно чекнуть тут переменные: https://lobehub.com/docs/self-hosting/environment-variables/auth
AUTH_LOGTO_ID=YOUR_LOGTO_ID
AUTH_LOGTO_SECRET=YOUR_LOGTO_SECRET
AUTH_LOGTO_ISSUER=https://lobe-auth-api.example.com/oidc

# Настройки прокси (если нужны)
# HTTP_PROXY=http://localhost:7890
# HTTPS_PROXY=http://localhost:7890

# Конфигурация S3 (на примере Tebi)
# Обязательный параметр: S3 Access Key ID
S3_ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY_ID
# Обязательный параметр: S3 Secret Access Key
S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
# Обязательный параметр: S3 Endpoint для server/client соединений с S3 API
S3_ENDPOINT=https://s3.tebi.io
# Обязательный параметр: название S3 Bucket
S3_BUCKET=lobe
# Обязательный параметр: публичный домен S3 для клиентского доступа к загруженным файлам(вообще небезопасно, мы будем генерить временные ссылки вместо этого, но если нужно, можно настроить(в Cloudflare есть такая фича, в Tebi не нашёл))
S3_PUBLIC_DOMAIN=https://s3.tebi.io
# Необязательно: S3 Enable Path Style
# Используй 0 для популярных S3 провайдеров; используй 1 для self-hosted MinIO
# Подробнее: https://lobehub.com/docs/self-hosting/advanced/s3#s-3-enable-path-style
S3_ENABLE_PATH_STYLE=0
# Указываем LobeChat, что S3 bucket закрыт от посторонних глаз и нужно генерить временные ссылки
S3_SET_ACL=0
# Другие базовые переменные(если нужны)
# Подробнее: https://lobehub.com/docs/self-hosting/environment-variables/basic
# Примечание: Для локальных версий LobeChat API должен поддерживать embedding модели (точнее, OpenAI text-embedding-3-small) для обработки файлов. Так то и без этого будет работать, только pdfки загрузить в чат не сможете, с фотками всё ок
# Модель для эмбеддингов не нужно прописывать в OPENAI_MODEL_LIST
# А вообще всё это можно будет прописать в web морде, правда закрепится конфигурация за конкретным пользователем, а не у всех пользователей, как лучше/удобнее решай сам
# OPENAI_API_KEY=sk-xxxx
# OPENAI_PROXY_URL=https://api.openai.com/v1
# OPENAI_MODEL_LIST=...

Готовим бэкенд(локальный)

Домен

Можно получить домен на DuckDNS. Логинимся, создаём субдомен, после создания вводим IP сервера.

Предполагается, что IP белый, если это не так, то нужно пробросить порты и сделать автообновление IP в DuckDNS

Получаем SSL-сертификат

  1. Устанавливаем certbot: sudo apt install certbot
  2. sudo certbot -d <твой домен> --manual --preferred-challenges dns certonly
  3. certbot выдал строку/значение ресурсной записи TXT типа, которую нам нужно будет указать в DNS(что-то типо такого: VHaDQNmoNVAgFFhkf34oQTCEsgp_m6WO44oygWpoSFY)
  4. Собираем ссылку: https://www.duckdns.org/update?domains=<твой домен>&token=<твой token(на главной страние под словом DuckDNS)>&txt=<строка, которую выдал certbot>&verbose=true и открываем её в браузере
  5. Продолжаем процесс создания сертификата в certbot
  6. Дожидаемся сообщения об успешном создании сертификата и завершения работы certbot

Иногда DuckDNS шалит из-за чего сертификат не выдаётся, поэтому при получении ошибки об отсутствии TXT записи нужно подождать некоторое время и снова запустить процесс создания сертификата

Запускаем Nginx

  1. Устанавливаем nginx sudo apt install nginx
  2. Удаляем example конфигурацию: sudo rm -rf /etc/nginx/sites-enabled/*
  3. Создаём свою конфигурацию:
    sudo nano /etc/nginx/sites-available/lobechat и вставляем следующее:
server {
listen <выбранный внешний порт> ssl;
server_name <твой домен>;

ssl_certificate /etc/letsencrypt/live/<твой домен>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<твой домен>/privkey.pem;

location / {
proxy_pass http://localhost:<выбранный свободный локальный порт сервера>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Активируем конфигурацию:

sudo ln -s /etc/nginx/sites-available/lobechat /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload-or-restart nginx

Включам nginx на постоянной основе:

sudo systemctl enable nginx

Готовим бэкенд(удалённый)

Нам понадобится:
(в скобках указаны сервисы с free-tier, ресурсов которых нам должно хватить с головой для личного использования)

  1. PostgreSQL БД (Neon.tech)
  2. Хранилище, поддерживающее S3 (Tebi)
  3. Провайдер для аутентификации, поддерживаемый NextAuth (LogTo)

1. PostgreSQL

Ничего сложного, регаемся на Neon.tech, создаём БД, копируем connection string, добавляем его в переменную DATABASE_URL в файле .env

2. Logto

Регистрируемся, создаём tenant, переходим на вкладку Applications, создаём приложение, клацаем внизу на кнопку Create app without framework -> Traditional Web, придумываем рандомное имя. Теперь настраиваем приложение:

  1. Redirect URIs: https://<твой_домен>/api/auth/callback/logto
  2. Post sign-out redirect URIs: https://<твой_домен>
  3. CORS allowed origins: https://<твой_домен>

Так, а теперь заполним файлик .env:

AUTH_LOGTO_ISSUER=<значение в поле Issuer endpoint>  
AUTH_LOGTO_ID=<значение в поле App ID>  
AUTH_LOGTO_SECRET=<значение в поле Value в табличке App Secrets>

Возвращаемся к конфигурации на стороне Logto. Если ты не хочешь, чтобы пользователи регистрировались через веб морду LobeChat и нагружали твой сервер, можно отключить регистрацию следующим образом: вкладка Sign-in experience -> подвкладка Sign-up and sign-in -> Advanced options -> переключаем тумблер Enable user registration и делаем его серым. Тогда пользователей можно будет создать на вкладке User management

Tebi (S3 хранилище)

Регаемся в tebi, после успешной регистрации переходим в web-консоли Tebi на вкладку Buckets и создаём bucket(вводим рандомное название бакета и нажимаем ADD BUCKET. После этого нажимаем на кнопку EDIT у созданного бакета, на открывшейся вкладке нажимаем кнопку ADD и ждём, когда создастся ключ. Возможно, нужно будет обновить страницу, чтобы он появился.
Продолжаем заполнять файлик .env:

S3_ACCESS_KEY_ID=<строчка над надписью Key ACL>
S3_SECRET_ACCESS_KEY=<ключ, который открывается при нажатии на кнопку SHOW SECRET>
S3_ENDPOINT=уже вбито в примере конфигурации
S3_BUCKET=<то рандомное название, которое ввели при создании бакета>
S3_PUBLIC_DOMAIN=уже вбито в примере конфигурации
S3_ENABLE_PATH_STYLE=уже вбито
S3_SET_ACL=уже вбито

В web консоли Tebi переходим на вкладку CORS, клацаем на галочку Enable и заполняем конфигурацию CORS так:

<?xml version='1.0' encoding='UTF-8'?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://"твой домен"</AllowedOrigin>
        <AllowedOrigin>https://"твой домен"</AllowedOrigin>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
      	<AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Нажимаем кнопку UPDATE и готово!

Шаг X. Запуск LobeChat

Перейди в папку с файлами конфигурации и запусти в ней команду docker compose up -d. Готово! Теперь можешь открыть LobeChat в браузере по ссылке https://<твой домен>:<выбранный внешний порт>/
Поздравляю, ты справился!🎉