Self-Hosting Installation
This guide covers deploying Better Hub on your own infrastructure using Docker.
Prerequisites
Node.js 22+
pnpm 10+
Docker and Docker Compose
A GitHub OAuth App (create one here )
Quick Start with Docker
Clone the repository
git clone https://github.com/better-auth/better-hub.git
cd better-hub
Start infrastructure services
Launch PostgreSQL and Redis with Docker Compose: This starts:
PostgreSQL on localhost:54320
Redis (internal)
Redis REST proxy on localhost:8079
Configure environment variables
Copy the example environment file and fill in required values: cp apps/web/.env.example apps/web/.env
See Configuration below for required values.
Run database migrations
cd apps/web && npx prisma migrate dev && cd ../..
Start the development server
Better Hub will be available at http://localhost:3000.
Configuration
Required Environment Variables
Edit apps/web/.env with these required values:
Authentication
Create a GitHub OAuth App at github.com/settings/developers :
GITHUB_CLIENT_ID = your_github_oauth_app_client_id
GITHUB_CLIENT_SECRET = your_github_oauth_app_client_secret
When creating your OAuth App, set the Homepage URL to http://localhost:3000 and the Authorization callback URL to http://localhost:3000/api/auth/callback/github.
Generate a random 32-character secret for session encryption:
# Generate with openssl
openssl rand -hex 16
Then add to .env:
BETTER_AUTH_SECRET = your_generated_32_char_string
BETTER_AUTH_URL = http://localhost:3000
NEXT_PUBLIC_APP_URL = http://localhost:3000
Database
For the Docker Compose setup:
DATABASE_URL = postgresql://postgres:postgres@localhost:54320/better_hub
The default password is postgres. To change it, set POSTGRES_PASSWORD before running docker compose up.
Redis
For the Docker Compose setup with REST proxy:
UPSTASH_REDIS_REST_URL = http://localhost:8079
UPSTASH_REDIS_REST_TOKEN = local_token
The default token is local_token. For production, set SRH_TOKEN to a secure value before running docker compose up.
AI Configuration
Ghost AI requires API keys for AI providers.
Required for Ghost
# OpenRouter powers Ghost assistant
OPEN_ROUTER_API_KEY = your_open_router_api_key
# Anthropic for specific AI tasks
ANTHROPIC_API_KEY = your_anthropic_api_key
Optional AI Settings
Customize the models Ghost uses:
# Defaults shown — uncomment to override
# GHOST_MODEL=moonshotai/kimi-k2.5
# GHOST_MERGE_MODEL=google/gemini-2.5-pro-preview
# OpenAI (optional)
# OPENAPI_KEY=your_openai_api_key
Optional Features
Code Sandbox (E2B)
For sandboxed code execution:
E2B_API_KEY = your_e2b_api_key
# Custom template (optional)
# Build with: cd apps/web && npx e2b template build
# E2B_TEMPLATE=your_e2b_template_id
Background Jobs (Inngest)
INNGEST_EVENT_KEY = your_inngest_event_key
INNGEST_SIGNING_KEY = your_inngest_signing_key
Search & Memory
# Mixedbread embeddings for semantic search
MIXEDBREAD_API_KEY = your_mixedbread_api_key
# SuperMemory for AI conversation memory
SUPER_MEMORY_API_KEY = your_super_memory_api_key
Integrations
# Slack notifications
SLACK_CLIENT_ID = your_slack_client_id
SLACK_CLIENT_SECRET = your_slack_client_secret
# Vercel OIDC (for deployment auth)
VERCEL_OIDC_TOKEN = your_vercel_oidc_token
Monitoring
# Sentry error tracking
SENTRY_DSN = https://your-dsn@sentry.io/project-id
SENTRY_AUTH_TOKEN = your_sentry_auth_token
Billing (Stripe)
STRIPE_SECRET_KEY = your_stripe_secret_key
STRIPE_WEBHOOK_SECRET = your_stripe_webhook_secret
STRIPE_BASE_PRICE_ID = price_xxx
STRIPE_METERED_PRICE_ID = price_xxx
Docker Services
The docker-compose.yml configures:
PostgreSQL
postgres :
image : postgres:16-alpine
container_name : better-hub-postgres
environment :
POSTGRES_USER : postgres
POSTGRES_PASSWORD : ${POSTGRES_PASSWORD:-postgres}
POSTGRES_DB : better_hub
ports :
- "127.0.0.1:54320:5432"
Redis with REST Proxy
redis :
image : redis:7-alpine
container_name : better-hub-redis
redis-rest :
image : hiett/serverless-redis-http:latest
container_name : better-hub-redis-rest
ports :
- "127.0.0.1:8079:80"
environment :
SRH_MODE : env
SRH_TOKEN : ${SRH_TOKEN:-local_token}
SRH_CONNECTION_STRING : redis://redis:6379
Data persists in Docker volumes postgres_data and redis_data. To reset, run docker compose down -v.
Development Scripts
Run from the repo root:
pnpm dev # Start all apps in dev mode
pnpm lint # Run oxlint
pnpm lint:fix # Run oxlint with auto-fix
pnpm fmt # Format with oxfmt
pnpm fmt:check # Check formatting
pnpm typecheck # TypeScript type checking
pnpm check # Run lint + fmt:check + typecheck
Production Deployment
Before deploying to production:
Change default passwords — Set POSTGRES_PASSWORD and SRH_TOKEN to secure values
Use HTTPS — Update BETTER_AUTH_URL and NEXT_PUBLIC_APP_URL to your domain
Secure secrets — Never commit .env files to version control
Update OAuth callback — Change GitHub OAuth App callback URL to your production domain
For production deployments:
Set production environment variables
Update .env with production values (database, Redis, domain, etc.).
Run migrations
cd apps/web && npx prisma migrate deploy && cd ../..
Start the production server
Troubleshooting
Database connection failed
Verify PostgreSQL is running:
docker ps | grep better-hub-postgres
Check the connection string matches your Docker setup:
DATABASE_URL = postgresql://postgres:postgres@localhost:54320/better_hub
Redis connection failed
Verify Redis REST proxy is running:
docker ps | grep better-hub-redis-rest
Ensure the token matches:
UPSTASH_REDIS_REST_TOKEN = local_token # Must match SRH_TOKEN in docker-compose.yml
GitHub OAuth errors
Verify your OAuth App settings:
Homepage URL matches BETTER_AUTH_URL
Callback URL is ${BETTER_AUTH_URL}/api/auth/callback/github
GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET are correct
Next Steps
Quickstart Learn how to use Better Hub features
Contributing Help build Better Hub — contributor guide