−25%

no Windows com pagamento anual, até 31/10. Ver planos

EQVPS
Começar

VPS para Langfuse: o que seus agentes de IA fizeram

Hospede o Langfuse você mesmo e rastreie cada chamada ao LLM e cada passo de ferramenta dos seus agentes. Docker Compose testado, RAM real e o plano certo.

Um agente que trabalha às três da manhã sem ninguém olhando vale tanto quanto a sua capacidade de reconstruir depois o que ele fez. «Queimou US$ 38 em tokens durante a noite» é uma manhã ruim. «Queimou US$ 38 porque uma ferramenta de busca devolveu uma página vazia e o planejador tentou de novo 400 vezes» é um bug que você corrige antes do almoço. A segunda frase exige traces.

O Langfuse registra cada chamada ao LLM, cada prompt, passo de ferramenta, contagem de tokens e latência como uma árvore em que dá para clicar. Hospedado por você, esses prompts e respostas — que muitas vezes trazem dados de clientes, saídas de API e algum segredo perdido — ficam num servidor que você controla, e não no painel de outra pessoa.

Quanto custa manter no ar

O Langfuse v4 não é um binário pequeno, e sim seis contêineres: o app web, um worker em segundo plano, Postgres, ClickHouse para os eventos, Redis e MinIO para os arquivos. Instalamos num servidor de teste e medimos cerca de 3,5 GB de RAM em uso com um projeto vazio. Quem cresce é o ClickHouse, porque é lá que vai parar cada span que você envia.

CargaPlano
Alguns agentes, semanas de tracesMedium-IP: 6 vCPU, 6 GB, 45 GB ($20/mês)
Uma frota de agentes, meses de históricoPlanos Pro, a partir de 32 GB de RAM — sob consulta

Em planos menores ele instala e depois sofre assim que o ClickHouse e o worker querem memória ao mesmo tempo. Eu não ficaria abaixo de 6 GB.

Onde vivem os agentes? Se rodam em outras máquinas, escolha um plano com IPv4 próprio: eles precisam de um endpoint HTTPS, e num plano NAT o endereço de saída não é seu e de fora só se chega à porta SSH. Se os agentes rodam neste mesmo servidor, o Langfuse nunca precisa encarar a internet: para um teste basta o Medium com NAT ($12/mês). São duas localizações, Alemanha e Finlândia; a disponibilidade aparece na hora do pedido. Escolha a mais próxima dos agentes, não de você. Os servidores são pagos em cripto, sem KYC.

Instalação

Num servidor Ubuntu 24.04 ou Debian 12 recém-criado, como root. Primeiro o Docker:

curl -fsSL https://get.docker.com | sh

Depois o Langfuse, com segredos de verdade no lugar dos valores padrão do arquivo compose:

git clone --depth 1 https://github.com/langfuse/langfuse.git
cd langfuse

PG=$(openssl rand -hex 16); MINIO=$(openssl rand -hex 16)
cat > .env <<EOF
NEXTAUTH_URL=https://langfuse.example.com
NEXTAUTH_SECRET=$(openssl rand -hex 32)
SALT=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$PG
DATABASE_URL=postgresql://postgres:$PG@postgres:5432/postgres
CLICKHOUSE_PASSWORD=$(openssl rand -hex 16)
MINIO_ROOT_PASSWORD=$MINIO
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=$MINIO
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY=$MINIO
LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY=$MINIO
REDIS_AUTH=$(openssl rand -hex 16)
TELEMETRY_ENABLED=false
EOF
chmod 600 .env

Duas dessas senhas andam em par: a do Postgres também fica dentro de DATABASE_URL, e a do MinIO precisa bater com as três linhas S3_..._SECRET_ACCESS_KEY. Por isso cada uma vem de uma única variável.

Agora a armadilha. O arquivo compose publica o app web na porta 3000 e o MinIO na 9090 em todas as interfaces, e portas publicadas pelo Docker passam por cima do ufw. Prenda as duas ao localhost para que o proxy reverso seja a única entrada:

sed -i 's/- 3000:3000/- 127.0.0.1:3000:3000/; s/- 9090:9000/- 127.0.0.1:9090:9000/' docker-compose.yml
docker compose up -d
curl -s http://127.0.0.1:3000/api/public/health

O último comando deve mostrar {"status":"OK", ...}. A primeira inicialização roda as migrações do banco; no nosso teste, o health check passou uns 15 segundos depois que os contêineres subiram.

HTTPS na frente

Aponte langfuse.example.com para o IP do servidor e então:

apt install -y caddy
cat > /etc/caddy/Caddyfile <<'EOF'
langfuse.example.com {
    reverse_proxy 127.0.0.1:3000
}
EOF
systemctl reload caddy
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable

O Caddy obtém o certificado sozinho. Abra o site, crie sua conta (ela vira a primeira organização), adicione um projeto e copie as chaves pública e secreta dele.

Depois, feche a porta ao sair. O Langfuse entende AUTH_DISABLE_SIGNUP, mas o arquivo compose padrão não a repassa ao contêiner web, então é preciso uma linha a mais sob langfuse-web:

sed -i 's|^      NEXTAUTH_SECRET: \(.*\)$|      NEXTAUTH_SECRET: \1\n      AUTH_DISABLE_SIGNUP: ${AUTH_DISABLE_SIGNUP:-false}|' docker-compose.yml
echo "AUTH_DISABLE_SIGNUP=true" >> .env
docker compose up -d

A partir daí, uma tentativa de cadastro recebe «Sign up is disabled». Colegas você adiciona de dentro do projeto.

Enviando traces de um agente

O SDK Python envolve suas funções, e chamadas aninhadas viram spans aninhados:

python3 -m venv venv && . venv/bin/activate
pip install langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_BASE_URL=https://langfuse.example.com
from langfuse import get_client, observe

langfuse = get_client()  # lê as variáveis LANGFUSE_*

@observe(name="fetch-prices")
def fetch_prices(pair: str) -> dict:
    return {"pair": pair, "bid": 64210.5}

@observe(name="nightly-agent-run")
def run() -> str:
    data = fetch_prices("BTC/USDT")
    return f"done: {data['pair']}"

print(run())
langfuse.flush()  # scripts curtos terminam antes de o envio em segundo plano acabar

Não pule LANGFUSE_BASE_URL. Sem ela, o SDK manda tudo em silêncio para a nuvem do Langfuse, suas chaves não existem lá e você fica olhando para um painel vazio.

Para conferir pelo terminal que os spans chegaram:

curl -s -u "$LANGFUSE_PUBLIC_KEY:$LANGFUSE_SECRET_KEY" \
  "$LANGFUSE_BASE_URL/api/public/v2/observations?limit=5"

No v4, o antigo endpoint /api/public/traces responde com um erro sobre o modo events-only. Isso é esperado, não uma instalação quebrada. Num agente de verdade você envolve do mesmo jeito a chamada ao LLM e cada ferramenta; além disso, o Langfuse tem integrações para os SDKs de LLM e frameworks de agentes mais comuns, então muitas vezes basta trocar um import em vez de espalhar decoradores por tudo.

O que acompanhar

  • Disco. O ClickHouse e o MinIO guardam tudo o que você envia. docker system df -v mostra para onde foi o espaço. Se você rastreia prompts e respostas longos, os 45 GB do Medium-IP enchem em semanas, não em anos. Confira uma vez por mês; quando ficar apertado, um plano Pro com 400 GB ou mais está sob consulta.
  • Atualizações. O arquivo compose fixa a versão major (:4). docker compose pull && docker compose up -d traz as correções dentro dela. Leia o changelog antes de trocar de versão major: foi justamente na v4 que o endpoint de traces sumiu.
  • Backups. O que importa vive em volumes do Docker: o Postgres guarda usuários, projetos e chaves; o ClickHouse e o MinIO, os traces. Copie-os para fora do servidor de forma agendada.

Vale $20 por mês? Se os seus agentes gastam mais do que isso em tokens — e a maioria dos agentes sem supervisão gasta —, saber para onde foram os tokens se paga na primeira vez que um loop sai do controle. Um agente pequeno que roda uma vez por dia não precisa de nada disso: um arquivo de log e um contador de tokens bastam.

Relacionados

Pronto para implantar? Pague com cripto, sem KYC — online em cerca de um minuto.

Implantar agora →

FAQ

Quanta RAM o Langfuse auto-hospedado precisa?

No nosso servidor de teste, o Langfuse v4 rodou como seis contêineres — web, worker, Postgres, ClickHouse, Redis e MinIO — e usou cerca de 3,5 GB de RAM com um projeto vazio. O ClickHouse cresce a cada span que você envia. O Medium-IP (6 GB de RAM, 45 GB de disco) aguenta com folga alguns agentes; uma frota inteira com meses de histórico precisa de um plano Pro, disponível sob consulta.

Preciso de um IP dedicado para o Langfuse?

Só se os seus agentes rodam em outro lugar e mandam traces pela internet: eles precisam de um endpoint HTTPS, e um plano NAT só aceita de fora a sua porta SSH. Se os agentes ficam no mesmo servidor, o Langfuse pode ficar em localhost e você abre o painel por um túnel SSH; para isso basta o plano Medium com NAT.

O código roda, mas o painel continua vazio. Por quê?

Quase sempre falta LANGFUSE_BASE_URL. Sem ela, o SDK manda tudo para a nuvem do Langfuse, suas chaves auto-hospedadas não existem lá e nada chega ao seu servidor. Coloque o seu próprio endereço na variável.

O endpoint /api/public/traces retorna erro. A instalação está quebrada?

Não. O Langfuse v4 roda num modo events-only em que esse endpoint fica desativado. Leia os dados por /api/public/v2/observations: foi com essa chamada que conferimos que nossos spans de teste tinham chegado.

Como impeço estranhos de se cadastrarem na minha instância?

O Langfuse lê AUTH_DISABLE_SIGNUP, mas o docker-compose.yml padrão não repassa a variável para o contêiner web, então colocá-la só no .env não adianta. Adicione uma linha ao ambiente do langfuse-web (o comando está mais abaixo), defina true depois de criar sua conta e os cadastros seguintes recebem «Sign up is disabled».

Comentários

Nenhum comentário ainda. Seja o primeiro.

Deixe um comentário

Os comentários são moderados antes de aparecerem.