−25%

sur Windows en paiement annuel, jusqu'au 31/10. Voir les offres

EQVPS
Commencer

VPS pour Langfuse : ce qu'ont fait vos agents IA

Auto-hébergez Langfuse pour tracer chaque appel LLM et étape d'outil de vos agents sans surveillance. Docker Compose testé, vrais chiffres RAM, offre.

Un agent qui travaille à 3 h du matin sans personne pour le surveiller ne vaut que ce que vaut votre capacité à reconstituer ce qu'il a fait. « Il a brûlé 38 $ de tokens cette nuit », c'est un mauvais matin. « Il a brûlé 38 $ parce qu'un outil de recherche a renvoyé une page vide et que le planificateur a réessayé 400 fois », c'est un bug corrigé avant midi. Pour la deuxième phrase, il faut des traces.

Langfuse enregistre chaque appel LLM, prompt, étape d'outil, nombre de tokens et latence sous forme d'arbre que l'on parcourt en cliquant. Hébergé chez vous, il garde ces prompts et ces réponses — qui contiennent souvent des données clients, des sorties d'API et parfois un secret égaré — sur un serveur que vous contrôlez, plutôt que dans le tableau de bord de quelqu'un d'autre.

Ce que ça coûte à faire tourner

Langfuse v4 n'est pas un petit binaire, mais six conteneurs : l'application web, un worker en arrière-plan, Postgres, ClickHouse pour les événements, Redis et MinIO pour les fichiers. Nous l'avons installé sur un serveur de test et mesuré environ 3,5 Go de RAM avec un projet vide. C'est ClickHouse qui grossit, puisque chaque span envoyé y atterrit.

ChargeOffre
Quelques agents, des semaines de tracesMedium-IP — 6 vCPU, 6 Go, 45 Go (20 $/mois)
Une flotte d'agents, des mois d'historiqueOffres Pro, à partir de 32 Go de RAM — sur demande

Les offres plus petites l'installeront, puis peineront dès que ClickHouse et le worker voudront de la mémoire en même temps. Je ne descendrais pas sous 6 Go.

Où vivent les agents ? S'ils tournent sur d'autres machines, prenez une offre avec sa propre IPv4 : il leur faut un point d'accès HTTPS, et sur une offre NAT l'adresse sortante n'est pas la vôtre et seul le port SSH est joignable de l'extérieur. Si les agents tournent sur ce même serveur, Langfuse n'a jamais besoin de faire face à Internet — Medium en NAT (12 $/mois) suffit pour un essai. Il y a deux localisations, l'Allemagne et la Finlande ; la disponibilité s'affiche à la commande. Choisissez celle qui est proche des agents, pas de vous. Les serveurs se paient en crypto, sans KYC.

Installation

Sur un serveur Ubuntu 24.04 ou Debian 12 tout neuf, en root. D'abord Docker :

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

Puis Langfuse lui-même, avec de vrais secrets à la place des valeurs par défaut du fichier 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

Deux de ces mots de passe ont un partenaire : celui de Postgres figure aussi dans DATABASE_URL, et celui de MinIO doit correspondre aux trois lignes S3_..._SECRET_ACCESS_KEY. C'est pour ça que chacun vient d'une seule variable.

Maintenant, le piège. Le fichier compose publie l'application web sur le port 3000 et MinIO sur le 9090 sur toutes les interfaces, et les ports publiés par Docker contournent ufw. Liez les deux à localhost pour que le reverse proxy reste la seule porte d'entrée :

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

La dernière commande doit afficher {"status":"OK", ...}. Le premier démarrage exécute les migrations de la base ; chez nous, le contrôle de santé est passé environ 15 secondes après le lancement des conteneurs.

HTTPS devant

Faites pointer langfuse.example.com vers l'IP du serveur, puis :

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

Caddy récupère le certificat tout seul. Ouvrez le site, créez votre compte (il devient la première organisation), ajoutez un projet et copiez ses clés publique et secrète.

Ensuite, fermez la porte derrière vous. Langfuse comprend AUTH_DISABLE_SIGNUP, mais le fichier compose fourni ne le transmet pas au conteneur web, il faut donc une ligne de plus sous 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

Désormais, une tentative d'inscription reçoit « Sign up is disabled ». Ajoutez vos collègues depuis le projet.

Envoyer des traces depuis un agent

Le SDK Python enveloppe vos fonctions, et les appels imbriqués deviennent des spans imbriqués :

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()  # lit les variables 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()  # les scripts courts se terminent avant la fin de l'envoi en arrière-plan

Ne sautez pas LANGFUSE_BASE_URL. Sans elle, le SDK envoie discrètement tout vers le cloud de Langfuse, vos clés n'y existent pas, et vous finissez devant un tableau de bord vide.

Pour vérifier depuis le shell que les spans sont arrivés :

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

En v4, l'ancien point d'accès /api/public/traces répond par une erreur sur le mode events-only. C'est normal, l'installation n'y est pour rien. Dans un vrai agent, vous enveloppez de la même façon l'appel au LLM et chaque outil ; Langfuse propose aussi des intégrations pour les SDK LLM et les frameworks d'agents courants, si bien qu'il suffit souvent de changer un import plutôt que de semer des décorateurs partout.

Ce qu'il faut surveiller

  • Le disque. ClickHouse et MinIO gardent tout ce que vous envoyez. docker system df -v montre où est passé l'espace. Si vous tracez de longs prompts et réponses, les 45 Go de Medium-IP se remplissent en quelques semaines, pas en années. Vérifiez chaque mois ; quand vous serez à l'étroit, une offre Pro de 400 Go et plus est disponible sur demande.
  • Les mises à jour. Le fichier compose fige la version majeure (:4). docker compose pull && docker compose up -d apporte les correctifs à l'intérieur de celle-ci. Lisez le changelog avant de changer de version majeure : c'est justement en v4 que le point d'accès des traces a disparu.
  • Les sauvegardes. Ce qui compte vit dans les volumes Docker : Postgres contient utilisateurs, projets et clés, ClickHouse et MinIO les traces. Copiez-les hors du serveur à intervalles réguliers.

Est-ce que ça vaut 20 $ par mois ? Si vos agents dépensent plus que ça en tokens — et la plupart des agents sans surveillance le font —, savoir où sont partis les tokens se rentabilise la première fois qu'une boucle s'emballe. Un petit agent qui tourne une fois par jour n'a besoin de rien de tout ça ; un fichier de log et un compteur de tokens suffisent.

À lire aussi

Prêt à déployer ? Payez en crypto, sans KYC — en ligne en une minute environ.

Déployer →

FAQ

Combien de RAM faut-il pour un Langfuse auto-hébergé ?

Sur notre serveur de test, Langfuse v4 tournait en six conteneurs — web, worker, Postgres, ClickHouse, Redis et MinIO — et occupait environ 3,5 Go de RAM avec un projet vide. ClickHouse grossit à chaque span envoyé. Medium-IP (6 Go de RAM, 45 Go de disque) le fait tourner sans peine pour quelques agents ; toute une flotte d'agents avec des mois d'historique demande une offre Pro, disponible sur demande.

Ai-je besoin d'une IP dédiée pour Langfuse ?

Seulement si vos agents tournent ailleurs et envoient leurs traces par Internet : il leur faut un point d'accès HTTPS, et une offre NAT n'accepte de l'extérieur que votre port SSH. Si les agents vivent sur le même serveur, Langfuse peut rester sur localhost et vous ouvrez le tableau de bord via un tunnel SSH — l'offre Medium en NAT suffit pour ça.

Mon code tourne, mais le tableau de bord reste vide. Pourquoi ?

Presque toujours, il manque LANGFUSE_BASE_URL. Sans elle, le SDK envoie tout vers le cloud hébergé de Langfuse, vos clés auto-hébergées n'y existent pas, et rien n'arrive sur votre serveur. Mettez votre propre adresse dans la variable.

Le point d'accès /api/public/traces renvoie une erreur. L'installation est cassée ?

Non. Langfuse v4 fonctionne en mode events-only, où ce point d'accès est désactivé. Lisez les données via /api/public/v2/observations — c'est l'appel qui nous a permis de vérifier que nos spans de test étaient arrivés.

Comment empêcher des inconnus de s'inscrire sur mon instance ?

Langfuse lit AUTH_DISABLE_SIGNUP, mais le docker-compose.yml fourni ne transmet pas la variable au conteneur web : l'ajouter seulement dans .env ne sert à rien. Ajoutez une ligne à l'environnement de langfuse-web (la commande est plus bas), passez-la à true une fois votre compte créé, et les inscriptions suivantes reçoivent « Sign up is disabled ».

Commentaires

Pas encore de commentaires. Soyez le premier.

Laisser un commentaire

Les commentaires sont modérés avant leur publication.