bolt Valebyte VPS від $4/міс — NVMe, запуск за 60 секунд.

Отримати VPS arrow_forward
eco Початковий Туторіал

Langfuse self-hosted: трасування та вартість LLM-запитів

calendar_month Sep 19, 2026 schedule 18 хв. читання visibility 36 переглядів
Langfuse self-hosted: трассировка и стоимость LLM-запросов
info

Потрібен сервер для цього гайду? Ми пропонуємо виділені сервери та VPS у 50+ країнах з миттєвим налаштуванням.

Потрібен сервер для цього гайду?

Розгорніть VPS або виділений сервер за хвилини.

Langfuse self-hosted: трасування та вартість LLM-запитів на власному VPS

TL;DR

Langfuse self-hosted дає змогу збирати трасування LLM-запитів, бачити затримки, помилки, токени та реальну вартість викликів OpenAI, Anthropic, Google, локальних моделей і власних API-шлюзів. У цьому посібнику ви розгорнете Langfuse v3 на Ubuntu VPS через Docker Compose, захистите його HTTPS, підключите сховища даних і налаштуєте резервне копіювання.

  • Langfuse зберігає ланцюжки викликів LLM, промпти, відповіді, usage і метадані користувача.
  • Для невеликих команд достатньо VPS із 4 vCPU, 8 GB RAM і NVMe-диском від 100 GB.
  • Розгортання використовує Docker Engine, PostgreSQL 16, ClickHouse, Redis і Caddy.
  • Секрети зберігаються у файлі .env, а не всередині вихідного коду чи Docker Compose.
  • HTTPS випускається автоматично через Caddy і Let's Encrypt.
  • Для надійної експлуатації потрібно робити резервні копії PostgreSQL, ClickHouse, конфігурації та об'єктного сховища.

Що ми налаштовуємо і навіщо

Langfuse — платформа observability для застосунків із великими мовними моделями. Вона приймає події із SDK, API або інтеграцій із LangChain, LlamaIndex, OpenAI SDK та іншими бібліотеками. Після цього у вебінтерфейсі можна побачити повний шлях одного користувацького запиту: вхідний промпт, проміжні кроки RAG-пайплайна, виклики інструментів, відповідь моделі, витрати токенів, вартість, тривалість і помилки.

Типова проблема AI-застосунку має такий вигляд: користувачі скаржаться на повільні відповіді, рахунки за API зростають, а розробник бачить лише уривчасті логи застосунку. Звичайні логи не пов'язують запит користувача, retrieval із векторної бази, два виклики моделі та фінальну відповідь в одну сутність. Langfuse вирішує це через trace, span і generation: trace описує користувацький сценарій, span — технічний етап, generation — конкретний виклик LLM.

Self-hosted Langfuse особливо корисний, коли промпти або відповіді містять комерційні дані, персональні дані, фрагменти документів клієнтів, вихідний код чи внутрішні знання компанії. За самостійного розгортання події залишаються у вашій інфраструктурі. Назовні надходять лише запити до того провайдера моделі, якого ви вже використовуєте: наприклад, OpenAI, Anthropic або хмарний endpoint локальної моделі.

Що працюватиме після налаштування

  • Створення проєктів, середовищ і API-ключів для development, staging і production.
  • Трасування запитів через Python, TypeScript або OpenTelemetry-сумісні інтеграції.
  • Розрахунок вартості запитів за моделями, вхідними та вихідними токенами.
  • Пошук повільних, помилкових і дорогих запитів.
  • Зберігання промптів із версіями та публікація prompt templates.
  • Оцінювання відповідей вручну, через користувацький feedback або LLM-as-a-judge.
  • Експорт і аналіз даних через PostgreSQL, ClickHouse і API.

Cloud-managed або self-hosted

Критерій Хмарний сервіс Langfuse self-hosted
Швидкість старту Кілька хвилин, інфраструктура вже готова Зазвичай 1–3 години на перший production-інстанс
Контроль над даними Дані зберігаються у зовнішнього оператора Дані перебувають у вашій БД і вашому сховищі
Обслуговування Оновлення та резервні копії виконує сервіс Оновлення, моніторинг і резервні копії виконуєте ви
Кастомізація мережі Обмежена можливостями SaaS Можна використовувати VPN, private network, SSO, reverse proxy
Економіка зі зростанням Залежить від тарифу й обсягу подій Передбачувані витрати на сервери та об'єктне сховище

Self-hosted варіант не скасовує вимог до захисту даних. У Langfuse за замовчуванням можуть зберігатися входи й виходи моделей, а отже, у них можуть опинитися email, телефони, тексти договорів та інші чутливі відомості. До підключення production-трафіку визначте строк зберігання подій, виключіть із логування непотрібні поля та додайте маскування секретів у своєму застосунку.

Практичне правило: надсилайте в Langfuse достатньо контексту для налагодження якості й ціни, але не дублюйте туди паролі, access tokens, номери платіжних карток і необроблені документи, якщо вони не потрібні для аналізу.

Яка VPS-конфігурація потрібна для цього завдання

Langfuse не є одним контейнером. Для нормальної роботи потрібні щонайменше вебзастосунок і worker, PostgreSQL для транзакційних даних, ClickHouse для аналітичних подій і Redis для черг та кешу. На одному VPS це зручно для невеликої команди та помірного обсягу трасувань, але ресурси потрібно закладати із запасом.

Навантаження vCPU RAM NVMe-диск Відповідний сценарій
Мінімальний стенд 2 vCPU 4 GB 60 GB Особисте тестування, до кількох тисяч подій на день
Робочий мінімум 4 vCPU 8 GB 100 GB Невелика команда, RAG або SaaS із десятками тисяч подій на день
Інтенсивна експлуатація 8 vCPU 16–32 GB 250 GB+ Високий потік трасувань, довгі промпти, кілька проєктів

Практична стартова конфігурація — 4 vCPU, 8 GB RAM, 100–160 GB NVMe і канал від 100 Мбіт/с. Такий сервер залишає запас для PostgreSQL і ClickHouse, які чутливі до нестачі пам'яті та повільного диска. Як один із варіантів можна взяти VPS із зазначеними характеристиками, але важливіше перевірити тип диска, доступність резервних копій і локацію сервера.

Чому NVMe важливіший за великий HDD

PostgreSQL постійно записує журнали транзакцій, а ClickHouse створює та зливає частини таблиць. На HDD інтерфейс Langfuse може залишатися доступним, але аналітичні запити, ingestion подій і резервні копії будуть помітно повільнішими. Для production-інстансу використовуйте SSD або NVMe. Почніть зі 100 GB, якщо зберігаєте трасування 30 днів; за зберігання протягом шести місяців, великих payload і тисячах запитів на годину знадобиться значно більше.

Коли потрібен dedicated, а не VPS

Виділений сервер стає виправданим, якщо ви стабільно приймаєте сотні тисяч або мільйони observation-подій на добу, зберігаєте довгі ланцюжки агентів, запускаєте важкі аналітичні запити або маєте ізолювати ресурси бази від сусідніх віртуальних машин. Ще один привід — потреба в 64 GB RAM і кількох швидких NVMe-дисках. До цього моменту простіше масштабувати VPS: збільшити CPU, пам'ять і винести ClickHouse або PostgreSQL на окремий сервер.

Вибір локації

Локація впливає на затримку між вашим застосунком і Langfuse, юридичні вимоги та вартість міжрегіонального трафіку. Якщо backend застосунку працює в європейському дата-центрі, розміщуйте Langfuse в тому самому регіоні: трасування додаватиме мілісекунди, а не десятки мілісекунд. Якщо в подіях присутні дані європейських користувачів, перевірте вимоги GDPR, DPA та внутрішні правила зберігання даних.

Підготовка сервера

Нижче передбачається чистий сервер з Ubuntu 24.04 LTS, публічною IPv4-адресою та доменом, наприклад langfuse.example.com. Для Ubuntu 22.04 команди майже ідентичні. Виконуйте початкове налаштування через консоль провайдера або SSH під користувачем root, потім вимкніть постійну роботу під root.

Створення адміністратора та SSH-доступу

На локальному комп'ютері створіть ключ, якщо його ще немає. Використовуйте сучасний алгоритм Ed25519 і захистіть ключ парольовою фразою.

ssh-keygen -t ed25519 -a 100 -C "admin@langfuse"

Скопіюйте публічний ключ на сервер і увійдіть під root. Замініть IP-адресу на адресу VPS.

ssh-copy-id [email protected]
ssh [email protected]

Створіть окремого користувача, додайте його до групи sudo та підготуйте каталог SSH.

adduser deploy
usermod -aG sudo deploy
install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
chown deploy:deploy /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys

Відкрийте другу SSH-сесію та переконайтеся, що користувач входить за ключем. Не закривайте root-сесію, доки перевірка не завершиться.

ssh [email protected]
sudo whoami

Оновлення системи та базові інструменти

Оновіть пакети до актуального стану. Після оновлення ядра перезавантажте сервер у зручний час.

sudo apt update && sudo apt full-upgrade -y
sudo apt install -y ca-certificates curl gnupg ufw fail2ban unattended-upgrades \
  jq vim htop cron rsync

Перевірте, чи потрібне перезавантаження.

test -f /var/run/reboot-required && echo "Reboot required"
sudo reboot

Firewall і Fail2ban

На сервері мають бути доступні SSH, HTTP і HTTPS. Не публікуйте назовні PostgreSQL, Redis або ClickHouse: вони будуть доступні лише контейнерам у внутрішній Docker-мережі.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Fail2ban обмежить перебір SSH-паролів і шкідливі повторні підключення. Створіть локальну конфігурацію, не редагуючи файл пакета безпосередньо.

sudo tee /etc/fail2ban/jail.d/sshd.local > /dev/null <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
EOF

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Після підтвердження входу за ключем вимкніть вхід root і автентифікацію паролем. Це зменшує поверхню атаки, але спершу обов'язково переконайтеся, що ваш SSH-ключ працює.

sudo tee /etc/ssh/sshd_config.d/99-hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
EOF

sudo sshd -t && sudo systemctl reload ssh

Також увімкніть автоматичне встановлення security-оновлень. Docker-образи однаково потрібно буде оновлювати окремо, але вразливості базової ОС закриватимуться без ручного втручання.

sudo dpkg-reconfigure --priority=low unattended-upgrades

Встановлення ПЗ — покроково

У цій схемі використовується Docker Engine 28.x або новіше, Docker Compose v2, Langfuse гілки v3, PostgreSQL 16, ClickHouse 24.8 LTS і Redis 7.2. Версії контейнерів слід фіксувати перед production-оновленням: тег latest може призвести до неочікуваної міграції схеми або несумісності.

Встановлення Docker Engine і Compose

Додайте офіційний репозиторій Docker для Ubuntu. Команда встановлює Docker Engine, CLI, Buildx і Compose plugin.

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo 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" | \
  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

Дозвольте користувачеві deploy запускати Docker без sudo. Членство в групі Docker фактично надає адміністративні можливості на сервері, тому додавайте туди лише довірених користувачів.

sudo usermod -aG docker deploy
newgrp docker
docker version
docker compose version

Створення робочої директорії

Зберігайте Compose-файл, змінні оточення, Caddyfile і скрипти поруч, у каталозі, доступному користувачеві розгортання. Дані баз будуть розміщені в Docker volumes.

sudo install -d -m 750 -o deploy -g deploy /opt/langfuse
cd /opt/langfuse
mkdir -p caddy backup scripts
touch .env
chmod 600 .env

Генерація криптографічних секретів

Langfuse використовує окремі секрети для сесій, солі та шифрування. Не використовуйте короткі приклади з документації та не повторюйте один секрет для всіх змінних.

openssl rand -base64 48
openssl rand -hex 32
openssl rand -base64 48
openssl rand -base64 32

Збережіть чотири результати: вони знадобляться в .env. Для паролів PostgreSQL, Redis і ClickHouse створіть окремі випадкові рядки.

openssl rand -base64 32
openssl rand -base64 32
openssl rand -base64 32

Перевірка домену до запуску

Створіть DNS-запис типу A для langfuse.example.com, спрямувавши його на публічний IPv4 сервера. Caddy зможе отримати сертифікат лише якщо порт 80 доступний з інтернету, а DNS уже вказує на цей сервер.

dig +short A langfuse.example.com
curl -4 ifconfig.me

Обидві адреси мають збігтися. Якщо використовується Cloudflare або інший проксі-DNS, під час першого запуску простіше тимчасово вимкнути proxy-режим або переконатися, що HTTP challenge не блокується.

Отримання образів і стартова діагностика

Після створення конфігурації з наступного розділу Docker завантажить потрібні образи. Ця команда попередньо завантажує їх і дає змогу побачити помилки мережі або доступу до registry до запуску.

cd /opt/langfuse
docker compose pull
docker compose config > /tmp/langfuse-rendered-compose.yml
docker compose config --quiet

Конфігурація Langfuse, HTTPS і перевірка

Нижче наведено компактну single-node конфігурацію. Вона підходить для початку роботи та не публікує порти PostgreSQL, ClickHouse або Redis. У зовнішню мережу виходить лише Caddy на портах 80 і 443.

Файл змінних оточення

Відкрийте /opt/langfuse/.env і замініть усі значення-приклади на унікальні. Адреса NEXTAUTH_URL має точно збігатися з публічним URL, включно з https.

cd /opt/langfuse
nano .env
LANGFUSE_DOMAIN=langfuse.example.com

POSTGRES_DB=langfuse
POSTGRES_USER=langfuse
POSTGRES_PASSWORD=REPLACE_WITH_RANDOM_POSTGRES_PASSWORD

CLICKHOUSE_DB=default
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=REPLACE_WITH_RANDOM_CLICKHOUSE_PASSWORD

REDIS_PASSWORD=REPLACE_WITH_RANDOM_REDIS_PASSWORD

NEXTAUTH_URL=https://langfuse.example.com
NEXTAUTH_SECRET=REPLACE_WITH_RANDOM_BASE64_SECRET
SALT=REPLACE_WITH_RANDOM_HEX_SALT
ENCRYPTION_KEY=REPLACE_WITH_RANDOM_BASE64_KEY

DATABASE_URL=postgresql://langfuse:REPLACE_WITH_RANDOM_POSTGRES_PASSWORD@postgres:5432/langfuse
CLICKHOUSE_URL=http://clickhouse:8123
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=REPLACE_WITH_RANDOM_CLICKHOUSE_PASSWORD
REDIS_CONNECTION_STRING=redis://:REPLACE_WITH_RANDOM_REDIS_PASSWORD@redis:6379

TELEMETRY_ENABLED=false

Файл містить паролі, тому не додавайте його до Git, не надсилайте в тікетах і не вставляйте в CI-логи. Перевірте права доступу.

chmod 600 /opt/langfuse/.env
ls -l /opt/langfuse/.env

Docker Compose

Створіть файл /opt/langfuse/docker-compose.yml. Для Langfuse фіксується тег основної гілки 3; перед плановим оновленням замінюйте його на конкретний протестований patch-тег з офіційного registry. Контейнер worker обробляє фонові завдання та має працювати постійно.

cd /opt/langfuse
nano docker-compose.yml
services:
  postgres:
    image: postgres:16.6-bookworm
    restart: unless-stopped
    env_file: .env
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10

  clickhouse:
    image: clickhouse/clickhouse-server:24.8
    restart: unless-stopped
    env_file: .env
    environment:
      CLICKHOUSE_DB: ${CLICKHOUSE_DB}
      CLICKHOUSE_USER: ${CLICKHOUSE_USER}
      CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
    volumes:
      - clickhouse_data:/var/lib/clickhouse
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    healthcheck:
      test: ["CMD-SHELL", "clickhouse-client --query 'SELECT 1'"]
      interval: 15s
      timeout: 10s
      retries: 10

  redis:
    image: redis:7.2-alpine
    restart: unless-stopped
    env_file: .env
    command: >
      redis-server --appendonly yes
      --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD-SHELL", "redis-cli -a \"${REDIS_PASSWORD}\" ping | grep PONG"]
      interval: 10s
      timeout: 5s
      retries: 10

  langfuse-web:
    image: ghcr.io/langfuse/langfuse:3
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      clickhouse:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      NODE_ENV: production
      NEXTAUTH_URL: ${NEXTAUTH_URL}
      NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
      SALT: ${SALT}
      ENCRYPTION_KEY: ${ENCRYPTION_KEY}
      DATABASE_URL: ${DATABASE_URL}
      CLICKHOUSE_URL: ${CLICKHOUSE_URL}
      CLICKHOUSE_USER: ${CLICKHOUSE_USER}
      CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
      REDIS_CONNECTION_STRING: ${REDIS_CONNECTION_STRING}
      TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}
    expose:
      - "3000"

  langfuse-worker:
    image: ghcr.io/langfuse/langfuse:3
    restart: unless-stopped
    command: worker
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      clickhouse:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      NODE_ENV: production
      NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
      SALT: ${SALT}
      ENCRYPTION_KEY: ${ENCRYPTION_KEY}
      DATABASE_URL: ${DATABASE_URL}
      CLICKHOUSE_URL: ${CLICKHOUSE_URL}
      CLICKHOUSE_USER: ${CLICKHOUSE_USER}
      CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
      REDIS_CONNECTION_STRING: ${REDIS_CONNECTION_STRING}
      TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}

  caddy:
    image: caddy:2.8-alpine
    restart: unless-stopped
    depends_on:
      - langfuse-web
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

volumes:
  postgres_data:
  clickhouse_data:
  redis_data:
  caddy_data:
  caddy_config:

У деяких мінорних випусках Langfuse набір параметрів і спосіб запуску worker можуть змінюватися. Перед оновленням звіряйте розділ self-hosting офіційної документації Langfuse і вивід docker compose logs langfuse-web. Не змішуйте нові образи з довільною старою схемою змінних оточення.

Налаштування Caddy і TLS

Caddy автоматично отримує та продовжує TLS-сертифікат Let's Encrypt. Створіть Caddyfile; пошта потрібна центру сертифікації для сповіщень про проблеми із сертифікатом.

cd /opt/langfuse
nano caddy/Caddyfile
{
    email [email protected]
}

langfuse.example.com {
    encode zstd gzip

    reverse_proxy langfuse-web:3000 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }

    log {
        output stdout
        format json
    }
}

Запустіть стек у фоновому режимі. Перший запуск може тривати кілька хвилин: PostgreSQL створює кластер, ClickHouse піднімає таблиці, а Langfuse застосовує міграції.

cd /opt/langfuse
docker compose up -d
docker compose ps
docker compose logs --tail=100 langfuse-web

Перевірка доступності

Перевірте контейнери та HTTPS із самого сервера. Код відповіді 200, 302 або 307 на кореневому URL зазвичай означає, що інтерфейс доступний; конкретний маршрут healthcheck залежить від версії Langfuse.

docker compose ps
curl -I http://127.0.0.1
curl -I https://langfuse.example.com
docker compose logs --tail=100 caddy

Відкрийте https://langfuse.example.com у браузері, створіть першого користувача та організацію. Потім створіть проєкт, наприклад production, і в його налаштуваннях згенеруйте public key та secret key. Secret key відображається обмежено: збережіть його в менеджері секретів застосунку.

Швидкий тест із Python

На машині, де працює ваш AI-застосунок, встановіть актуальний Python SDK Langfuse. У production передавайте ключі через змінні оточення CI/CD, Docker secrets або сховище секретів, а не через вихідний файл.

python3 -m venv .venv
. .venv/bin/activate
pip install --upgrade langfuse openai
export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://langfuse.example.com"
from langfuse import Langfuse

langfuse = Langfuse()

trace = langfuse.trace(
    name="manual-cost-test",
    user_id="demo-user",
    metadata={"environment": "test"}
)

generation = trace.generation(
    name="demo-generation",
    model="gpt-4o-mini",
    model_parameters={"temperature": 0.2},
    input=[{"role": "user", "content": "Скажи привет одним словом"}],
)

generation.end(
    output="Привет!",
    usage={"input": 12, "output": 3, "total": 15}
)

langfuse.flush()

Відкрийте розділ Traces в інтерфейсі. Має з’явитися трасування manual-cost-test з generation і usage. Для автоматичного розрахунку вартості назва моделі має збігатися з моделлю, налаштованою в model definitions Langfuse. Якщо використовується проксі, Azure deployment або локальна модель, створіть власну модель і вкажіть ціну за мільйон вхідних і вихідних токенів.

Бекапи та обслуговування

Знімок VPS корисний, але не замінює незалежний бекап. Він може бути створений уже після помилки, залежати від одного дата-центру або не дозволяти швидко відновити окрему базу. Мінімальна стратегія: щоденний логічний дамп PostgreSQL, резервна копія ClickHouse, копія .env, Caddyfile і даних об'єктного сховища, якщо воно підключене.

Що саме потрібно зберігати

Компонент Що містить Критичність
PostgreSQL Користувачі, проєкти, налаштування, ключі, метадані Критично
ClickHouse Траси, observations, аналітичні дані Критично
.env Паролі, encryption key, URL і параметри підключення Критично, зберігати зашифрованим
Caddy data Сертифікати та стан Caddy Бажано
S3/MinIO Завантажені файли та великі payload, якщо використовуються Залежить від конфігурації

Встановлення restic

Restic шифрує резервні копії на боці сервера та вміє працювати з S3-сумісним сховищем, SFTP або окремою машиною. Не зберігайте єдиний бекап на тому ж VPS, де працює Langfuse.

sudo apt install -y restic
sudo install -d -m 700 -o deploy -g deploy /opt/langfuse/backup
nano /opt/langfuse/backup/restic.env
chmod 600 /opt/langfuse/backup/restic.env

Приклад файлу для S3-сумісного bucket. Підставте свій endpoint, bucket і ключі доступу. Пароль репозиторію має бути окремим від усіх паролів Langfuse.

RESTIC_REPOSITORY=s3:https://s3.example.net/langfuse-backups
RESTIC_PASSWORD=REPLACE_WITH_LONG_UNIQUE_BACKUP_PASSWORD
AWS_ACCESS_KEY_ID=REPLACE_WITH_S3_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_S3_SECRET_KEY

Ініціалізуйте порожній репозиторій один раз.

set -a
. /opt/langfuse/backup/restic.env
set +a
restic init

Скрипт щоденного бекапу

Скрипт створює дамп PostgreSQL, використовує вбудований backup ClickHouse через файлову копію після короткої зупинки сервісу та надсилає результат у restic. Для великих production-баз краще налаштувати ClickHouse Keeper і штатні backup destinations, але для single-node інстансу цей варіант зрозумілий і придатний для регулярного відновлення.

nano /opt/langfuse/scripts/backup-langfuse.sh
chmod 700 /opt/langfuse/scripts/backup-langfuse.sh
#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/opt/langfuse"
BACKUP_DIR="${APP_DIR}/backup/staging"
DATE="$(date +%F-%H%M%S)"

mkdir -p "${BACKUP_DIR}"
cd "${APP_DIR}"

set -a
. "${APP_DIR}/.env"
. "${APP_DIR}/backup/restic.env"
set +a

docker compose exec -T postgres \
  pg_dump -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" \
  -Fc > "${BACKUP_DIR}/postgres-${DATE}.dump"

docker compose stop clickhouse
docker run --rm \
  -v langfuse_clickhouse_data:/source:ro \
  -v "${BACKUP_DIR}:/backup" \
  alpine:3.20 \
  sh -c "tar -czf /backup/clickhouse-${DATE}.tar.gz -C /source ."
docker compose start clickhouse

tar -czf "${BACKUP_DIR}/config-${DATE}.tar.gz" \
  "${APP_DIR}/.env" \
  "${APP_DIR}/docker-compose.yml" \
  "${APP_DIR}/caddy/Caddyfile"

restic backup "${BACKUP_DIR}"
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

rm -f "${BACKUP_DIR}"/

Перевірте скрипт вручну перед додаванням cron. Якщо контейнер ClickHouse великий, зупинка займе час; виконуйте бекап уночі та повідомте команду про коротке вікно недоступності аналітики.

/opt/langfuse/scripts/backup-langfuse.sh
set -a && . /opt/langfuse/backup/restic.env && set +a
restic snapshots
restic check

Додайте щоденний запуск о 03:20 і запис журналу. Редагуйте crontab користувача deploy.

crontab -e
20 3    /opt/langfuse/scripts/backup-langfuse.sh >> /opt/langfuse/backup/backup.log 2>&1

Оновлення та контроль стану

Для одиночного сервера оновлення Langfuse — це maintenance window, а не повноцінний rolling update: веб-інтерфейс та ingestion можуть бути короткочасно недоступні. Спочатку створіть бекап, прочитайте release notes, зафіксуйте поточні версії й лише потім оновлюйте образи.

cd /opt/langfuse
docker compose images
/opt/langfuse/scripts/backup-langfuse.sh
docker compose pull
docker compose up -d
docker compose logs --tail=150 langfuse-web
docker compose ps

Не запускайте без перевірки команду docker system prune -a на production-сервері: вона може видалити потрібні образи та ускладнити відкат. Після оновлення створіть тестову трасу, перевірте вхід в інтерфейс і перегляньте помилки контейнерів.

docker compose logs --since=15m | grep -iE "error|fatal|exception" || true
df -h
docker stats --no-stream

Troubleshooting і FAQ

Чому Caddy не отримує сертифікат і в логах є ACME error?

Спочатку перевірте DNS: команда dig +short A langfuse.example.com має повертати IP вашого сервера. Потім переконайтеся, що UFW дозволяє TCP-порти 80 і 443, а інший веб-сервер не зайняв ці порти: sudo ss -ltnp '( sport = :80 or sport = :443 )'. Якщо увімкнено CDN-проксі, тимчасово перемкніть запис у DNS-only. Також перевірте, що домен не має AAAA-запису, який веде на недоступний IPv6-сервер.

Langfuse відкривається, але після входу виникає нескінченний redirect або помилка сесії. Що робити?

Найчастіше причина — неправильний NEXTAUTH_URL або змінений NEXTAUTH_SECRET. URL має бути публічною адресою з https://, без зайвого шляху та без localhost. Перевірте змінну командою docker compose exec langfuse-web printenv | grep NEXTAUTH, потім перезапустіть контейнер. Не змінюйте NEXTAUTH_SECRET без потреби: це завершить наявні користувацькі сесії.

Чому в інтерфейсі немає трас після надсилання подій із застосунку?

Перевірте три речі: public key, secret key і LANGFUSE_BASE_URL. Ключі мають належати потрібному проєкту, а base URL має вказувати на ваш HTTPS-домен. Потім перегляньте логи worker і web: docker compose logs --tail=100 langfuse-worker. Якщо застосунок перебуває в закритій мережі, перевірте вихідний доступ до домену Langfuse. Для діагностики надішліть мінімальну тестову trace з прикладу вище та викличте langfuse.flush() перед завершенням процесу.

Вартість запитів відображається як нуль або порожнє значення. Чому?

Langfuse може показати usage, але не розрахувати ціну, якщо ім'я моделі невідоме, токени не передано або модель викликана через нестандартний deployment name. Передавайте поля input, output і usage з відповіді провайдера. Потім відкрийте налаштування моделей у проєкті та додайте визначення своєї моделі з тарифом за мільйон input/output tokens. Для Azure OpenAI зазвичай корисно зіставити deployment name з реальною моделлю вручну.

Контейнер ClickHouse постійно перезапускається або серверу бракує пам'яті. Як виправити?

Перевірте причину через docker compose logs clickhouse і dmesg -T | grep -i oom. Повідомлення OOM означає, що ядро вбило процес через нестачу RAM. Для стабільної роботи додайте пам'ять до 8 GB, скоротіть паралельне навантаження та переконайтеся, що на диску достатньо вільного місця. Тимчасовий swap допустимий як аварійний захід, але він не замінює RAM: ClickHouse на swap стає суттєво повільнішим.

Яка конфігурація VPS мінімально підійде?

Для особистого тестового середовища підійде 2 vCPU, 4 GB RAM і 60 GB SSD/NVMe, якщо ви не зберігаєте багато подій і не запускаєте кілька паралельних застосунків. Для реальної команди розумний мінімум — 4 vCPU, 8 GB RAM і 100 GB NVMe. Стежте за docker stats, free -h і df -h у перший тиждень: зростання ClickHouse-data покаже фактичну потребу в диску.

Що вибрати — VPS чи dedicated для цього завдання?

Для старту майже завжди достатньо VPS: він дешевший, швидше масштабується та дозволяє швидко збільшити RAM або диск. Dedicated потрібен за дуже великого потоку telemetry-подій, тривалого зберігання, важких аналітичних вибірок або вимог до апаратної ізоляції. Хороший проміжний етап — залишити веб-застосунок на одному VPS, а PostgreSQL і ClickHouse винести на окремі керовані або виділені вузли. Це простіше, ніж передчасно купувати великий сервер.

Чи можна видалити старі траси та зменшити витрати диска?

Так, але спочатку визначте retention policy: наприклад, 30 днів для сирих production-трас і 90 днів для агрегованої аналітики. Видалення краще виконувати через штатні механізми retention і документацію поточної версії Langfuse, а не вручну видаляти файли з Docker volume. Ручне видалення каталогів ClickHouse пошкодить метадані таблиць. Після налаштування retention контролюйте розмір volumes командою docker system df -v і наявність вільного місця на хості.

Як відновитися з резервної копії?

Розгорніть сумісні версії контейнерів на новому сервері, відновіть .env і Compose-конфігурацію, потім зупиніть сервіси. PostgreSQL-дамп формату custom відновлюється через pg_restore всередині контейнера. Архів ClickHouse слід розпакувати в порожній volume при зупиненому контейнері, а потім запустити ClickHouse. Перед перемиканням DNS обов'язково перевірте вхід, список проєктів і кілька трас на тимчасовому домені або через hosts-файл.

Висновки та наступні кроки

Тепер у вас є self-hosted Langfuse з HTTPS, ізольованими внутрішніми базами, трасуванням LLM-викликів і основою для розрахунку вартості токенів. Така установка допомагає знаходити дорогі промпти, повільні ланцюжки агентів і помилки інтеграцій до того, як вони стануть проблемою для користувачів.

  1. Підключіть SDK до production-застосунку та почніть із трасування одного критичного користувацького сценарію.
  2. Налаштуйте моделі й ціни, потім створіть регулярний звіт щодо вартості на користувача, проєкт або endpoint.
  3. У разі зростання навантаження винесіть ClickHouse і PostgreSQL на окремі вузли, додайте моніторинг диска, пам'яті та успішності бекапів.

Чи був цей гайд корисним?

Ваш відгук допомагає нам покращувати гайди.

Share this post:

Надішліть гайд тому, кому він може стати в пригоді.

Telegram VKVK WhatsApp Facebook LinkedIn XX

langfuse self-hosted: трасування та вартість llm-запитів
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.