Déployer Langfuse sur AWS EC2
La stack v3 complète en Docker Compose — Postgres, ClickHouse, Redis et MinIO — derrière un reverse proxy HTTPS. De l’instance vide au premier projet tracé.
La stack v3 complète en Docker Compose — Postgres, ClickHouse, Redis et MinIO — derrière un reverse proxy HTTPS. De l’instance vide au premier projet tracé.
Depuis la v3, Langfuse n’est plus un simple conteneur + Postgres. Les traces vivent maintenant dans ClickHouse (une base OLAP colonne), la file d’attente dans Redis, et les payloads bruts dans un stockage S3 — ici MinIO. Six services au total.
ClickHouse est indispensable depuis la v3. S’il manque, le conteneur web redémarre en boucle (il ne peut pas joindre clickhouse:9000). On le met en place à l’étape 04.
Six conteneurs, dont ClickHouse : vise large sur la RAM. En dessous de 4 Go, le démarrage échoue silencieusement.
Évite les instances t4g / Graviton (ARM64) : les images officielles ciblent amd64 et l’ARM provoque des boucles de crash. Reste sur t3.
N’ouvre jamais 3005, 8123 ni 9000 au public : ce sont des ports internes. Pointe aussi un enregistrement DNS A de langfuse.mondomaine.com vers l’IP élastique de l’instance avant l’étape HTTPS.
Une fois connecté en SSH, installe Docker et le plugin Compose via le script officiel.
Docker récent utilise docker compose (avec un espace). Tes commandes docker-compose (avec un tiret) fonctionnent aussi si tu installes l’ancien binaire v1 — dans ce guide on utilise le plugin.
Crée le dossier et le fichier. Voici le compose complet : Postgres, ClickHouse, Redis et MinIO, avec des healthchecks et un démarrage ordonné.
Points clés : le service clickhouse et son volume chdata, des healthchecks sur db et clickhouse, et un depends_on conditionnel (condition: service_healthy) pour que web/worker attendent que les bases soient prêtes.
web et worker lisent tous les deux ce .env. Commence par générer les trois secrets.
NEXTAUTH_URL doit être l’URL HTTPS publique exacte, sinon la connexion casse (redirections OAuth invalides). Et change les mots de passe par défaut (minio, redis, clickhouse) avant toute mise en prod.
Au premier démarrage, le worker applique les migrations ClickHouse — ça peut prendre une à deux minutes. Suis docker compose logs -f web jusqu’à voir le serveur écouter sur le port 3000.
Le web écoute en interne sur 3000 (mappé sur 3005). On ne l’expose pas au monde : le reverse proxy s’en charge à l’étape suivante.
Caddy gère le HTTPS automatiquement (certificat Let’s Encrypt, renouvellement inclus) — c’est le plus simple. On l’ajoute au même compose pour qu’il joigne web en interne.
Retire ensuite le mapping ports: - "3005:3000" du service web (Caddy le joint en interne via web:3000), puis relance : docker compose up -d.
Caddy obtient le certificat tout seul au premier appel sur https://langfuse.mondomaine.com. Si tu préfères Nginx + certbot, le principe est identique : proxy vers web:3000.
Ouvre ton domaine en HTTPS. Le premier compte créé est le tien — crée ensuite une organisation, un projet, et récupère les clés API.
Pour fermer les inscriptions une fois ton compte créé, ajoute AUTH_DISABLE_SIGNUP=true au .env puis relance docker compose up -d.
Presque toujours ClickHouse injoignable. Vérifie que le hostname est bien clickhouse (pas localhost) et que CLICKHOUSE_MIGRATION_URL=clickhouse://clickhouse:9000. Les conteneurs se joignent par leur nom de service sur le réseau Docker.
docker compose down -v supprime les volumes = perte totale des données. Pour juste arrêter, utilise docker compose down sans le -v.
Une stack qui tourne, c’est bien ; une stack qu’on peut restaurer, c’est mieux. Le piège du single-node, c’est que les données sont réparties sur trois systèmes hétérogènes : l’état transactionnel dans Postgres, les traces dans ClickHouse, les payloads bruts dans MinIO. Perdre l’un des trois casse la cohérence. Il faut donc sauvegarder les trois — pas seulement Postgres par réflexe. La doc backups de Langfuse détaille l’approche pour chaque composant.
Le plus simple et le plus fiable : un dump compressé, quotidien, avec rotation. On l’exécute depuis l’hôte, directement dans le conteneur db.
ClickHouse a sa propre commande de sauvegarde native, qui écrit directement vers un bucket S3. C’est bien plus propre qu’un tar du volume chdata (qu’il faudrait faire conteneur arrêté). Attention : la restauration doit viser une version de ClickHouse identique ou compatible.
Si tu restes en single-node Docker sans S3 externe, l’alternative documentée est le snapshot de volume (ou un tar de chdata conteneur arrêté). Le point clé reste : ne mélange pas un dump ClickHouse d’une version avec un binaire d’une autre version majeure.
Les payloads bruts (les événements d’ingestion) atterrissent d’abord dans MinIO avant d’être traités. On les réplique vers un vrai bucket S3 avec le client mc ou aws s3 sync. D’ailleurs, en prod, la doc recommande carrément de remplacer MinIO par S3 natif — un souci de sauvegarde en moins.
Un backup non testé n’est pas un backup. Monte une instance jetable, restaure les trois systèmes dessus, et vérifie qu’un trace existant s’affiche bien dans l’UI. C’est le seul test qui compte.
Le single-node du guide tient très bien pour une équipe et un volume modéré. Quand ça grossit, deux leviers : scaler le worker horizontalement, et donner plus de RAM à ClickHouse. La doc scaling donne des seuils concrets.
ClickHouse se scale surtout verticalement : plus de RAM avant plus de nœuds. Et Langfuse ne supporte pas les clusters multi-shard — le nombre de shards reste à 1, on ajoute des réplicas, pas des shards.
Sur une seule machine on peut déjà lancer plusieurs répliques du worker : elles se partagent la file Redis. Le web, lui, reste derrière le reverse proxy.
La config encryption est claire : les clés d’API LLM et les secrets d’intégration stockés dans Langfuse sont chiffrés avec ENCRYPTION_KEY, et les clés d’API Langfuse sont hachées avec SALT. Ces deux valeurs doivent être générées, secrètes, et surtout stables — si tu perds ENCRYPTION_KEY, tu perds l’accès à tout ce qu’elle a chiffré.
Pour rester dans une même majeure, épingle le tag langfuse/langfuse:3 (et le worker en :3) : les migrations s’appliquent automatiquement au démarrage. Pour un saut de majeure (v2 → v3), suis le guide de migration dédié — ce n’est pas un simple pull.
Avant tout upgrade : sauvegarde Postgres ET ClickHouse. Une migration de schéma qui tourne à moitié sur une base non sauvegardée, c’est le pire scénario. Le schéma ClickHouse n’est pas un contrat stable — il change entre versions.
C’est en ligne. Prochaines étapes : brancher un SDK sur tes agents, monter des dashboards de coût, et mettre en place les backups (pg_dump pour Postgres, snapshots pour ClickHouse et MinIO).
Doc officielle Langfuse ↗