Lago
★ 10.8kA self-hosted alternative to Stripe
About
Community Ratings
No ratings yetNew this week
Read recap →Features
- usage event ingestion
- billable metrics
- usage-based pricing
- credits and top-ups
- subscriptions and allowances
- invoices and credit notes
- payment-provider orchestration
- revenue and usage analytics
- REST API
- MCP server
Details
- Last Updated
- Nov 3, 2026
- Created
- Feb 28, 2022
- Install Methods
- dockerdocker-composesource
- Requirements
- Dockercurljq
- Default Port
- 8080Lago UI
- API
- REST
- Backup & Export
- database-dumpfile-backup
- Runtime / Stack
- Docker
- Privacy & Independence
- Cloud: OptionalOffline Capable
- User Model
- Multi-UserMulti-Tenant
- Deployment
Deployment: Docker Compose ✓8 Containers — heavy hosting footprintRuns as 8 containers
Run Lago yourself
Pick how much you want to manage.
HetznerBest match
Full control
A small server, then Docker Compose.
About 20 minutes with Docker
DigitalOcean
Full control
A small server, then Docker Compose.
About 20 minutes with Docker
OVHcloud
Full control
A small server, then Docker Compose.
About 20 minutes with Docker
1 more way to host
Is this your project? Sponsor a listing
Run Lago with Docker Compose
Compose file from the Lago project repository.
8 services
no resource limits declared
needs persistent storage (4 volumes)
docker-compose.yml · @ 05b2d16 · scanned Nov 3, 2026
volumes:
lago_postgres_data:
lago_redis_data:
lago_storage_data:
x-postgres-image: &postgres-image
image: getlago/postgres-partman:15.0-alpine
x-redis-image: &redis-image
image: redis:7-alpine
x-backend-image: &backend-image
image: getlago/api:v1.50.0
x-frontend-image: &frontend-image
image: getlago/front:v1.50.0
x-lago-api-url: &lago-api-url
"LAGO_API_URL": ${LAGO_API_URL:-http://localhost:3000}
x-lago-front-url: &lago-front-url
"LAGO_FRONT_URL": ${LAGO_FRONT_URL:-http://localhost}
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:-}
"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": ${LAGO_PDF_URL:-http://pdf:3000}
"LAGO_DATA_API_URL": ${LAGO_DATA_API_URL:-http://data-api}
"LAGO_DATA_API_BEARER_TOKEN": ${LAGO_DATA_API_BEARER_TOKEN:-}
"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_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_DISABLE_PDF_GENERATION": ${LAGO_DISABLE_PDF_GENERATION:-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:-}
"MISTRAL_API_KEY": ${MISTRAL_API_KEY:-}
"MISTRAL_AGENT_ID": ${MISTRAL_AGENT_ID:-}
# - SIDEKIQ_EVENTS=true
# - SIDEKIQ_PDFS=true
# - SIDEKIQ_BILLING=true
# - SIDEKIQ_CLOCK=true
# - SIDEKIQ_WEBHOOK=true
# - SIDEKIQ_AI_AGENT=true
x-frontend-environment: &frontend-env
"API_URL": ${LAGO_API_URL:-http://localhost:3000}
"APP_ENV": production
"LAGO_OAUTH_PROXY_URL": https://proxy.getlago.com
"LAGO_DISABLE_PDF_GENERATION": ${LAGO_DISABLE_PDF_GENERATION:-false}
services:
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}
redis:
<<: *redis-image
container_name: lago-redis
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "-p", "${REDIS_PORT:-6379}", "ping"]
interval: 10s
timeout: 5s
retries: 5
command: --port ${REDIS_PORT:-6379}
volumes:
- lago_redis_data:/data
ports:
- ${REDIS_PORT:-6379}:${REDIS_PORT:-6379}
migrate:
<<: *backend-image
container_name: lago-migrate
depends_on:
db:
condition: service_healthy
restart: true
command: ["./scripts/migrate.sh"]
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
redis:
condition: service_healthy
restart: true
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, *lago-api-url, *lago-front-url]
volumes:
- lago_storage_data:/app/storage
ports:
- ${API_PORT:-3000}:3000
front:
<<: *frontend-image
container_name: lago-front
restart: unless-stopped
# Use this command if you want to use SSL with Let's Encrypt
# command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
depends_on:
api:
condition: service_healthy
restart: true
environment:
<<: [*frontend-env, *lago-api-url, *lago-front-url]
ports:
- ${FRONT_PORT:-80}:80
# - 443:443
# Using SSL with Let's Encrypt
# volumes:
# - ./extra/nginx-letsencrypt.conf:/etc/nginx/conf.d/default.conf
# - ./extra/certbot/conf:/etc/letsencrypt
# - ./extra/certbot/www:/var/www/certbot
# Using SSL with self signed certificates
# volumes:
# - ./extra/nginx-selfsigned.conf:/etc/nginx/conf.d/default.conf
# - ./extra/ssl/nginx-selfsigned.crt:/etc/ssl/certs/nginx-selfsigned.crt
# - ./extra/ssl/nginx-selfsigned.key:/etc/ssl/private/nginx-selfsigned.key
# - ./extra/ssl/dhparam.pem:/etc/ssl/certs/dhparam.pem
# Only used for SSL support with Let's Encrypt
# certbot:
# image: certbot/certbot
# entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
# volumes:
# - ./extra/certbot/conf:/etc/letsencrypt
# - ./extra/certbot/www:/var/www/certbot
api-worker:
<<: *backend-image
container_name: lago-worker
restart: unless-stopped
depends_on:
migrate:
condition: service_completed_successfully
db:
condition: service_healthy
restart: true
redis:
condition: service_healthy
restart: true
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, *lago-api-url]
volumes:
- lago_storage_data:/app/storage
# You can uncomment this if you want to use a dedicated Sidekiq worker for the event ingestion.
# It is recommendend if you have a high usage of events to not impact the other Sidekiq Jobs.
#api-events-worker:
# <<: *backend-image
# container_name: lago-events-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.events.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
# You can uncomment this if you want to use a dedicated Sidekiq worker for the invoices pdf creation.
# It is recommended if you have a high usage of invoices being created to not impact the other Sidekiq Jobs.
#api-pdfs-worker:
# <<: *backend-image
# container_name: lago-pdfs-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.pdfs.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
# You can uncomment this if you want to use a dedicated Sidekiq worker for the invoices creation.
# It is recommended if you have a high usage of invoices being created to not impact the other Sidekiq Jobs.
#api-billing-worker:
# <<: *backend-image
# container_name: lago-billing-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.billing.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
# You can uncomment this if you want to use a dedicated Sidekiq worker for the clock jobs.
#api-clock-worker:
# <<: *backend-image
# container_name: lago-clock-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.clock.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
# You can uncomment this if you want to use a dedicated Sidekiq worker for the webhook jobs.
#api-webhook-worker:
# <<: *backend-image
# container_name: lago-webhook-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.webhook.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
# You can uncomment this if you want to use a dedicated Sidekiq worker for the analytics-related jobs.
#api-analytics-worker:
# <<: *backend-image
# container_name: api-analytics-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.analytics.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
# You can uncomment this if you want to use a dedicated Sidekiq worker for the AI Agent-related jobs.
#api-ai-agent-worker:
# <<: *backend-image
# container_name: api-ai-agent-worker
# restart: unless-stopped
# depends_on:
# api:
# condition: service_healthy
# command: ["./scripts/start.ai_agent.worker.sh"]
# environment:
# <<: [*backend-env, *lago-api-url]
api-clock:
<<: *backend-image
container_name: lago-clock
restart: unless-stopped
depends_on:
migrate:
condition: service_completed_successfully
db:
condition: service_healthy
restart: true
redis:
condition: service_healthy
restart: true
command: ["./scripts/start.clock.sh"]
environment:
<<: [*backend-env, *lago-api-url]
pdf:
image: getlago/lago-gotenberg:7.8.2
This file may be out of date. Check the Lago documentation for current setup steps.
Tags
Track your self-hosted stack
Bookmark software to try, rate tools you've used, and keep your collection in one place.
Alternatives to Lago
Kill Bill
FOSSBilling
SolidInvoice
InvoicePlane
Invoice Ninja
InvoiceShelf
Pancake
Related Software
HyperSwitch
Revert
Langfuse
