PostgreSQL Docker Compose Setup
This guide covers how to run llm-proxy with PostgreSQL using Docker Compose.
Build Tags
The llm-proxy uses Go build tags to conditionally compile PostgreSQL support. This allows for smaller binaries when PostgreSQL support is not needed.
Default Build (SQLite Only)
By default, the binary is built without PostgreSQL support:
# Build without PostgreSQL support (smaller binary)
go build ./cmd/proxy
# Or with explicit flags
go build -o llm-proxy ./cmd/proxy
Build with PostgreSQL Support
To enable PostgreSQL support, use the postgres build tag:
# Build with PostgreSQL support
go build -tags postgres ./cmd/proxy
# Or with explicit flags
go build -tags postgres -o llm-proxy ./cmd/proxy
Docker Build Variants
The Dockerfile supports both variants via the POSTGRES_SUPPORT build argument:
# Build with PostgreSQL support (default)
docker build -t llm-proxy:postgres .
# Build without PostgreSQL support (smaller image)
docker build --build-arg POSTGRES_SUPPORT=false -t llm-proxy:sqlite .
Binary Size Comparison
| Variant | Approximate Size |
|---|---|
| SQLite only | ~31 MB |
| With PostgreSQL | ~37 MB |
Error Handling
If you try to use PostgreSQL with a binary built without the postgres tag, you’ll receive this error:
PostgreSQL support not compiled in; build with -tags postgres to enable
Overview
The llm-proxy supports both SQLite (default) and PostgreSQL as database backends. This guide explains how to run the PostgreSQL setup using Docker Compose.
Quick Start
Prerequisites
- Docker and Docker Compose installed
- Go 1.23+ (for running integration tests)
Start PostgreSQL Only
To start just the PostgreSQL database (useful for development):
# Start PostgreSQL with the postgres profile
docker compose --profile postgres up -d postgres
# Wait for PostgreSQL to be ready
docker compose --profile postgres exec postgres pg_isready -U llmproxy -d llmproxy
Start Full Stack with PostgreSQL
To start the full llm-proxy stack with PostgreSQL backend:
# Set required environment variables
export POSTGRES_PASSWORD="your-secure-password"
export OPENAI_API_KEY="your-openai-key"
export MANAGEMENT_TOKEN="your-management-token"
# Start all services with PostgreSQL
docker compose --profile postgres up -d
Stop and Clean Up
# Stop all containers
docker compose --profile postgres down
# Stop and remove volumes (deletes all data)
docker compose --profile postgres down -v
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
POSTGRES_PASSWORD |
secret |
PostgreSQL password (required for production) |
DB_DRIVER |
sqlite |
Database driver (sqlite or postgres) |
DATABASE_URL |
- | PostgreSQL connection string |
DATABASE_POOL_SIZE |
10 |
Maximum database connections |
DATABASE_MAX_IDLE_CONNS |
5 |
Maximum idle connections |
DATABASE_CONN_MAX_LIFETIME |
1h |
Connection max lifetime |
Connection String Format
The PostgreSQL connection string follows this format:
postgres://user:password@host:port/database?sslmode=MODE
Example:
postgres://llmproxy:secret@postgres:5432/llmproxy?sslmode=disable
SSL Mode Options
| Mode | Description |
|---|---|
disable |
No SSL (development only) |
require |
SSL required, no certificate verification |
verify-ca |
SSL with CA certificate verification |
verify-full |
SSL with full certificate and hostname verification |
Production Recommendation: Use sslmode=require or sslmode=verify-full.
Docker Compose Services
The PostgreSQL profile adds these services:
postgres
The PostgreSQL 15 database server.
- Image:
postgres:15 - Port:
5432 - Healthcheck:
pg_isready - Volume:
postgres_data(persistent)
llm-proxy-postgres
The llm-proxy server configured to use PostgreSQL.
- Port:
8082(to avoid conflict with SQLite version on8080) - Depends on:
postgres(healthy),redis(started)
Integration Tests
Run PostgreSQL Integration Tests
Use the provided script to run integration tests against a real PostgreSQL instance:
# Full test run (starts PostgreSQL, runs tests, stops PostgreSQL)
./scripts/run-postgres-integration.sh
# Start PostgreSQL and keep it running
./scripts/run-postgres-integration.sh start
# Run tests only (PostgreSQL must be running)
./scripts/run-postgres-integration.sh test
# Stop and clean up
./scripts/run-postgres-integration.sh teardown
Manual Test Run
# Start PostgreSQL
docker compose --profile postgres up -d postgres
# Wait for PostgreSQL
docker compose --profile postgres exec postgres pg_isready -U llmproxy -d llmproxy
# Run tests with postgres and integration tags
export TEST_POSTGRES_URL="postgres://llmproxy:secret@localhost:5432/llmproxy?sslmode=disable"
go test -v -race -tags=postgres,integration ./internal/database/...
# Clean up
docker compose --profile postgres down -v
Data Persistence
PostgreSQL data is persisted in a Docker volume named llm-proxy-postgres-data.
View Data Volume
docker volume inspect llm-proxy-postgres-data
Backup Database
docker compose --profile postgres exec postgres \
pg_dump -U llmproxy llmproxy > backup.sql
Restore Database
cat backup.sql | docker compose --profile postgres exec -T postgres \
psql -U llmproxy llmproxy
Migration from SQLite
To migrate from SQLite to PostgreSQL:
- Export data from SQLite:
# Export tokens and projects (adapt as needed) sqlite3 data/llm-proxy.db ".dump tokens" > tokens.sql sqlite3 data/llm-proxy.db ".dump projects" > projects.sql - Start PostgreSQL:
docker compose --profile postgres up -d postgres -
Migrations run automatically when the application starts.
- Import data (you may need to adapt SQL syntax):
# Note: SQLite and PostgreSQL have different SQL dialects # Manual data migration may be required
Troubleshooting
PostgreSQL Won’t Start
Check the logs:
docker compose --profile postgres logs postgres
Common issues:
- Volume permission problems
- Port 5432 already in use
Connection Refused
Ensure PostgreSQL is healthy:
docker compose --profile postgres exec postgres pg_isready -U llmproxy
Migration Failures
Check application logs:
docker compose --profile postgres logs llm-proxy-postgres
Common issues:
- Database doesn’t exist (should be created by PostgreSQL container)
- Invalid migration files
Reset Database
To completely reset the PostgreSQL database:
# Stop and remove containers and volumes
docker compose --profile postgres down -v
# Start fresh
docker compose --profile postgres up -d postgres
Security Considerations
Production Checklist
- Change
POSTGRES_PASSWORDfrom default - Use
sslmode=requireorsslmode=verify-full - Limit network access to PostgreSQL port
- Enable PostgreSQL audit logging
- Regular database backups
- Consider encrypting data at rest
API Key Storage
API keys are stored in plaintext in the database. For production:
- Use a secret manager for sensitive configuration
- Consider database-level encryption
- Implement key rotation policies
Related Documentation
- Migrations Guide - Database migration system
- Migration Concurrency Guide - Concurrent migration handling
- Configuration Reference - All environment variables