Self-Hosting LEADR¶
This guide covers deploying your own LEADR instance using Docker Compose.
Prerequisites¶
- A ready cloud-hosting environment or your own server
- Docker and Docker Compose (v2.20+)
- A domain name with DNS control
- A PostgreSQL 16+ database (cloud-hosted or self-managed)
For PostgreSQL, you can use any provider that gives you a standard connection string:
- Cloud: Supabase, Neon, AWS RDS, Google Cloud SQL, DigitalOcean
- Self-hosted: Your own PostgreSQL instance
Quick Start¶
- Clone the repository:
git clone https://github.com/LEADR-official/leadr-oss.git
cd leadr-oss
- Create your environment file:
cp .env.example .env
-
Configure your
.envfile (see Environment Variables) -
Start the stack:
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml --env-file .env up -d
Environment Variables¶
Required¶
| Variable | Description |
|---|---|
ENV |
Environment name (e.g., PROD) |
DB_HOST |
PostgreSQL host (e.g., db.example.com) |
DB_PASSWORD |
Database password |
DB_NAME |
Database name (default: leadr) |
DB_USER |
Database user (default: leadr) |
DOMAIN |
Your domain for routing (e.g., example.com) |
SUPERADMIN_API_KEY |
Admin API key - must start with ldr_ |
JWT_SECRET |
Secret for JWT signing - generate a strong random string |
API_KEY_SECRET |
Secret for API key hashing - generate a strong random string |
Optional Variables¶
These have sensible defaults but can be customized:
| Variable | Default | Description |
|---|---|---|
LEADR_IMAGE_TAG |
latest |
Docker image version (e.g., v0.1.0) |
DB_PORT |
5432 |
PostgreSQL port |
DB_POOL_SIZE |
20 |
Database connection pool size |
ACCESS_TOKEN_EXPIRY_HOURS |
24 |
Device access token lifetime |
REFRESH_TOKEN_EXPIRY_DAYS |
30 |
Device refresh token lifetime |
ANTICHEAT_ENABLED |
false |
Enable anti-cheat checks |
See src/leadr/config.py for the complete list of configuration options.
Architecture¶
The self-hosted stack consists of:
┌─────────────────────────────────┐
│ Caddy │
│ (Reverse Proxy + HTTPS) │
└───────────┬─────────────────────┘
│
┌─────────────────┴─────────────────┐
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ admin-api │ │ client-api │
│ api.admin.example.com │ │ api.example.com │
│ │ │ │
│ - Account management │ │ - Score submissions │
│ - Game configuration │ │ - Leaderboard queries │
│ - User management │ │ - Device registration │
└─────────────────────────┘ └─────────────────────────┘
│ │
└─────────────────┬─────────────────┘
│
▼
┌─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐
│ PostgreSQL (not included) │
└─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘
- admin-api: Administrative endpoints for managing accounts, games, and users
- client-api: Public endpoints for game clients (score submission, leaderboards)
- Caddy: Automatic HTTPS with Let's Encrypt, routes traffic to appropriate API
DNS Setup¶
Create two A records pointing to your server's IP address:
| Record | Type | Value |
|---|---|---|
api.example.com |
A | <your-server-ip> |
api.admin.example.com |
A | <your-server-ip> |
Caddy will automatically obtain and renew TLS certificates from Let's Encrypt.
Running the Stack¶
Start¶
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml --env-file .env up -d
View Logs¶
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml logs -f
Stop¶
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml down
Verify Health¶
curl https://api.example.com/v1/health
curl https://api.admin.example.com/v1/health
Both should return a 200 OK response.
First Steps After Deploy¶
Install the LEADR CLI¶
Download and install the CLI from the releases page:
curl -sSL https://github.com/LEADR-official/leadr-cli-releases/raw/main/install.sh | bash
Or download binaries directly from github.com/LEADR-official/leadr-cli-releases.
Configure Admin Authentication¶
-
Verify the superadmin bootstrap: On first startup, LEADR creates a superadmin account using your
SUPERADMIN_*environment variables. -
Configure the CLI with your superadmin API key:
leadr --host api.admin.example.com auth admin configure
Enter your SUPERADMIN_API_KEY when prompted.
Create Your First Game¶
# Get your account ID (created during bootstrap)
leadr --host api.admin.example.com account get <account-id>
# Create a game
leadr --host api.admin.example.com game create \
--account-id <account-id> \
--name "My Game"
Run leadr --help to see all available commands.
Optional Features¶
GeoIP Auto-Labeling¶
LEADR can automatically extract geolocation (country, city, timezone) from player IP addresses using MaxMind GeoLite2 databases. This requires a free MaxMind account.
See the "GeoIP Auto-Labeling" section in CLAUDE.md for configuration details.
Email Notifications¶
Email functionality (verification codes, notifications) requires Mailgun credentials:
MAILGUN_API_KEYMAILGUN_DOMAIN
Updating¶
To update to a newer version:
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml pull
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml up -d
Database migrations run automatically on startup when RUN_MIGRATIONS=true (default for selfhost).
Troubleshooting¶
Container won't start¶
Check logs for errors:
docker compose -f docker/docker-compose.base.yml -f docker/docker-compose.selfhost.yml logs admin-api
Common issues:
- Database connection failed: Verify
DB_HOST,DB_USER,DB_PASSWORD - Missing required env vars: Ensure all required variables are set
Caddy certificate errors¶
- Ensure DNS records are correctly configured and propagated
- Verify ports 80 and 443 are accessible from the internet
- Check Caddy logs:
docker compose ... logs caddy
API returns 401/403¶
- Verify your API key starts with
ldr_ - Ensure the
leadr-api-keyheader is correctly spelled (lowercase)