lago Documentation

Open Source Metering and Usage Based Billing API ⭐️ Consumption tracking, Subscription management, Pricing iterations, Payment orchestration & Revenue analytics

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy lago on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name lago -p 8080:8080 --restart always getlago/api:v1.27.1
Configured Services & Ports
⚙️ traefik
image: traefik:v3.3
🔌 Ports: 8080:8080, 443:443
⚙️ db
image: postgres:15-alpine
🔌 Ports: ${POSTGRES_PORT:-5432}:${POSTGRES_PORT:-5432}
⚙️ redis
image: redis:7-alpine
🔌 Ports: ${REDIS_PORT:-6379}:${REDIS_PORT:-6379}
⚙️ rsa-keys
image: getlago/api:v1.27.1
⚙️ migrate
image: getlago/api:v1.27.1
⚙️ api
image: getlago/api:v1.27.1
⚙️ front
image: getlago/front:v1.27.1
⚙️ api-worker
image: getlago/api:v1.27.1
⚙️ api-clock
image: getlago/api:v1.27.1
⚙️ pdf
image: getlago/lago-gotenberg:8.15
docker-compose.yml
yaml (docker-compose.yml)
name: lago-light

volumes:
  lago_rsa_data:
  lago_postgres_data:
  lago_redis_data:
  lago_storage_data:

x-postgres-image: &postgres-image
  image: postgres:15-alpine
x-redis-image: &redis-image
  image: redis:7-alpine
x-backend-image: &backend-image
  image: getlago/api:v1.27.1
x-frontend-image: &frontend-image
  image: getlago/front:v1.27.1

x-lago-domain: &lago-domain
  "LAGO_DOMAIN": ${LAGO_DOMAIN}

# TODO: Use only LAGO_DOMAIN
x-backend-urls: &backend-urls
  "LAGO_FRONT_URL": https://${LAGO_DOMAIN}
  "LAGO_API_URL": https://${LAGO_DOMAIN}/api

x-backend-environment: &backend-env
  "DATABASE_URL": postgresql://${POSTGRES_USER:-lago}:${POSTGRES_PASSWORD:-changeme}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-lago}?search_path=${POSTGRES_SCHEMA:-public}
  "REDIS_URL": redis://${REDIS_HOST:-redis}:${REDIS_PORT:-6379}
  "REDIS_PASSWORD": ${REDIS_PASSWORD:-}
  "LAGO_REDIS_SIDEKIQ_SENTINELS": ${LAGO_REDIS_SIDEKIQ_SENTINELS:-}
  "LAGO_REDIS_SIDEKIQ_MASTER_NAME": ${LAGO_REDIS_SIDEKIQ_MASTER_NAME:-master}
  "LAGO_REDIS_SIDEKIQ_SENTINEL_USERNAME": ${LAGO_REDIS_SIDEKIQ_SENTINEL_USERNAME:-}
  "LAGO_REDIS_SIDEKIQ_SENTINEL_PASSWORD": ${LAGO_REDIS_SIDEKIQ_SENTINEL_PASSWORD:-}
  "SECRET_KEY_BASE": ${SECRET_KEY_BASE:-your-secret-key-base-hex-64}
  "RAILS_ENV": production
  "RAILS_LOG_TO_STDOUT": ${LAGO_RAILS_STDOUT:-true}
  "LAGO_RSA_PRIVATE_KEY": ${LAGO_RSA_PRIVATE_KEY:-}
  "LAGO_SIDEKIQ_WEB": ${LAGO_SIDEKIQ_WEB:-true}
  "LAGO_ENCRYPTION_PRIMARY_KEY": ${LAGO_ENCRYPTION_PRIMARY_KEY:-your-encryption-primary-key}
  "LAGO_ENCRYPTION_DETERMINISTIC_KEY": ${LAGO_ENCRYPTION_DETERMINISTIC_KEY:-your-encryption-deterministic-key}
  "LAGO_ENCRYPTION_KEY_DERIVATION_SALT": ${LAGO_ENCRYPTION_KEY_DERIVATION_SALT:-your-encryption-derivation-salt}
  "LAGO_USE_AWS_S3": ${LAGO_USE_AWS_S3:-false}
  "LAGO_AWS_S3_ACCESS_KEY_ID": ${LAGO_AWS_S3_ACCESS_KEY_ID:-azerty123456}
  "LAGO_AWS_S3_SECRET_ACCESS_KEY": ${LAGO_AWS_S3_SECRET_ACCESS_KEY:-azerty123456}
  "LAGO_AWS_S3_REGION": ${LAGO_AWS_S3_REGION:-us-east-1}
  "LAGO_AWS_S3_BUCKET": ${LAGO_AWS_S3_BUCKET:-bucket}
  "LAGO_AWS_S3_ENDPOINT": ${LAGO_AWS_S3_ENDPOINT:-}
  "LAGO_USE_GCS": ${LAGO_USE_GCS:-false}
  "LAGO_GCS_PROJECT": ${LAGO_GCS_PROJECT:-}
  "LAGO_GCS_BUCKET": ${LAGO_GCS_BUCKET:-}
  "LAGO_FROM_EMAIL": ${LAGO_FROM_EMAIL:-}
  "LAGO_SMTP_ADDRESS": ${LAGO_SMTP_ADDRESS:-}
  "LAGO_SMTP_PORT": ${LAGO_SMTP_PORT:-587}
  "LAGO_SMTP_USERNAME": ${LAGO_SMTP_USERNAME:-}
  "LAGO_SMTP_PASSWORD": ${LAGO_SMTP_PASSWORD:-}
  "LAGO_PDF_URL": http://pdf:3000
  "LAGO_REDIS_CACHE_URL": redis://${LAGO_REDIS_CACHE_HOST:-redis}:${LAGO_REDIS_CACHE_PORT:-6379}
  "LAGO_REDIS_CACHE_PASSWORD": ${LAGO_REDIS_CACHE_PASSWORD:-}
  "LAGO_REDIS_CACHE_SENTINELS": ${LAGO_REDIS_CACHE_SENTINELS:-}
  "LAGO_REDIS_CACHE_MASTER_NAME": ${LAGO_REDIS_CACHE_MASTER_NAME:-master}
  "LAGO_REDIS_CACHE_SENTINEL_USERNAME": ${LAGO_REDIS_CACHE_SENTINEL_USERNAME:-}
  "LAGO_REDIS_CACHE_SENTINEL_PASSWORD": ${LAGO_REDIS_CACHE_SENTINEL_PASSWORD:-}
  "LAGO_REDIS_CABLE_URL": ${LAGO_REDIS_CABLE_URL:-}
  "LAGO_DISABLE_SEGMENT": ${LAGO_DISABLE_SEGMENT:-}
  "LAGO_DISABLE_WALLET_REFRESH": ${LAGO_DISABLE_WALLET_REFRESH:-}
  "LAGO_DISABLE_SIGNUP": ${LAGO_DISABLE_SIGNUP:-false}
  "LAGO_WEBHOOK_ALLOW_PRIVATE_URLS": ${LAGO_WEBHOOK_ALLOW_PRIVATE_URLS:-false}
  "LAGO_OAUTH_PROXY_URL": https://proxy.getlago.com
  "LAGO_LICENSE": ${LAGO_LICENSE:-}
  "LAGO_CREATE_ORG": ${LAGO_CREATE_ORG:-false}
  "LAGO_ORG_USER_PASSWORD": ${LAGO_ORG_USER_PASSWORD:-}
  "LAGO_ORG_USER_EMAIL": ${LAGO_ORG_USER_EMAIL:-}
  "LAGO_ORG_NAME": ${LAGO_ORG_NAME:-}
  "LAGO_ORG_API_KEY": ${LAGO_ORG_API_KEY:-}
  "GOOGLE_AUTH_CLIENT_ID": ${GOOGLE_AUTH_CLIENT_ID:-}
  "GOOGLE_AUTH_CLIENT_SECRET": ${GOOGLE_AUTH_CLIENT_SECRET:-}

x-frontend-environment: &frontend-env
  "API_URL": "https://${LAGO_DOMAIN}"
  "APP_ENV": production
  "LAGO_OAUTH_PROXY_URL": https://proxy.getlago.com

services:
  traefik:
    image: traefik:v3.3
    container_name: lago-traefik
    restart: unless-stopped
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.email=${LAGO_ACME_EMAIL:[email protected]}"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory"
    ports:
      - 8080:8080
      - 443:443
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
      
  db:
    <<: *postgres-image
    container_name: lago-db
    restart: unless-stopped
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pg_isready -U ${POSTGRES_USER:-lago} -d ${POSTGRES_DB:-lago} -h localhost -p ${POSTGRES_PORT:-5432}",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-lago}
      POSTGRES_USER: ${POSTGRES_USER:-lago}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
      PGDATA: /data/postgres
      PGPORT: ${POSTGRES_PORT:-5432}
      POSTGRES_SCHEMA: public
    volumes:
      - lago_postgres_data:/data/postgres
    ports:
      - ${POSTGRES_PORT:-5432}:${POSTGRES_PORT:-5432}
    profiles:
      - all
      - all-no-redis
      - all-no-keys

  redis:
    <<: *redis-image
    container_name: lago-redis
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    command: --port ${REDIS_PORT:-6379}
    volumes:
      - lago_redis_data:/data
    ports:
      - ${REDIS_PORT:-6379}:${REDIS_PORT:-6379}
    profiles:
      - all
      - all-no-pg
      - all-no-keys

  rsa-keys:
    <<: *backend-image
    container_name: lago-rsa-keys
    command: ["./scripts/generate.rsa.sh"]
    volumes:
      - lago_rsa_data:/app/config/keys
    profiles:
      - all
      - all-no-pg
      - all-no-redis
      - all-no-db

  migrate:
    <<: *backend-image
    container_name: lago-migrate
    restart: no
    depends_on:
      db:
        condition: service_healthy
        restart: true
        required: false
    command: ["./scripts/migrate.sh"]
    volumes:
      - lago_rsa_data:/app/config/keys
    environment:
      <<: *backend-env

  api:
    <<: *backend-image
    container_name: lago-api
    restart: unless-stopped
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy
        restart: true
        required: false
      redis:
        condition: service_healthy
        restart: true
        required: false
    command: ["./scripts/start.api.sh"]
    healthcheck:
      test: curl -f http://localhost:3000/health || exit 1
      interval: 10s
      start_period: 30s
      timeout: 60s
      start_interval: 2s
    environment:
      <<: [*backend-env, *backend-urls]
    volumes:
      - lago_storage_data:/app/storage
      - lago_rsa_data:/app/config/keys
    labels:
      - "traefik.enable=true"

      # API Routes
      - "traefik.http.routers.lago-api.priority=100"
      - "traefik.http.routers.lago-api.entrypoints=websecure"
      - "traefik.http.routers.lago-api.rule=Host(`${LAGO_DOMAIN}`) && PathPrefix(`/api/`)"
      - "traefik.http.routers.lago-api.middlewares=lago-api-stripprefix"
      - "traefik.http.middlewares.lago-api-stripprefix.stripprefix.prefixes=/api"
      - "traefik.http.routers.lago-api.tls.certresolver=letsencrypt"
      - "traefik.http.routers.lago-api.service=lago-api-service"
      - "traefik.http.services.lago-api-service.loadbalancer.server.port=3000"

      # API Versioned Routes
      - "traefik.http.routers.lago-api-versioned.priority=110"
      - "traefik.http.routers.lago-api-versioned.entrypoints=websecure"
      - "traefik.http.routers.lago-api-versioned.rule=Host(`${LAGO_DOMAIN}`) && PathPrefix(`/api/v`)"
      - "traefik.http.routers.lago-api-versioned.tls.certresolver=letsencrypt"
      - "traefik.http.routers.lago-api-versioned.service=lago-api-service"

      # API Rails Assets
      - "traefik.http.routers.lago-api-rails.priority=100"
      - "traefik.http.routers.lago-api-rails.entrypoints=websecure"
      - "traefik.http.routers.lago-api-rails.rule=Host(`${LAGO_DOMAIN}`) && PathPrefix(`/rails`)"
      - "traefik.http.routers.lago-api-rails.tls.certresolver=letsencrypt"
      - "traefik.http.routers.lago-api-rails.service=lago-api-service"

      # GraphQL Routes
      - "traefik.http.routers.lago-graphql.priority=100"
      - "traefik.http.routers.lago-graphql.entrypoints=websecure"
      - "traefik.http.routers.lago-graphql.rule=Host(`${LAGO_DOMAIN}`) && Path(`/graphql`)"
      - "traefik.http.routers.lago-graphql.tls.certresolver=letsencrypt"
      - "traefik.http.routers.lago-graphql.service=lago-api-service"

  front:
    <<: *frontend-image
    container_name: lago-front
    restart: unless-stopped
    depends_on:
      api:
        condition: service_healthy
        restart: true
    environment:
      <<: [*frontend-env]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.lago-front.priority=50"
      - "traefik.http.routers.lago-front.entrypoints=websecure"
      - "traefik.http.routers.lago-front.rule=Host(`${LAGO_DOMAIN}`)"
      - "traefik.http.routers.lago-front.tls.certresolver=letsencrypt"
      - "traefik.http.services.lago-front.loadbalancer.server.port=80"
      

  api-worker:
    <<: *backend-image
    container_name: lago-worker
    restart: unless-stopped
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy
        restart: true
        required: false
      redis:
        condition: service_healthy
        restart: true
        required: false
    command: ["./scripts/start.worker.sh"]
    healthcheck:
      test: curl -f http://localhost:8080 || exit 1
      interval: 10s
      start_period: 30s
      timeout: 60s
      start_interval: 2s
    environment:
      <<: [*backend-env, *backend-urls]
    volumes:
      - lago_storage_data:/app/storage
      - lago_rsa_data:/app/config/keys

  api-clock:
    <<: *backend-image
    container_name: lago-clock
    restart: unless-stopped
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy
        restart: true
        required: false
      redis:
        condition: service_healthy
        restart: true
        required: false
    command: ["./scripts/start.clock.sh"]
    volumes:
      - lago_rsa_data:/app/config/keys
    environment:
      <<: [*backend-env, *backend-urls]

  pdf:
    image: getlago/lago-gotenberg:8.15
    command:
      - gotenberg
      - --libreoffice-disable-routes=true
      - --chromium-ignore-certificate-errors=true
      - --chromium-disable-javascript=true
      - --api-timeout=300s

File: README.md


See Lago price an AI workload

Run the maintained demo from this repository:

bash
./examples/agentic-ai-demo/run.sh

It starts the Lago version that matches this checkout, creates a disposable local organization, and prices three illustrative AI requests. Each request sends one input-token event and one output-token event:

text
3 AI requests
5,000 input tokens  x $0.000002 = $0.01
1,250 output tokens x $0.000008 = $0.01
Lago usage total                   = $0.02

Docker Compose starts an isolated Lago service, then a small script seeds and verifies the example through Lago's API. It retrieves current usage, independently reconciles the result, and retries one transaction to confirm that usage does not increase. Everything stays on your machine; the demo does not access Lago Cloud. The bundled credentials and API key are disposable and only intended for this local demo.

Log into http://localhost:8080 with [email protected] / agentic-ai-demo-local-password, then open Customers → Agentic AI Demo Customer → Agentic AI Demo subscription → Usage.

Requirements: Docker, curl, and jq. If ports 8080 or 3001 are occupied, set LAGO_DEMO_UI_PORT and LAGO_DEMO_API_PORT before running. The demo keeps Lago running so you can inspect the customer, metrics, plan, subscription, events, and usage in the UI. Remove its isolated Compose project and data volume when you are done:

bash
./examples/agentic-ai-demo/run.sh --cleanup

Use Claude Code, Codex, or Cursor

Open this repository in your coding agent and paste:

text
Run Lago's maintained Agentic AI demo by following this README. Keep it local;
do not modify source files or unrelated Docker resources. When it passes, give
me the UI URL, token usage and charges, idempotency evidence, and cleanup
command. Then offer to connect this agent to Lago's local MCP server.

What is Lago?

Lago is the programmable system between product usage and revenue. Send events from your application, turn them into billable metrics, apply pricing and entitlements, then generate invoices and collect payments.

text
Usage events -> Metering -> Pricing and credits -> Entitlements -> Invoices -> Payments -> Revenue

Use Lago to launch and change pricing without rebuilding billing:

  • tokens by model, input, output, cache, reasoning, or tool call
  • GPU, CPU, storage, and other compute consumption
  • API calls, transactions, seats, active users, or custom events
  • prepaid credits with automatic top-ups
  • subscriptions with allowances, minimum commitments, and overages
  • self-serve plans and negotiated enterprise contracts in the same system

Lago is headless and API-first. Your application, internal tools, and agents use the same billing primitives through the REST API, SDKs, webhooks, and MCP server. Product, finance, and operations teams can use the Lago UI when a human interface is faster.

How Lago fits into your stack

Lago keeps metering and pricing independent from payment processing. Connect Stripe, Adyen, GoCardless, or another provider without making its product catalog your source of truth.

Lago Direct and Lago Embedded

The same Lago engine supports two operating models:

Lago Direct Lago Embedded
Who monetizes You monetize your own product Your customers monetize through your platform
Experience Your application and teams use Lago through APIs, agent interfaces, and Lago UI Your customers use billing capabilities inside your product through APIs and white-label interfaces
Brand Lago powers your billing stack Lago stays behind the scenes under your brand
Public example Mistral AI PayPal

Lago Direct is the standard way to use Lago: send your own product usage, model your pricing, and bill your customers. Lago Embedded uses the same primitives to let platforms, marketplaces, AI builders, fintech products, and developer tools offer metering and billing to their customers.

Both models start with Lago's open-source billing engine and can be paired with Premium deployment, customization, security, and support options. With Lago Embedded, you control the customer experience and which capabilities your users can access.

Agentic-first by design

Agentic-first means Lago's billing model is available as structured, inspectable interfaces instead of being trapped in a dashboard.

Interface What it enables Availability
REST API and OpenAPI Program every core billing workflow and generate typed clients or tools from the schema Open source
Lago MCP server Give an MCP-compatible agent tools to read and write invoices, usage, customers, payments, credit notes, coupons, and other Lago primitives Open source, MIT
Lago Agent SDK for Python Wrap supported LLM clients, normalize usage, and send token or model-cost events without blocking the LLM call Open source, MIT
Lago Agent SDK for JavaScript and TypeScript Instrument OpenAI, Anthropic, Mistral, Gemini, and AWS Bedrock clients with under 5 ms p99 wrapper overhead Open source, MIT
Finance Assistant Ask read-only questions about billing, usage, and revenue in plain language Beta, early access
Billing Assistant Query billing data and run operations in natural language, with confirmation for important or destructive actions Premium beta, available upon request

The MCP server exposes read and write tools and inherits the permissions of its Lago API key. Treat agent credentials as privileged, control who can access the agent, review tool calls, and keep human confirmation around sensitive billing changes.

Platform

Layer Capabilities
Meter usage Real-time event ingestion, filters, dimensions, custom aggregations, batch ingestion, and idempotency by transaction_id
Model pricing Usage-based, recurring, prepaid, percentage, graduated, package, volume, minimum-commitment, and hybrid charges
Control access Entitlements, allowances, wallets, credit grants, top-ups, and usage alerts
Bill customers Subscriptions, invoices, credit notes, taxes, multiple currencies, multiple entities, and customer-specific overrides
Collect revenue Payment-provider orchestration, retries, dunning, and payment-status synchronization
Understand revenue Usage, MRR, invoice, customer, and revenue analytics
Connect the stack Salesforce, HubSpot, NetSuite, Xero, Avalara, cloud marketplaces, data warehouses, and webhooks
Lago Direct Meter and bill your own customers through Lago APIs, agent interfaces, and UI
Lago Embedded White-label metering and billing for platforms, marketplaces, AI builders, and fintech products

Explore metering, billing and invoicing, entitlements, cash collection, revenue analytics, and integrations.

Production characteristics

  • Idempotent ingestion. Lago deduplicates usage events by transaction_id, so retrying an event does not bill it twice. Read the ingestion guide.
  • Atomic batches. If one event in a batch is invalid, Lago rejects the batch and persists none of its events. Read the batch API reference.
  • Asynchronous processing. Dedicated workers can isolate events, billing, payments, invoices, webhooks, PDFs, alerts, and analytics as volume grows. Review the architecture.
  • Observable operation. Lago exposes Prometheus metrics for APIs, queues, workers, events, billing, webhooks, and dependencies. Review monitoring.
  • Deployment control. Run Lago locally, in your cloud, or on your infrastructure. Production deployments can separate and scale stateful services and workers independently.
  • Security. Lago is SOC 2 Type II certified and supports self-hosting for teams that need infrastructure and data control. Review security.

Chosen by teams operating at scale

Mistral AI, Groq, PayPal, Synthesia, Blacksmith, and other teams have publicly selected Lago for billing. The figures below describe the companies using Lago, not volume processed by Lago.

Company Lago use Public company context
Mistral AI Token metering, prepaid credits, invoicing, taxes, and payment collection for paid AI products Reported at more than $400M in annualized revenue run rate
Groq Lago customer More than 5M developers and trillions of AI tokens processed weekly
Blacksmith Usage-based billing for compute-intensive CI workloads More than 6,000 companies; raised a $45M Series B at a $550M valuation
Synthesia Lago customer Approximately $140M ARR
PayPal Embedded, usage-based billing for merchants More than 430M active accounts worldwide

Sources for company context: Mistral AI, Groq, Blacksmith, Synthesia, and PayPal.

Open source and managed options

Option Best for Access
Lago open source Teams that want to inspect, extend, and operate the billing platform on their infrastructure This repository, AGPLv3
Agent tooling Teams that want to meter LLM usage or expose billing primitives to agents Separate open-source Agent SDK and MCP repositories, MIT
Lago Cloud Teams that want Lago to operate the platform and provide commercial support Talk to us
Premium capabilities Teams that need selected assistants, enterprise integrations, governance, or embedded use cases Availability varies by feature; talk to us

Deploy Lago

For a source-based local deployment:

bash
git clone --depth 1 https://github.com/getlago/lago.git
cd lago

echo "LAGO_RSA_PRIVATE_KEY=\"$(openssl genrsa 2048 | openssl base64 -A)\"" >> .env
docker compose up -d

Use the self-hosted deployment guide for persistent storage, SMTP, TLS, object storage, Redis, database configuration, and upgrades. For larger deployments, use the Lago Helm charts and configure dedicated workers.

SDKs and developer resources

Language Client
Node.js lago-javascript-client
Python lago-python-client
Ruby lago-ruby-client
Go lago-go-client

Contributing

Lago is built in the open. Read the contributing guide and development environment setup to get started.

Look for issues labeled beginner or help-wanted, or join the Lago Slack community.

License

The Lago platform is distributed under the AGPLv3 license. Read why Lago chose AGPLv3. Lago's Agent SDKs and MCP server are distributed from separate repositories under the MIT license.

Analytics and tracking

Self-hosted Lago instances collect basic product analytics by default. Lago does not collect customer PII or financial data through this tracking. Review what is collected or opt out.


File: deploy/README.md

Lago Deploy

This repository contains the necessary files to deploy the Lago project.

Docker Compose Local

To deploy the project locally, you need to have Docker and Docker Compose installed on your machine.
This configuration can be used for small production usages but it's not recommended for large scale deployments.

Get Started

  1. Get the docker compose file
bash
curl -o docker-compose.yml https://raw.githubusercontent.com/getlago/lago/main/deploy/docker-compose.local.yml
  1. Run the following command to start the project:
bash
docker compose up --profile all

# If you want to run it in the background
docker compose up -d --profile all

Docker Compose Light

This configuration provide Traefik as a reverse proxy to ease your deployment.
It supports SSL with Let's Encrypt. :warning: You need a valid domain (with at least one A or AAA record)!

  1. Get the docker compose file
bash
curl -o docker-compose.yml https://raw.githubusercontent.com/getlago/lago/main/deploy/docker-compose.light.yml
curl -o .env https://raw.githubusercontent.com/getlago/lago/main/deploy/.env.light.example
  1. Replace the .env values with yours
bash
LAGO_DOMAIN=domain.tld
[email protected]
  1. Run the following command to start the project
bash
docker compose up --profile all

# If you want to run it in the background
docker compose up -d --profile all

Docker Compose Production

This configuration provide Traefik as a reverse proxy to ease your deployment.
It supports SSL wth Let's Encrypt. :warning: You need a valid domain (with at least one A or AAA record)!
It also adds multiple services that will help your to handle more load.
Portainer is also packed to help you scale services and manage your Lago stack.

bash
curl -o docker-compose.yml https://raw.githubusercontent.com/getlago/lago/main/deploy/docker-compose.production.yml
curl -o .env https://raw.githubusercontent.com/getlago/lago/main/deploy/.env.production.example
  1. Replace the .env values with yours
bash
LAGO_DOMAIN=domain.tld
[email protected]
PORTAINER_USER=lago
PORTAINER_PASSWORD=changeme
  1. Run the following command to start the project
bash
docker compose up --profile all

# If you want to run it in the background
docker compose up -d --profile all

Configuration

Profiles

The docker compose file contains multiple profiles to enable or disable some services.
Here are the available profiles:

  • all: Enable all services
  • all-no-pg: Disable the PostgreSQL service
  • all-no-redis: Disable the Redis service
  • all-no-keys: Disable the RSA keys generation service

This allow you to start only the service you want to use, please see the following sections for more information.

bash
# Start all services
docker compose up --profile all

# Start without PostgreSQL
docker compose up --profile all-no-pg

# Start without Redis
docker compose up --profile all-no-redis

# Start without PostgreSQL and Redis
docker compose up --profile all-no-db

# Start without RSA keys generation
docker compose up --profile all-no-keys

# Start without PostgreSQL, Redis and RSA keys generation
docker compose up

PostgreSQL

It is possible to disable the usage of the PostgreSQL database to use an external database instance.

  1. Set those environment variables:
  • POSTGRES_USER
  • POSTGRES_PASSWORD
  • POSTGRES_DB
  • POSTGRES_HOST
  • POSTGRES_PORT
  • POSTGRES_SCHEMA optional
  1. Run the following command to start the project without PostgreSQL:
bash
docker compose up --profile all-no-pg

Redis

It is possible to disable the usage of the Redis database to use an external Redis instance.

  1. Set those environment variables:
  • REDIS_HOST
  • REDIS_PORT
  • REDIS_PASSWORD optional
  1. Run the following command to start the project without Redis:
bash
docker compose up --profile all-no-redis

RSA Keys

Those docker compose file generates an RSA Keys pair for the JWT tokens generation.
You can find the keys in the lago_rsa_data volume or in the /app/config/keys directory in the backends containers.
If you do not want to use those keys:

  • Remove the lago_rsa_data volume
  • Generate your own key using openssl genrsa 2048 | openssl base64 -A
  • Export this generated key to the LAGO_RSA_PRIVATE_KEY env var.
  • Run the following command to start the project without the RSA keys generation:
bash
docker compose up --profile all-no-keys

All BE Services use the same RSA key, they will exit immediately if no key is provided.

Monitoring

For production deployments, we recommend setting up monitoring for Sidekiq workers. See the Monitoring documentation for:

  • Prometheus metrics endpoints and available metrics
  • Recommended alerting rules
  • Grafana dashboard recommendations

File: docker/README.md

Lago Docker Image

This is the official one docker image for Lago.

This docker image is designed for testing and staging environments only. It is not recommended for production use due to its simplified architecture and resource constraints. For production deployments, please refer to our deployment guides in the deploy folder or use our helm chart for a more robust and scalable setup.

Features

This docker image embed everything to run Lago with just one command line to ease the deployment.
Here are the services that are running into the container :

  • PostgreSQL
  • Redis
  • Lago UI
  • Lago API
  • Lago Worker
  • Lago Clock
  • PDF Service (optional)

Get Started

bash
docker run -d --name lago -p 80:80 -p 3000:3000 getlago/lago:latest

PDF generation is disabled by default. We use Gotenberg, which is only available as a Docker image. To enable PDF generation, use the following command:

bash
docker run -d --name lago -v /var/run/docker.sock:/var/run/docker.sock -p 80:80 -p 3000:3000 getlago/lago:latest

You will see an other docker container named lago-pdf running.

Using External Services

You can use external services for the database and Redis instance.
Here are the env var you should pass to the container to use them :

Env Var Description Default
DATABASE_URL The URL of the database postgres://lago:lago@localhost:5432/lago
REDIS_URL The URL of the Redis instance redis://localhost:6379/0

Storage

The container is using a volume to store the data, you can mount it to your host to keep the data safe.
You can find many folders for each services in the /data folder.

SSL

SSL is disabled by default in this development/staging image. To enable SSL support when using a proxy or load balancer:

For new installations:

  • Add the environment variable LAGO_DISABLE_SSL=false when running the container
    bash
    docker run -e LAGO_DISABLE_SSL=false ...

For existing installations:

  • Navigate to your /data volume
  • Edit the .env file to change LAGO_DISABLE_SSL=true to LAGO_DISABLE_SSL=false

:warning: Note that this only enables SSL support - you must still configure SSL certificates and termination through your reverse proxy or load balancer.

Logs

Database Logs (creation, migration) are stored in the /data/db.log file.
Applicative logs are streamed to the standard output.

Contributing

This docker image is a work in progress.
Feel free to open issues or PRs to improve it or ask for new features.


File: events-processor/README.md

Lago Events Processor

High throughput events processor for Lago.
This service is in charge of providing a post-process for events in high volume scenarios.

This service need to be configured with Clickhouse and Redpanda. Please contact us for further informations.

How to run it

With the docker compose environment:

shell
go build -o event_processors .

./event_processors

Development

Running

shell
lago up -d events-processor

Testing

shell
lago exec events-processor go test ./...

Configuration

This app requires some env vars

Variable Description
ENV Set as production to not load .env file
DATABASE_URL PostgreSQL server URL (eg: postgresql://lago_user:lago_password@lago_server:5432/lago_db)
LAGO_KAFKA_BOOTSTRAP_SERVERS Kafka Brokers list URL with port (eg: "redpanda:9092,kafka:9092")
LAGO_KAFKA_RAW_EVENTS_TOPIC Events Kafka Topic (eg: events_raw)
LAGO_KAFKA_ENRICHED_EVENTS_TOPIC Events Enriched Kafka Topic (eg: events_enriched)
LAGO_KAFKA_ENRICHED_EVENTS_EXPANDED_TOPIC Events Enriched Expanded Kafka Topic (eg: events_enriched_expanded)
LAGO_KAFKA_EVENTS_CHARGED_IN_ADVANCE_TOPIC Events Charge In Advance Kafka Topic (eg: events_charge_in_advance)
LAGO_KAFKA_EVENTS_DEAD_LETTER_TOPIC Events Dead Letter Queue (eg: events_dead_letter)
LAGO_KAFKA_CONSUMER_GROUP Kafka Consumer Group Name for Post Processing
LAGO_REDIS_STORE_URL Redis URL to store subscription refresh IDs
LAGO_REDIS_CACHE_URL Redis URL to store charge usage cache entries

Additionally there's a few optional environment variables

Variable Description
LAGO_REDIS_STORE_DB Redis database number to use for the store (default: 0)
LAGO_REDIS_STORE_PASSWORD Password for the Redis store (if required)
LAGO_REDIS_STORE_TLS Redis TLS configuration for the Redis store (default: false)
LAGO_REDIS_CACHE_DB Redis database number to use for the cache (default: 0)
LAGO_REDIS_CACHE_PASSWORD Password for the Redis cache (if required)
LAGO_REDIS_CACHE_TLS Redis TLS configuration for charge usage cache entries (default: false)
LAGO_KAFKA_TLS Set to true if your broker uses TLS termination
LAGO_KAFKA_SCRAM_ALGORITHM Your Broker SCRAM algo, supported values are SCRAM-SHA-256 and SCRAM-SHA-512. If you provide a SCRAM Algo, LAGO_KAFKA_USERNAME and LAGO_KAFKA_PASSWORD are required
LAGO_KAFKA_USERNAME If your broker needs auth, your Kafka Username
LAGO_KAFKA_PASSWORD If your broker needs auth, your Kafka password
OTEL_SERVICE_NAME OpenTelemetry service name (eg: events-processor)
OTEL_EXPORTER_OTLP_ENDPOINT OpenTelemetry server URL. Setting this environment variable will enable tracing
OTEL_INSECURE Set to true to use the insecure mode of OpenTelemetry
LAGO_USE_MEMORY_CACHE Use the new in memory cache instead of DB calls
LAGO_DEBEZIUM_TOPIC_PREFIX Mandatory if USE_MEMORY_CACHE is set to true, debezium kafka topic prefix (eg: lago_dbz)