chore: add pnpm workspace configuration for apps and packages

This commit is contained in:
GW_MC
2026-02-23 21:04:19 +08:00
parent ab02758382
commit 932f384f0d
31 changed files with 9081 additions and 203 deletions

View File

@@ -112,24 +112,6 @@ services:
networks:
- dreamchat-network
keycloak:
image: quay.io/keycloak/keycloak:23.0
restart: unless-stopped
command: start-dev
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://db:5432/keycloak
KC_DB_USERNAME: postgres
KC_DB_PASSWORD: postgres
ports:
- "8080:8080"
depends_on:
- db
networks:
- dreamchat-network
volumes:
postgres-data:
@@ -138,6 +120,8 @@ networks:
driver: bridge
```
**Note:** Keycloak is configured as an external service. Set `KEYCLOAK_URL` in your environment to point to your external Keycloak instance.
### .devcontainer/Dockerfile
```dockerfile
@@ -274,15 +258,15 @@ services:
timeout: 10s
retries: 3
# Frontend
# Frontend (static file server)
# Note: External reverse proxy expected for SSL and routing
frontend:
build:
context: .
dockerfile: apps/frontend/Dockerfile
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "3001:3000"
environment:
- VITE_API_URL=/api
- VITE_WS_URL=/ws
@@ -319,23 +303,6 @@ services:
networks:
- dreamchat-network
# Nginx Reverse Proxy (optional)
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- model-cache:/model-cache:ro
depends_on:
- backend
- frontend
networks:
- dreamchat-network
volumes:
postgres-data:
redis-data:
@@ -400,7 +367,7 @@ KEYCLOAK_CLIENT_SECRET=your_keycloak_secret
```dockerfile
# apps/backend/Dockerfile
FROM node:20-alpine AS base
FROM node:24-alpine AS base
RUN npm install -g pnpm@8
FROM base AS dependencies
@@ -456,7 +423,7 @@ CMD ["node", "dist/main.js"]
```dockerfile
# apps/frontend/Dockerfile
FROM node:20-alpine AS base
FROM node:24-alpine AS base
RUN npm install -g pnpm@8
FROM base AS dependencies
@@ -486,46 +453,59 @@ RUN pnpm --filter @dreamchat/shared build
# Build frontend
RUN pnpm --filter @dreamchat/frontend build
# Production with Nginx
FROM nginx:alpine
# Production stage - using serve for static files
# External reverse proxy (nginx/traefik/etc.) expected
FROM node:24-alpine AS production
WORKDIR /app
# Install serve
RUN npm install -g serve
# Copy built assets
COPY --from=build /app/apps/frontend/dist /usr/share/nginx/html
COPY --from=build /app/apps/frontend/dist ./dist
# Copy nginx config
COPY apps/frontend/nginx.conf /etc/nginx/conf.d/default.conf
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs
EXPOSE 80
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]
# Serve static files
# Note: External reverse proxy should handle:
# - SSL/TLS termination
# - Path routing (/api -> backend, / -> frontend)
# - WebSocket proxying
CMD ["serve", "-s", "dist", "-l", "3000"]
```
### frontend/nginx.conf
### External Reverse Proxy Configuration
The frontend container serves static files on port 3000. An external reverse proxy is expected to handle:
- **SSL/TLS termination**
- **Path routing**:
- `/api/*` → Backend (port 3000)
- `/ws` → Backend WebSocket (port 3000)
- `/*` → Frontend (port 3001)
- **Static file caching**
Example nginx configuration:
```nginx
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
listen 443 ssl;
server_name dreamchat.example.com;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# API proxy
location /api {
proxy_pass http://backend:3000/api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# WebSocket proxy
@@ -534,45 +514,110 @@ server {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Static files
# Frontend static files
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control "public, max-age=31536000, immutable";
}
# Health check
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
}
```
## Keycloak Configuration
## Keycloak Configuration (External)
### Initial Setup
Keycloak is configured as an external service with support for group/role/attribute-based authorization and auto-user creation.
1. Access Keycloak admin console: `http://localhost:8080/admin`
2. Login with admin credentials
3. Create new realm: `dreamchat`
4. Create client: `dreamchat-backend`
### Prerequisites
1. Have a running Keycloak instance (self-hosted or managed)
2. Configure the following environment variables in `.env`:
```bash
# Basic Keycloak settings
KEYCLOAK_ENABLED=true
KEYCLOAK_URL=http://your-keycloak-server:8080
KEYCLOAK_REALM=dreamchat
KEYCLOAK_CLIENT_ID=dreamchat-backend
KEYCLOAK_CLIENT_SECRET=your_keycloak_secret
# Authorization settings (optional but recommended)
KEYCLOAK_REQUIRED_GROUP=dreamchat-users
KEYCLOAK_REQUIRED_ROLE=dreamchat-access
KEYCLOAK_REQUIRED_CLIENT_ROLE=user
KEYCLOAK_REQUIRED_ATTRIBUTE=approved:true
# Auto-create users
KEYCLOAK_AUTO_CREATE_USER=true
KEYCLOAK_DEFAULT_USER_ROLE=USER
```
### Keycloak Realm Setup
1. Access your Keycloak admin console
2. Create new realm: `dreamchat`
3. Create client: `dreamchat-backend`
- Client authentication: ON
- Authorization: ON
- Valid redirect URIs: `http://localhost:3000/*`
- Web origins: `http://localhost:3000`
5. Create client: `dreamchat-frontend`
4. Create client: `dreamchat-frontend`
- Client authentication: OFF
- Valid redirect URIs: `http://localhost:5173/*`
- Web origins: `http://localhost:5173`
### Authorization Configuration
You can restrict access based on:
**1. Group Membership**
```bash
KEYCLOAK_REQUIRED_GROUP=dreamchat-users
```
Users must be members of this Keycloak group to access the application.
**2. Realm Role**
```bash
KEYCLOAK_REQUIRED_ROLE=dreamchat-access
```
Users must have this realm-level role.
**3. Client Role**
```bash
KEYCLOAK_REQUIRED_CLIENT_ROLE=user
```
Users must have this role for the `dreamchat-backend` client.
**4. User Attribute**
```bash
KEYCLOAK_REQUIRED_ATTRIBUTE=department:engineering
# or
KEYCLOAK_REQUIRED_ATTRIBUTE=approved:true
```
Users must have this attribute with the specified value.
### User Auto-Creation
When `KEYCLOAK_AUTO_CREATE_USER=true`:
- Users are automatically created in the database on first Keycloak login
- Username is derived from Keycloak preferred_username
- Email is taken from Keycloak email claim
- Role is set to `KEYCLOAK_DEFAULT_USER_ROLE` (default: USER)
- The `keycloakSub` field links the local user to Keycloak
When `KEYCLOAK_AUTO_CREATE_USER=false`:
- Only existing local users can log in via Keycloak
- The `keycloakSub` must match between Keycloak and local user
### Example Keycloak Group/Role Setup
1. Create a group: `dreamchat-users`
2. Create a realm role: `dreamchat-access`
3. Assign the group and/or role to users who should have access
4. Configure `KEYCLOAK_REQUIRED_GROUP` and/or `KEYCLOAK_REQUIRED_ROLE`
### realm-export.json (Optional)
```json