fix: local mode

This commit is contained in:
Wendong-Fan 2025-09-03 02:50:23 +08:00
parent ce333106d3
commit f991f3b90c
5 changed files with 272 additions and 63 deletions

View file

@ -1,8 +1,6 @@
VITE_BASE_URL=/api
VITE_PROXY_URL=https://dev.eigent.ai
VITE_USE_LOCAL_PROXY=false
VITE_PROXY_URL=http://localhost:3001
VITE_USE_LOCAL_PROXY=true
# VITE_PROXY_URL=http://localhost:3001
# VITE_USE_LOCAL_PROXY=true

View file

@ -1,35 +1,72 @@
# Environment Configuration Example
# ================================
# EIGENT SERVER CONFIGURATION
# ================================
# Copy this file to .env and update with your own values
# IMPORTANT: Never commit .env with real values to version control
# ================================
# Application Settings
# ================================
debug=false
url_prefix=/api
# Security Configuration
# Generate with: openssl rand -hex 32
# ================================
# Security Configuration - MUST CHANGE!
# ================================
# Generate a secure secret key with: openssl rand -hex 32
# This is used for JWT token signing and must be kept secret
secret_key=CHANGE_THIS_TO_A_RANDOM_SECRET_KEY_USE_OPENSSL_RAND_HEX_32
# ================================
# Database Configuration
# Use a strong password in production
database_url=postgresql://postgres:CHANGE_THIS_STRONG_PASSWORD@localhost:5432/eigent
# ================================
# PostgreSQL connection string
# Format: postgresql://username:password@host:port/database
# For Docker setup, use 'eigent_postgres' as host
# For external PostgreSQL, update with your server details
database_url=postgresql://postgres:CHANGE_THIS_STRONG_PASSWORD@eigent_postgres:5432/eigent
# Docker Compose Database Settings (if using docker-compose)
# Docker Compose Database Settings
# These must match the password in database_url above
POSTGRES_PASSWORD=CHANGE_THIS_STRONG_PASSWORD
POSTGRES_USER=postgres
POSTGRES_DB=eigent
# ================================
# JWT Configuration
# Token expiration in seconds (3600 = 1 hour, recommended for production)
# ================================
# Token expiration in seconds
# 3600 = 1 hour (recommended for production)
# 86400 = 24 hours (convenient for development)
JWT_EXPIRATION=3600
# ================================
# Chat Share Security
# ================================
# Used for encrypting shared chat links
# Generate with: openssl rand -hex 32
CHAT_SHARE_SECRET_KEY=CHANGE_THIS_TO_A_RANDOM_SECRET_KEY
# Generate with: openssl rand -hex 16
CHAT_SHARE_SALT=CHANGE_THIS_TO_A_RANDOM_SALT
# Stack Auth Configuration (Optional)
# Leave empty if not using Stack Auth
# ================================
# Optional: Stack Auth Configuration
# ================================
# Only configure if using Stack Auth for authentication
# Leave empty if using local authentication only
STACK_AUTH_PROJECT_ID=
STACK_AUTH_API_KEY=
STACK_AUTH_BASE_URL=
STACK_AUTH_BASE_URL=
# ================================
# SETUP INSTRUCTIONS
# ================================
# 1. Copy this file: cp .env.example .env
# 2. Generate secure keys:
# echo "secret_key=$(openssl rand -hex 32)"
# echo "CHAT_SHARE_SECRET_KEY=$(openssl rand -hex 32)"
# echo "CHAT_SHARE_SALT=$(openssl rand -hex 16)"
# 3. Choose a strong database password
# 4. Update the .env file with generated values
# 5. Ensure POSTGRES_PASSWORD matches the password in database_url
# 6. Never commit the .env file with real values!

View file

@ -16,88 +16,252 @@
- MCP Management (import local/remote MCP servers)
- `GET /mcps`, `POST /mcp/install`, `POST /mcp/import/{Local|Remote}`, etc.
Note: All the above data is stored in the local PostgreSQL volume in Docker (see “Data Persistence” below). If you configure external models or remote MCP, requests go to the third-party services you specify.
Note: All the above data is stored in the local PostgreSQL volume in Docker (see "Data Persistence" below). If you configure external models or remote MCP, requests go to the third-party services you specify.
---
### Quick Start (Docker)
Prerequisite: Docker Desktop installed.
### Prerequisites
- Docker Desktop installed and running
- Node.js and npm installed (for frontend development)
- At least 2GB of free disk space
1) Start services
### Quick Start (Docker)
#### 1. Initial Setup
```bash
cd server
# Copy .env.example to .env(or create .env according to .env.example)
# Create the required public directory
mkdir -p app/public
# Copy and configure environment variables
cp .env.example .env
docker compose up -d
# Generate secure keys for your .env file
echo "Generating secure keys..."
echo "secret_key=$(openssl rand -hex 32)"
echo "CHAT_SHARE_SECRET_KEY=$(openssl rand -hex 32)"
echo "CHAT_SHARE_SALT=$(openssl rand -hex 16)"
```
2) Start Frontend (Local Mode)
- In the project root directory, create or modify `.env.development` to enable local mode and point to the local backend:
#### 2. Configure Environment Variables
Edit the `.env` file and replace the placeholder values with the generated keys:
```bash
VITE_USE_LOCAL_PROXY=true
VITE_PROXY_URL=http://localhost:3001
# IMPORTANT: Replace these with the values generated above
secret_key=YOUR_GENERATED_SECRET_KEY_HERE
CHAT_SHARE_SECRET_KEY=YOUR_GENERATED_CHAT_SECRET_HERE
CHAT_SHARE_SALT=YOUR_GENERATED_SALT_HERE
# Database configuration (you can change the password)
database_url=postgresql://postgres:your_secure_password@eigent_postgres:5432/eigent
POSTGRES_PASSWORD=your_secure_password
```
- Start the frontend application:
**Security Note**:
- Never commit the `.env` file with real values to version control
- Use strong, unique passwords for production environments
- The secret keys should be different for each deployment
#### 3. Start Services
```bash
# Build and start all services
docker compose up -d
# Wait for services to be ready (about 30 seconds for first run)
# Check if services are healthy
docker ps
# Verify the API is running
curl http://localhost:3001/health
# Should return: {"status":"healthy","service":"eigent-api"}
```
#### 4. Start Frontend (Local Mode)
In the project root directory (not in the server folder):
```bash
# Go back to the project root
cd ..
# Create or update .env.development to enable local mode
cat > .env.development << EOF
VITE_BASE_URL=/api
VITE_PROXY_URL=http://localhost:3001
VITE_USE_LOCAL_PROXY=true
EOF
# Install dependencies and start frontend
npm install
npm run dev
```
### Open API docs
- `http://localhost:3001/docs` (Swagger UI)
The application will be available at:
- Frontend: http://localhost:3000
- API: http://localhost:3001
- API Documentation: http://localhost:3001/docs
### Ports
- API: Host `3001` → Container `5678`
- PostgreSQL: Host `5432` → Container `5432`
---
### Data Persistence
- DB data is stored in Docker volume `server_postgres_data` at `/var/lib/postgresql/data` inside the container
- Database migrations run automatically on container startup (see `start.sh``alembic upgrade head`)
### Troubleshooting
#### Container keeps restarting
Check the logs to identify the issue:
```bash
docker logs eigent_api --tail 50
```
Common issues:
- **Missing environment variables**: Ensure all required variables in `.env` are set
- **Database connection failed**: Check that PostgreSQL is running and passwords match
- **Missing directories**: Ensure `app/public` directory exists
#### Database migration errors
If you see migration-related errors, you may need to reset the database:
```bash
# Stop services and remove volumes (WARNING: This deletes all data)
docker compose down -v
# Restart services
docker compose up -d
```
#### Port conflicts
If ports 3001 or 5432 are already in use, you can change them in `docker-compose.yml`:
```yaml
ports:
- "3002:5678" # Change 3001 to 3002 for API
- "5433:5432" # Change 5432 to 5433 for PostgreSQL
```
Remember to update the frontend `.env.development` accordingly.
---
### Common Commands
```bash
# List running containers
# View running containers
docker ps
# Stop/Start API container (keep DB)
docker stop eigent_api
docker start eigent_api
# Stop/Start all (API + DB)
# Stop/Start all services
docker compose stop
docker compose start
# View logs
docker logs -f eigent_api | cat
docker logs -f eigent_postgres | cat
docker logs -f eigent_api
docker logs -f eigent_postgres
# Rebuild after code changes
docker compose build api
docker compose up -d
# Complete reset (WARNING: Deletes all data)
docker compose down -v
docker compose up -d
```
---
### Developer Mode (Optional)
You can run the API locally with hot-reload while keeping the database in Docker:
For hot-reload during development:
```bash
# Stop API in container, keep DB
# Stop API container, keep database running
docker stop eigent_api
# Run locally (provide DB connection string)
# Run API locally with hot-reload
cd server
export database_url=postgresql://postgres:123456@localhost:5432/eigent
export database_url=postgresql://postgres:your_password@localhost:5432/eigent
export secret_key=$(openssl rand -hex 32)
export CHAT_SHARE_SECRET_KEY=$(openssl rand -hex 32)
export CHAT_SHARE_SALT=$(openssl rand -hex 16)
# Install dependencies and run
pip install uv
uv sync
uv run uvicorn main:api --reload --port 3001 --host 0.0.0.0
```
---
### Others
- API docs: `http://localhost:3001/docs`
- Runtime logs: `/app/runtime/log/app.log` in the container
- i18n (for developers)
### Data Persistence
- Database data: Stored in Docker volume `server_postgres_data`
- Location: `/var/lib/postgresql/data` inside the container
- Migrations: Run automatically on container startup via `start.sh`
To backup your data:
```bash
uv run pybabel extract -F babel.cfg -o messages.pot .
uv run pybabel init -i messages.pot -d lang -l zh_CN
uv run pybabel compile -d lang -l zh_CN
# Backup database
docker exec eigent_postgres pg_dump -U postgres eigent > backup.sql
# Restore database
docker exec -i eigent_postgres psql -U postgres eigent < backup.sql
```
For a fully offline environment, only use local models and local MCP servers, and avoid configuring any external Providers or remote MCP addresses.
---
### Security Considerations
1. **Environment Variables**:
- Always use strong, randomly generated secrets
- Never use the default/example values in production
- Keep `.env` file secure and never commit it to version control
2. **Database**:
- Change the default PostgreSQL password
- Consider using SSL for database connections in production
- Regularly backup your database
3. **API Access**:
- The API is exposed on localhost only by default
- For production, implement proper authentication and HTTPS
- Consider using a reverse proxy (nginx, traefik) for production deployments
4. **Offline Usage**:
- For fully offline environment, only use local models and local MCP servers
- Avoid configuring any external Providers or remote MCP addresses
---
### Advanced Configuration
#### Custom Database Settings
You can customize PostgreSQL settings by modifying `docker-compose.yml`:
```yaml
environment:
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
POSTGRES_HOST_AUTH_METHOD: "scram-sha-256" # More secure authentication
```
#### Performance Tuning
For better performance with large datasets:
```yaml
# In docker-compose.yml under postgres service
command:
- "postgres"
- "-c"
- "shared_buffers=256MB"
- "-c"
- "max_connections=200"
```
#### Using External PostgreSQL
If you prefer to use an external PostgreSQL instance:
1. Update `database_url` in `.env` to point to your PostgreSQL server
2. Comment out the `postgres` service in `docker-compose.yml`
3. Remove the `depends_on` section from the `api` service
---
### API Documentation
Full API documentation is available at `http://localhost:3001/docs` (Swagger UI) after starting the services.
### Support
For issues or questions:
- Check the logs first: `docker logs eigent_api`
- Review common issues in the Troubleshooting section
- Ensure all prerequisites are met and steps are followed in order

View file

@ -17,7 +17,7 @@ from app.model.mcp.mcp import Status
from app.model.mcp.mcp_env import Status
from app.model.mcp.mcp_user import McpType
from app.model.mcp.mcp_user import Status
from app.model.provider.provider import VaildStatus
from app.model.provider.provider import ValidStatus
from app.model.user.admin import Status
from app.model.user.key import KeyStatus
from app.model.user.role import RoleType
@ -48,14 +48,6 @@ def upgrade() -> None:
sa.Column("status", ChoiceType(choices=Status, impl=sa.SmallInteger()), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"admin_role",
sa.Column("admin_id", sa.Integer(), nullable=False),
sa.Column("role_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(["admin_id"], ["admin.id"], ondelete="CASCADE"),
sa.ForeignKeyConstraint(["role_id"], ["role.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("admin_id", "role_id"),
)
op.create_table(
"category",
sa.Column("deleted_at", sa.DateTime(), nullable=True),
@ -167,7 +159,7 @@ def upgrade() -> None:
sa.Column("prefer", sa.Boolean(), server_default=sa.text("false"), nullable=True),
sa.Column(
"is_vaild",
ChoiceType(choices=VaildStatus, impl=sa.SmallInteger()),
ChoiceType(choices=ValidStatus, impl=sa.SmallInteger()),
server_default=sa.text("1"),
nullable=True,
),
@ -186,6 +178,14 @@ def upgrade() -> None:
sa.Column("permissions", sa.JSON(), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"admin_role",
sa.Column("admin_id", sa.Integer(), nullable=False),
sa.Column("role_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(["admin_id"], ["admin.id"], ondelete="CASCADE"),
sa.ForeignKeyConstraint(["role_id"], ["role.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("admin_id", "role_id"),
)
op.create_table(
"user",
sa.Column("deleted_at", sa.DateTime(), nullable=True),
@ -379,6 +379,7 @@ def downgrade() -> None:
op.drop_index(op.f("ix_key_user_id"), table_name="key")
op.drop_table("key")
op.drop_table("user")
op.drop_table("admin_role")
op.drop_table("role")
op.drop_index(op.f("ix_provider_user_id"), table_name="provider")
op.drop_table("provider")
@ -397,6 +398,5 @@ def downgrade() -> None:
op.drop_index(op.f("ix_chat_history_task_id"), table_name="chat_history")
op.drop_table("chat_history")
op.drop_table("category")
op.drop_table("admin_role")
op.drop_table("admin")
# ### end Alembic commands ###

View file

@ -30,15 +30,25 @@ services:
context: .
dockerfile: Dockerfile
args:
database_url: ${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/eigent}
database_url: ${database_url:-postgresql://postgres:changeme@eigent_postgres:5432/eigent}
container_name: eigent_api
restart: unless-stopped
ports:
- "3001:5678"
env_file:
- .env
environment:
- DATABASE_URL=${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/eigent}
- database_url=${database_url:-postgresql://postgres:changeme@eigent_postgres:5432/eigent}
- ENVIRONMENT=production
- DEBUG=false
- DEBUG=${debug:-false}
- secret_key=${secret_key}
- url_prefix=${url_prefix:-/api}
- JWT_EXPIRATION=${JWT_EXPIRATION:-3600}
- CHAT_SHARE_SECRET_KEY=${CHAT_SHARE_SECRET_KEY}
- CHAT_SHARE_SALT=${CHAT_SHARE_SALT}
- STACK_AUTH_PROJECT_ID=${STACK_AUTH_PROJECT_ID}
- STACK_AUTH_API_KEY=${STACK_AUTH_API_KEY}
- STACK_AUTH_BASE_URL=${STACK_AUTH_BASE_URL}
# volumes:
# - ./app:/app/app
# - ./alembic:/app/alembic