feat: add demo user initialization for local development

- Add hattori@hanzo.ai demo user with password demo1234
- Create seed_demo_user.js script to initialize demo account
- Add demo-init service to compose.yml for automatic setup
- Add compose.dev.yml for development with mounted volumes
- Create init-demo-user.sh for manual demo user creation
- Add Makefile.hanzo with comprehensive stack management
- Include README-demo-user.md with usage instructions
- Configure Hanzo Router branding in hanzo-config.yaml
This commit is contained in:
Hanzo Dev
2025-07-14 16:20:44 -05:00
parent 0ffe54f515
commit 02ffc50db8
10 changed files with 1130 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
# Hanzo AI Chat Stack Environment Variables
# Copy this file to .env and update with your values
# ==================================
# LLM API Keys (at least one required)
# ==================================
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
TOGETHER_API_KEY=...
# ==================================
# Database Configuration
# ==================================
POSTGRES_PASSWORD=hanzo123
MONGO_PASSWORD=hanzo123
REDIS_PASSWORD=hanzosecret
# ==================================
# Service URLs
# ==================================
DOMAIN_CLIENT=http://localhost:3081
DOMAIN_SERVER=http://localhost:3081
# ==================================
# Security Keys (CHANGE IN PRODUCTION!)
# ==================================
ROUTER_MASTER_KEY=sk-hanzo-master-key
JWT_SECRET=hanzo-jwt-secret-change-in-production
JWT_REFRESH_SECRET=hanzo-refresh-secret-change-in-production
CREDS_KEY=hanzo-creds-key-change-in-production
CREDS_IV=hanzo-creds-iv-change
MEILI_MASTER_KEY=HanzoMeiliMasterKey
# ==================================
# Feature Flags
# ==================================
ALLOW_REGISTRATION=true
ALLOW_UNVERIFIED_EMAIL_LOGIN=false
DEBUG=false
# ==================================
# Performance Tuning
# ==================================
ROUTER_WORKERS=4
# ==================================
# Optional: Additional LLM Providers
# ==================================
# AZURE_API_KEY=...
# AZURE_API_BASE=https://your-resource.openai.azure.com/
# GROQ_API_KEY=...
# COHERE_API_KEY=...
# ==================================
# Optional: Observability
# ==================================
# LANGFUSE_PUBLIC_KEY=...
# LANGFUSE_SECRET_KEY=...
# LANGFUSE_HOST=https://cloud.langfuse.com
# ==================================
# Optional: Authentication Providers
# ==================================
# GOOGLE_CLIENT_ID=...
# GOOGLE_CLIENT_SECRET=...
# GITHUB_CLIENT_ID=...
# GITHUB_CLIENT_SECRET=...
+21
View File
@@ -0,0 +1,21 @@
# Hanzo Chat with Demo User
FROM ghcr.io/danny-avila/librechat:latest
# Copy demo user initialization script
COPY scripts/seed_demo_user.js /app/scripts/
COPY docker/entrypoint-with-demo.sh /app/
# Install mongosh for the initialization script
USER root
RUN apt-get update && apt-get install -y gnupg wget && \
wget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | apt-key add - && \
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/7.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list && \
apt-get update && \
apt-get install -y mongodb-mongosh && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN chmod +x /app/entrypoint-with-demo.sh
# Use our custom entrypoint
ENTRYPOINT ["/app/entrypoint-with-demo.sh"]
+225
View File
@@ -0,0 +1,225 @@
# Hanzo AI Chat Stack Makefile
# One-command deployment and management
.PHONY: help up down restart logs build push deploy clean test status backup restore
# Color definitions
YELLOW := \033[1;33m
GREEN := \033[1;32m
RED := \033[1;31m
BLUE := \033[1;34m
NC := \033[0m # No Color
# Configuration
DOCKER_REGISTRY ?= ghcr.io/hanzoai
ROUTER_IMAGE := $(DOCKER_REGISTRY)/router
CHAT_IMAGE := $(DOCKER_REGISTRY)/chat
VERSION ?= latest
COMPOSE_FILE := docker-compose.hanzo.yml
# Default target
help:
@echo "$(BLUE)Hanzo AI Chat Stack Management$(NC)"
@echo ""
@echo "$(YELLOW)Quick Start:$(NC)"
@echo " $(GREEN)make deploy$(NC) - Build and start the entire Hanzo stack"
@echo ""
@echo "$(YELLOW)Development:$(NC)"
@echo " $(GREEN)make up$(NC) - Start all services"
@echo " $(GREEN)make down$(NC) - Stop all services"
@echo " $(GREEN)make restart$(NC) - Restart all services"
@echo " $(GREEN)make logs$(NC) - View logs (all services)"
@echo " $(GREEN)make logs-chat$(NC) - View chat service logs"
@echo " $(GREEN)make logs-router$(NC) - View Hanzo Router logs"
@echo " $(GREEN)make status$(NC) - Check service health"
@echo ""
@echo "$(YELLOW)Building:$(NC)"
@echo " $(GREEN)make build$(NC) - Build Docker images"
@echo " $(GREEN)make push$(NC) - Push images to registry"
@echo " $(GREEN)make clean$(NC) - Clean up volumes and images"
@echo ""
@echo "$(YELLOW)Testing:$(NC)"
@echo " $(GREEN)make test$(NC) - Run all tests"
@echo " $(GREEN)make test-api$(NC) - Test API endpoints"
@echo ""
@echo "$(YELLOW)Data Management:$(NC)"
@echo " $(GREEN)make backup$(NC) - Backup all data"
@echo " $(GREEN)make restore$(NC) - Restore from backup"
# Quick deploy - builds and starts everything
deploy: check-env build
@echo "$(BLUE)🚀 Deploying Hanzo AI Chat Stack...$(NC)"
@docker compose -f $(COMPOSE_FILE) up -d
@echo "$(GREEN)✅ Deployment complete!$(NC)"
@echo ""
@echo "$(YELLOW)Access points:$(NC)"
@echo " Chat UI: http://localhost:3081"
@echo " Hanzo Router: http://localhost:4000"
@echo " Router Admin: http://localhost:4000/ui"
@echo ""
@echo "$(YELLOW)Default credentials:$(NC)"
@echo " Master Key: sk-hanzo-master-key"
@echo ""
@$(MAKE) wait-healthy
# Check required environment variables
check-env:
@echo "$(BLUE)🔍 Checking environment...$(NC)"
@if [ -z "$$OPENAI_API_KEY" ] && [ -z "$$ANTHROPIC_API_KEY" ] && [ -z "$$TOGETHER_API_KEY" ]; then \
echo "$(RED)❌ Error: At least one LLM API key must be set$(NC)"; \
echo "$(YELLOW)Please set one of: OPENAI_API_KEY, ANTHROPIC_API_KEY, or TOGETHER_API_KEY$(NC)"; \
exit 1; \
fi
@if [ ! -f .env ]; then \
echo "$(YELLOW)📝 Creating .env file from template...$(NC)"; \
cp .env.example .env; \
fi
@echo "$(GREEN)✅ Environment check passed$(NC)"
# Build Docker images
build:
@echo "$(BLUE)🔨 Building Docker images...$(NC)"
@docker compose -f $(COMPOSE_FILE) build
@echo "$(GREEN)✅ Build complete$(NC)"
# Push images to registry
push:
@echo "$(BLUE)📤 Pushing images to registry...$(NC)"
@docker tag hanzo/router:latest $(ROUTER_IMAGE):$(VERSION)
@docker tag hanzo/chat:latest $(CHAT_IMAGE):$(VERSION)
@docker push $(ROUTER_IMAGE):$(VERSION)
@docker push $(CHAT_IMAGE):$(VERSION)
@echo "$(GREEN)✅ Images pushed successfully$(NC)"
# Start services
up:
@echo "$(BLUE)▶️ Starting services...$(NC)"
@docker compose -f $(COMPOSE_FILE) up -d
@$(MAKE) wait-healthy
# Stop services
down:
@echo "$(BLUE)⏹️ Stopping services...$(NC)"
@docker compose -f $(COMPOSE_FILE) down
@echo "$(GREEN)✅ Services stopped$(NC)"
# Restart services
restart:
@echo "$(BLUE)🔄 Restarting services...$(NC)"
@docker compose -f $(COMPOSE_FILE) restart
@$(MAKE) wait-healthy
# View logs
logs:
@docker compose -f $(COMPOSE_FILE) logs -f
logs-chat:
@docker compose -f $(COMPOSE_FILE) logs -f chat
logs-router:
@docker compose -f $(COMPOSE_FILE) logs -f router
# Check service health
status:
@echo "$(BLUE)📊 Service Status:$(NC)"
@echo ""
@docker compose -f $(COMPOSE_FILE) ps
@echo ""
@echo "$(BLUE)🏥 Health Checks:$(NC)"
@for service in postgres redis mongodb meilisearch router chat nginx; do \
if docker compose -f $(COMPOSE_FILE) exec -T $$service echo "OK" >/dev/null 2>&1; then \
echo " $$service: $(GREEN)✅ Healthy$(NC)"; \
else \
echo " $$service: $(RED)❌ Unhealthy$(NC)"; \
fi; \
done
# Wait for services to be healthy
wait-healthy:
@echo "$(BLUE)⏳ Waiting for services to be healthy...$(NC)"
@for i in 1 2 3 4 5 6 7 8 9 10; do \
if docker compose -f $(COMPOSE_FILE) exec -T router curl -f http://localhost:4000/health >/dev/null 2>&1 && \
docker compose -f $(COMPOSE_FILE) exec -T chat curl -f http://localhost:3080/health >/dev/null 2>&1; then \
echo "$(GREEN)✅ All services are healthy!$(NC)"; \
break; \
fi; \
echo " Waiting... ($$i/10)"; \
sleep 5; \
done
# Run tests
test: test-api test-chat
test-api:
@echo "$(BLUE)🧪 Testing API endpoints...$(NC)"
@curl -s -X GET http://localhost:4000/health | grep -q "healthy" && \
echo "$(GREEN)✅ Hanzo Router: OK$(NC)" || \
echo "$(RED)❌ Hanzo Router: Failed$(NC)"
@curl -s -X GET http://localhost:3081/health | grep -q "OK" && \
echo "$(GREEN)✅ Chat UI: OK$(NC)" || \
echo "$(RED)❌ Chat UI: Failed$(NC)"
test-chat:
@echo "$(BLUE)🧪 Testing chat functionality...$(NC)"
@curl -s -X POST http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-hanzo-master-key" \
-d '{"model": "hanzo-zen-1", "messages": [{"role": "user", "content": "Hello"}]}' | \
grep -q "content" && \
echo "$(GREEN)✅ Chat completion: OK$(NC)" || \
echo "$(RED)❌ Chat completion: Failed$(NC)"
# Clean up
clean:
@echo "$(BLUE)🧹 Cleaning up...$(NC)"
@docker compose -f $(COMPOSE_FILE) down -v
@docker rmi hanzo/router:latest hanzo/chat:latest || true
@echo "$(GREEN)✅ Cleanup complete$(NC)"
# Backup data
backup:
@echo "$(BLUE)💾 Backing up data...$(NC)"
@mkdir -p backups
@BACKUP_NAME="hanzo-backup-$$(date +%Y%m%d-%H%M%S)"; \
docker compose -f $(COMPOSE_FILE) exec -T postgres pg_dump -U hanzo hanzo_chat > backups/$$BACKUP_NAME-postgres.sql; \
docker compose -f $(COMPOSE_FILE) exec -T mongodb mongodump --archive > backups/$$BACKUP_NAME-mongodb.archive; \
echo "$(GREEN)✅ Backup saved to backups/$$BACKUP_NAME-*$(NC)"
# Restore from backup
restore:
@if [ -z "$(BACKUP)" ]; then \
echo "$(RED)❌ Please specify BACKUP=<backup-name>$(NC)"; \
exit 1; \
fi
@echo "$(BLUE)📥 Restoring from backup...$(NC)"
@docker compose -f $(COMPOSE_FILE) exec -T postgres psql -U hanzo hanzo_chat < backups/$(BACKUP)-postgres.sql
@docker compose -f $(COMPOSE_FILE) exec -T mongodb mongorestore --archive < backups/$(BACKUP)-mongodb.archive
@echo "$(GREEN)✅ Restore complete$(NC)"
# Initialize demo user
init-demo:
@echo "$(BLUE)👤 Initializing demo user...$(NC)"
@./init-demo-user.sh
# Development helpers
dev-setup:
@echo "$(BLUE)🛠️ Setting up development environment...$(NC)"
@poetry install --with dev,proxy-dev --extras proxy
@cd client && npm install
@echo "$(GREEN)✅ Development setup complete$(NC)"
dev-frontend:
@echo "$(BLUE)🎨 Starting frontend development server...$(NC)"
@cd client && npm run dev
dev-backend:
@echo "$(BLUE)⚙️ Starting Hanzo Router development server...$(NC)"
@poetry run litellm --config hanzo-config.yaml --port 4000
# Production deployment
prod-deploy:
@echo "$(BLUE)🚀 Deploying to production...$(NC)"
@$(MAKE) build VERSION=$(shell git rev-parse --short HEAD)
@$(MAKE) push VERSION=$(shell git rev-parse --short HEAD)
@echo "$(GREEN)✅ Production deployment complete$(NC)"
@echo "$(YELLOW)Images tagged with version: $(shell git rev-parse --short HEAD)$(NC)"
+54
View File
@@ -0,0 +1,54 @@
# Hanzo Chat Demo User
When running Hanzo Chat locally, a demo user is automatically created for quick access.
## Demo User Credentials
- **Email**: `hattori@hanzo.ai`
- **Password**: `demo1234`
- **Role**: Admin
## Quick Start
1. Start the Hanzo stack:
```bash
docker compose up -d
```
2. Access Hanzo Chat:
- Open your browser to http://localhost:3081
- Log in with the demo credentials above
## Manual Demo User Creation
If you need to manually create the demo user (e.g., after resetting the database):
```bash
./init-demo-user.sh
```
Or using the Makefile:
```bash
make -f Makefile.hanzo init-demo
```
## Security Note
⚠️ **This demo user is for local development only!**
Never use these credentials in production. Always:
- Change default passwords
- Use proper authentication methods
- Disable demo users in production environments
## Customizing the Demo User
To modify the demo user details, edit `scripts/seed_demo_user.js` and change:
- Name
- Email
- Password
- Role (USER or ADMIN)
- Avatar URL
After making changes, restart the stack or run the initialization script again.
+215
View File
@@ -0,0 +1,215 @@
# Hanzo AI Chat Stack - Development Environment
# This mounts source code for live editing
# Use with: docker compose -f compose.dev.yml up
services:
# PostgreSQL Database
postgres:
image: postgres:16-alpine
container_name: hanzo-postgres-dev
environment:
POSTGRES_USER: hanzo
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-hanzo123}
POSTGRES_DB: hanzo_chat
ports:
- "5432:5432"
volumes:
- postgres_data_dev:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U hanzo"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network-dev
# Redis Cache
redis:
image: redis:7-alpine
container_name: hanzo-redis-dev
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-hanzosecret}
ports:
- "6379:6379"
volumes:
- redis_data_dev:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-hanzosecret}", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network-dev
# MongoDB for Chat History
mongodb:
image: mongo:7-jammy
container_name: hanzo-mongodb-dev
environment:
MONGO_INITDB_ROOT_USERNAME: hanzo
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:-hanzo123}
MONGO_INITDB_DATABASE: HanzoChat
ports:
- "27017:27017"
volumes:
- mongodb_data_dev:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network-dev
# Meilisearch for Full-Text Search
meilisearch:
image: getmeili/meilisearch:v1.9
container_name: hanzo-meilisearch-dev
environment:
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-HanzoMeiliMasterKey}
MEILI_ENV: development
ports:
- "7700:7700"
volumes:
- meilisearch_data_dev:/meili_data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7700/health"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network-dev
# Hanzo Router (Development Mode with Hot Reload)
router:
build:
context: ../router
dockerfile: Dockerfile.dev
target: development
container_name: hanzo-router-dev
ports:
- "4000:4000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
# Database
DATABASE_URL: postgresql://hanzo:${POSTGRES_PASSWORD:-hanzo123}@postgres:5432/hanzo_chat
REDIS_URL: redis://:${REDIS_PASSWORD:-hanzosecret}@redis:6379
# Router Configuration
ROUTER_MASTER_KEY: ${ROUTER_MASTER_KEY:-sk-hanzo-master-key}
LITELLM_MASTER_KEY: ${ROUTER_MASTER_KEY:-sk-hanzo-master-key}
# LLM API Keys
OPENAI_API_KEY: ${OPENAI_API_KEY}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
TOGETHER_API_KEY: ${TOGETHER_API_KEY}
# Development
LITELLM_LOG: DEBUG
DEBUG: true
PYTHONUNBUFFERED: 1
volumes:
# Mount source code for development
- ../router/litellm:/app/litellm:ro
- ../router/pyproject.toml:/app/pyproject.toml:ro
- ./hanzo-config.yaml:/app/config.yaml:ro
command: ["--config", "/app/config.yaml", "--port", "4000", "--num_workers", "1", "--detailed_debug"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4000/health/readiness"]
interval: 10s
timeout: 5s
retries: 10
networks:
- hanzo-network-dev
# Hanzo Chat Frontend (Development Mode)
chat:
build:
context: .
dockerfile: Dockerfile.dev
target: development
container_name: hanzo-chat-dev
ports:
- "3081:3080"
depends_on:
mongodb:
condition: service_healthy
meilisearch:
condition: service_healthy
router:
condition: service_healthy
environment:
# Server Configuration
HOST: 0.0.0.0
PORT: 3080
NODE_ENV: development
# Database
MONGO_URI: mongodb://hanzo:${MONGO_PASSWORD:-hanzo123}@mongodb:27017/HanzoChat?authSource=admin
# Domain
DOMAIN_CLIENT: ${DOMAIN_CLIENT:-http://localhost:3081}
DOMAIN_SERVER: ${DOMAIN_SERVER:-http://localhost:3081}
# Branding
APP_TITLE: "Hanzo AI Chat (Dev)"
CUSTOM_FOOTER: "Development Environment"
# Router Gateway
OPENAI_API_KEY: proxy
OPENAI_BASE_URL: http://router:4000/v1
# Auth & Security
JWT_SECRET: ${JWT_SECRET:-dev-jwt-secret}
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-dev-refresh-secret}
CREDS_KEY: ${CREDS_KEY:-dev-creds-key}
CREDS_IV: ${CREDS_IV:-dev-creds-iv}
# Features
ALLOW_REGISTRATION: true
ALLOW_UNVERIFIED_EMAIL_LOGIN: true
# Search
MEILI_HOST: http://meilisearch:7700
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-HanzoMeiliMasterKey}
# MCP Integration
MCP_ENABLED: true
# Logging
DEBUG_LOGGING: true
volumes:
# Mount source for development
- ./api:/app/api:ro
- ./client:/app/client:ro
- ./packages:/app/packages:ro
- ./package.json:/app/package.json:ro
- ./client/dist/assets:/app/client/dist/assets:ro
- chat_uploads_dev:/app/uploads
- chat_logs_dev:/app/logs
# Node modules volume for faster rebuilds
- node_modules:/app/node_modules
command: ["npm", "run", "dev"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3080/health"]
interval: 10s
timeout: 5s
retries: 10
networks:
- hanzo-network-dev
volumes:
postgres_data_dev:
redis_data_dev:
mongodb_data_dev:
meilisearch_data_dev:
chat_uploads_dev:
chat_logs_dev:
node_modules:
networks:
hanzo-network-dev:
driver: bridge
+218
View File
@@ -0,0 +1,218 @@
# Hanzo AI Chat Stack - Local Production Environment
# This runs pre-built images suitable for local testing
# For development with mounted volumes, use compose.dev.yml
services:
# PostgreSQL Database
postgres:
image: postgres:16-alpine
container_name: hanzo-postgres
environment:
POSTGRES_USER: hanzo
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-hanzo123}
POSTGRES_DB: hanzo_chat
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U hanzo"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network
# Redis Cache
redis:
image: redis:7-alpine
container_name: hanzo-redis
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-hanzosecret}
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-hanzosecret}", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network
# MongoDB for Chat History
mongodb:
image: mongo:7-jammy
container_name: hanzo-mongodb
environment:
MONGO_INITDB_ROOT_USERNAME: hanzo
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:-hanzo123}
MONGO_INITDB_DATABASE: HanzoChat
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network
# Meilisearch for Full-Text Search
meilisearch:
image: getmeili/meilisearch:v1.9
container_name: hanzo-meilisearch
environment:
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-HanzoMeiliMasterKey}
MEILI_ENV: production
ports:
- "7700:7700"
volumes:
- meilisearch_data:/meili_data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7700/health"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network
# Hanzo Router (LiteLLM Gateway)
router:
image: hanzo/router:latest
container_name: hanzo-router
ports:
- "4000:4000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
# Database
DATABASE_URL: postgresql://hanzo:${POSTGRES_PASSWORD:-hanzo123}@postgres:5432/hanzo_chat
REDIS_URL: redis://:${REDIS_PASSWORD:-hanzosecret}@redis:6379
# Router Configuration
ROUTER_MASTER_KEY: ${ROUTER_MASTER_KEY:-sk-hanzo-master-key}
LITELLM_MASTER_KEY: ${ROUTER_MASTER_KEY:-sk-hanzo-master-key} # For compatibility
# LLM API Keys
OPENAI_API_KEY: ${OPENAI_API_KEY}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
TOGETHER_API_KEY: ${TOGETHER_API_KEY}
# Logging
ROUTER_LOG_LEVEL: INFO
DEBUG: ${DEBUG:-false}
volumes:
- ./hanzo-config.yaml:/app/config.yaml:ro
command: ["--config", "/app/config.yaml", "--port", "4000", "--num_workers", "${ROUTER_WORKERS:-4}"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4000/health/readiness"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network
# Hanzo Chat Frontend
chat:
image: ghcr.io/hanzoai/chat:latest
container_name: hanzo-chat
ports:
- "3081:3080"
depends_on:
mongodb:
condition: service_healthy
meilisearch:
condition: service_healthy
router:
condition: service_healthy
demo-init:
condition: service_completed_successfully
environment:
# Server Configuration
HOST: 0.0.0.0
PORT: 3080
# Database
MONGO_URI: mongodb://hanzo:${MONGO_PASSWORD:-hanzo123}@mongodb:27017/HanzoChat?authSource=admin
# Domain
DOMAIN_CLIENT: ${DOMAIN_CLIENT:-http://localhost:3081}
DOMAIN_SERVER: ${DOMAIN_SERVER:-http://localhost:3081}
# Branding
APP_TITLE: "Hanzo AI Chat"
CUSTOM_FOOTER: "Powered by Hanzo AI"
# Router Gateway
OPENAI_API_KEY: proxy
OPENAI_BASE_URL: http://router:4000/v1
# Auth & Security
JWT_SECRET: ${JWT_SECRET:-hanzo-jwt-secret-change-in-production}
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-hanzo-refresh-secret-change-in-production}
CREDS_KEY: ${CREDS_KEY:-hanzo-creds-key-change-in-production}
CREDS_IV: ${CREDS_IV:-hanzo-creds-iv-change}
# Features
ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-true}
ALLOW_UNVERIFIED_EMAIL_LOGIN: ${ALLOW_UNVERIFIED_EMAIL_LOGIN:-false}
# Search
MEILI_HOST: http://meilisearch:7700
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-HanzoMeiliMasterKey}
# MCP Integration
MCP_ENABLED: true
# Logging
DEBUG_LOGGING: ${DEBUG:-false}
volumes:
- ./scripts:/app/scripts:ro
- ./client/dist/assets:/app/client/dist/assets:ro
- chat_uploads:/app/uploads
- chat_logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3080/health"]
interval: 10s
timeout: 5s
retries: 5
networks:
- hanzo-network
# Demo User Initialization Service
demo-init:
image: node:18-alpine
container_name: hanzo-demo-init
depends_on:
mongodb:
condition: service_healthy
environment:
MONGO_URI: mongodb://hanzo:${MONGO_PASSWORD:-hanzo123}@mongodb:27017/HanzoChat?authSource=admin
volumes:
- ./scripts/seed_demo_user.js:/app/seed_demo_user.js:ro
working_dir: /app
command: |
sh -c "
npm install mongoose bcryptjs
node seed_demo_user.js
"
networks:
- hanzo-network
volumes:
postgres_data:
redis_data:
mongodb_data:
meilisearch_data:
chat_uploads:
chat_logs:
networks:
hanzo-network:
driver: bridge
+89
View File
@@ -0,0 +1,89 @@
#!/bin/bash
# Hanzo Chat entrypoint with demo user initialization
echo "🚀 Starting Hanzo Chat with demo user initialization..."
# Function to wait for MongoDB
wait_for_mongodb() {
echo "⏳ Waiting for MongoDB to be ready..."
until mongosh "$MONGO_URI" --eval "db.adminCommand('ping')" > /dev/null 2>&1; do
sleep 2
done
echo "✅ MongoDB is ready"
}
# Function to create demo user
create_demo_user() {
echo "👤 Creating demo user..."
# Create a temporary Node.js script to add the user
cat > /tmp/create_demo_user.js << 'EOF'
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI)
.then(async () => {
console.log('Connected to MongoDB');
// Define User schema
const userSchema = new mongoose.Schema({
name: String,
username: { type: String, lowercase: true, required: true },
email: { type: String, lowercase: true, unique: true, required: true },
emailVerified: { type: Boolean, default: false },
password: String,
role: { type: String, default: 'USER', enum: ['USER', 'ADMIN'] },
providers: Array,
avatar: String,
created: { type: Date, default: Date.now },
lastLogin: { type: Date, default: Date.now }
}, { timestamps: true });
const User = mongoose.models.User || mongoose.model('User', userSchema);
// Check if demo user exists
const existingUser = await User.findOne({ email: 'hattori@hanzo.ai' });
if (!existingUser) {
const hashedPassword = await bcrypt.hash('demo1234', 10);
const demoUser = new User({
name: 'Hattori Hanzo',
username: 'hattori',
email: 'hattori@hanzo.ai',
emailVerified: true,
password: hashedPassword,
role: 'ADMIN',
providers: ['local'],
avatar: 'https://hanzo.ai/avatar/hattori.png'
});
await demoUser.save();
console.log('✅ Demo user created: hattori@hanzo.ai / demo1234');
} else {
console.log('️ Demo user already exists');
}
mongoose.disconnect();
})
.catch(err => {
console.error('Error:', err);
process.exit(1);
});
EOF
# Run the script
node /tmp/create_demo_user.js || true
rm -f /tmp/create_demo_user.js
}
# Start the initialization in background
(
wait_for_mongodb
create_demo_user
) &
# Start the main application
echo "🚀 Starting Hanzo Chat application..."
exec npm run backend
+88
View File
@@ -0,0 +1,88 @@
# Hanzo Router Configuration
# Unified LLM gateway for all AI providers in the Hanzo ecosystem
model_list:
# Primary Hanzo AI models (via Anthropic)
- model_name: hanzo-zen-1
litellm_params:
model: anthropic/claude-3-5-sonnet-20241022
api_key: os.environ/ANTHROPIC_API_KEY
model_info:
description: "Hanzo Zen-1: Fast, efficient AI for most tasks"
- model_name: hanzo-zen-1-pro
litellm_params:
model: anthropic/claude-3-opus-20240229
api_key: os.environ/ANTHROPIC_API_KEY
model_info:
description: "Hanzo Zen-1 Pro: Advanced reasoning for complex tasks"
# Additional models via different providers
- model_name: gpt-4
litellm_params:
model: openai/gpt-4
api_key: os.environ/OPENAI_API_KEY
- model_name: gpt-3.5-turbo
litellm_params:
model: openai/gpt-3.5-turbo
api_key: os.environ/OPENAI_API_KEY
# Together AI models
- model_name: mixtral-8x7b
litellm_params:
model: together_ai/mixtral-8x7b-32768
api_key: os.environ/TOGETHER_API_KEY
# Wildcard routing for flexibility
- model_name: "openai/*"
litellm_params:
model: "openai/*"
api_key: os.environ/OPENAI_API_KEY
- model_name: "anthropic/*"
litellm_params:
model: "anthropic/*"
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: "together_ai/*"
litellm_params:
model: "together_ai/*"
api_key: os.environ/TOGETHER_API_KEY
litellm_settings:
drop_params: true
num_retries: 3
request_timeout: 300
telemetry: false
router_settings:
routing_strategy: simple-shuffle
enable_pre_call_checks: true
redis_host: os.environ/REDIS_HOST
redis_password: os.environ/REDIS_PASSWORD
redis_port: os.environ/REDIS_PORT
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
store_model_in_db: true
database_url: os.environ/DATABASE_URL
database_connection_pool_limit: 10
# UI Configuration
ui_access_mode: "admin"
# Branding
custom_branding:
app_name: "Hanzo AI Chat"
logo_url: "/assets/hanzo-logo.svg"
primary_color: "#000000"
# MCP Integration
mcp_enabled: true
mcp_servers:
- name: "hanzo-mcp"
command: ["python", "-m", "hanzo_mcp_server"]
# Enable health checks
health_check_interval: 30
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
# Initialize demo user for Hanzo Chat
# Run this after docker compose up
echo "🚀 Initializing Hanzo Chat demo user..."
echo "📧 Email: hattori@hanzo.ai"
echo "🔑 Password: demo1234"
echo ""
# Wait for services to be ready
echo "⏳ Waiting for services to be ready..."
sleep 5
# Run the seed script inside a temporary container
docker run --rm \
--network chat_hanzo-network \
-e MONGO_URI="mongodb://hanzo:hanzo123@hanzo-mongodb:27017/HanzoChat?authSource=admin" \
-v "$PWD/scripts:/scripts" \
-w /scripts \
node:18-alpine sh -c "
npm install mongoose bcryptjs
node seed_demo_user.js
"
echo ""
echo "✅ Demo user initialization complete!"
echo "🌐 Access Hanzo Chat at: http://localhost:3081"
echo "📧 Login with: hattori@hanzo.ai / demo1234"
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/env node
/**
* Seed script to create demo user for Hanzo Chat
* Email: hattori@hanzo.ai
* Password: demo1234
*/
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// MongoDB connection URL from environment or default
const MONGO_URI = process.env.MONGO_URI || 'mongodb://hanzo:hanzo123@localhost:27017/HanzoChat?authSource=admin';
// User schema (matching LibreChat's schema)
const userSchema = new mongoose.Schema({
name: {
type: String,
},
username: {
type: String,
lowercase: true,
required: [true, "can't be blank"],
match: [/^[a-zA-Z0-9_]+$/, 'is invalid'],
index: true,
},
email: {
type: String,
lowercase: true,
unique: true,
required: [true, "can't be blank"],
match: [/\S+@\S+\.\S+/, 'is invalid'],
index: true,
},
emailVerified: {
type: Boolean,
default: false,
},
password: {
type: String,
trim: true,
minlength: 8,
maxlength: 128,
},
avatar: {
type: String,
required: false,
},
role: {
type: String,
default: 'USER',
enum: ['USER', 'ADMIN'],
},
provider: {
type: String,
required: false,
},
providers: {
type: Array,
required: false,
},
refreshToken: {
type: [String],
default: [],
},
created: {
type: Date,
default: Date.now,
},
lastLogin: {
type: Date,
default: Date.now,
},
plugins: {
type: Array,
default: [],
},
}, { timestamps: true });
const User = mongoose.model('User', userSchema);
async function seedDemoUser() {
try {
console.log('🔌 Connecting to MongoDB...');
await mongoose.connect(MONGO_URI);
console.log('✅ Connected to MongoDB');
// Check if demo user already exists
const existingUser = await User.findOne({ email: 'hattori@hanzo.ai' });
if (existingUser) {
console.log('⚠️ Demo user already exists');
return;
}
// Hash the password
const hashedPassword = await bcrypt.hash('demo1234', 10);
// Create demo user
const demoUser = new User({
name: 'Hattori Hanzo',
username: 'hattori',
email: 'hattori@hanzo.ai',
emailVerified: true,
password: hashedPassword,
role: 'ADMIN', // First user gets admin role
avatar: 'https://hanzo.ai/avatar/hattori.png',
providers: ['local'],
});
await demoUser.save();
console.log('✅ Demo user created successfully!');
console.log('📧 Email: hattori@hanzo.ai');
console.log('🔑 Password: demo1234');
console.log('👤 Role: ADMIN');
} catch (error) {
console.error('❌ Error seeding demo user:', error);
} finally {
await mongoose.disconnect();
console.log('🔌 Disconnected from MongoDB');
}
}
// Run the seed function
seedDemoUser();