mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-11-02 14:11:49 +08:00
Require explicitly configured secure JWT secrets for server deployments and persist a random per-installation desktop secret across restarts. Preserve explicit environment overrides for strict server validation. Fixes #665.
397 lines
14 KiB
Markdown
397 lines
14 KiB
Markdown
# Configuration
|
|
|
|
**Three places to configure MateClaw: `application.yml`, environment variables, and the database.**
|
|
|
|
Most settings live in `application.yml` (Spring Boot's default config file), with sensitive values overridden by environment variables. Anything you want to change at runtime — model providers, search keys, feature toggles — lives in the `mate_system_setting` table and is edited through the Settings page.
|
|
|
|
Deep-dive topics have their own pages — Tool Guard rules in [Security & Approval](./security), model providers in [Models](./models), memory tuning in [Memory](./memory).
|
|
|
|
---
|
|
|
|
## Profiles
|
|
|
|
| Profile | Database | Activated by |
|
|
|---------|----------|--------------|
|
|
| `default` | H2 file at `./data/mateclaw` | No action needed |
|
|
| `mysql` | MySQL 8.0+ | `spring.profiles.active=mysql` or `SPRING_PROFILES_ACTIVE=mysql` |
|
|
| `postgres` | PostgreSQL 16+ | `SPRING_PROFILES_ACTIVE=postgres` |
|
|
| `kingbase` | KingbaseES | `SPRING_PROFILES_ACTIVE=kingbase` (opt-in driver required) |
|
|
|
|
The public Docker Compose stack activates `postgres`. Desktop builds use `default`; the `mysql` profile remains supported for existing or self-managed deployments.
|
|
|
|
---
|
|
|
|
## Core `application.yml` sections
|
|
|
|
### Server
|
|
|
|
```yaml
|
|
server:
|
|
port: 18088 # HTTP port
|
|
servlet:
|
|
context-path: /
|
|
```
|
|
|
|
### Database — H2 (development)
|
|
|
|
```yaml
|
|
spring:
|
|
datasource:
|
|
url: jdbc:h2:file:./data/mateclaw;MODE=MYSQL
|
|
username: sa
|
|
password:
|
|
driver-class-name: org.h2.Driver
|
|
h2:
|
|
console:
|
|
enabled: true # Available at /h2-console (disable in production)
|
|
```
|
|
|
|
### Database — MySQL (supported self-managed deployment)
|
|
|
|
```yaml
|
|
spring:
|
|
profiles:
|
|
active: mysql
|
|
datasource:
|
|
url: jdbc:mysql://localhost:3306/mateclaw?useSSL=false&serverTimezone=UTC
|
|
username: root
|
|
password: ${DB_PASSWORD}
|
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
```
|
|
|
|
### AI model — managed in the UI, not YAML
|
|
|
|
::: tip
|
|
**Model configuration is 100% UI-driven.** Don't put `spring.ai.*` blocks in `application.yml` — every provider, key, and model config lives in `Settings → Models`, backed by the `mate_model_provider` and `mate_model_config` tables.
|
|
:::
|
|
|
|
**Provider, key, and model rows in the database are the primary configuration.** On a fresh install, log in and add the first provider under `Settings → Models → Add Provider`. `DASHSCOPE_API_KEY` remains a compatibility fallback for DashScope auto-configuration, but it does not replace the provider row; do not assume equivalent environment variables are read for other providers. Full reference in [Models](./models).
|
|
|
|
### Virtual threads (JDK 21)
|
|
|
|
```yaml
|
|
spring:
|
|
threads:
|
|
virtual:
|
|
enabled: true
|
|
```
|
|
|
|
Enabled by default. Tomcat request threads, `@Scheduled` tasks, and `@Async` methods all run on virtual threads. SSE long-connections no longer hold platform threads, and I/O-bound async tasks (memory extraction, auditing, skill install, etc.) no longer queue behind a 16-thread pool.
|
|
|
|
### Spring AI Observability
|
|
|
|
```yaml
|
|
spring:
|
|
ai:
|
|
chat:
|
|
observations:
|
|
log-prompt: false # don't write prompt content into spans (security)
|
|
log-completion: false # don't write completion content into spans
|
|
```
|
|
|
|
When enabled, `/actuator/metrics/gen_ai.client.operation` and `/actuator/metrics/gen_ai.client.token.usage` automatically record latency and token usage for every LLM call. Requires `spring-boot-starter-actuator` (already included).
|
|
|
|
### Context window
|
|
|
|
```yaml
|
|
mate:
|
|
agent:
|
|
conversation:
|
|
window:
|
|
default-max-input-tokens: 128000
|
|
compact-trigger-ratio: 0.75
|
|
preserve-recent-pairs: 2
|
|
summary-max-tokens: 300
|
|
```
|
|
|
|
Details in [Memory](./memory).
|
|
|
|
### Memory extraction and consolidation
|
|
|
|
```yaml
|
|
mate:
|
|
memory:
|
|
auto-summarize-enabled: true
|
|
min-messages-for-summarize: 4
|
|
min-user-message-length: 10
|
|
skip-cron-conversations: true
|
|
summary-max-tokens: 1000
|
|
max-transcript-messages: 30
|
|
cooldown-minutes: 5
|
|
emergence-enabled: true
|
|
emergence-day-range: 7
|
|
```
|
|
|
|
### LLM Wiki
|
|
|
|
```yaml
|
|
mate:
|
|
wiki:
|
|
enabled: true
|
|
max-chunk-size: 30000
|
|
max-context-chars: 10000
|
|
max-pages-per-raw: 15
|
|
max-parallel-raw-materials: 3
|
|
max-parallel-phase-b-pages: 3
|
|
auto-process-on-upload: true
|
|
upload-dir: ./data/wiki-uploads
|
|
```
|
|
|
|
Details in [LLM Wiki](./wiki).
|
|
|
|
### Tool Guard (rule-based)
|
|
|
|
Tool Guard's global switch, default policy, and rules are **not configured in application.yml** — they live in the database (`mate_tool_guard_config` / `mate_tool_guard_rule`) and are edited from the admin **Security** page or via REST:
|
|
|
|
| Method | Path | What it does |
|
|
|---|---|---|
|
|
| `GET` / `PUT` | `/api/v1/security/guard/config` | Global switch + default policy (`allow` / `deny` / `require_approval`) |
|
|
| `GET` | `/api/v1/security/guard/rules/builtin` | Built-in rules |
|
|
| `GET` / `POST` | `/api/v1/security/guard/rules` | List / create custom rules |
|
|
| `PUT` | `/api/v1/security/guard/rules/{ruleId}` | Update a rule |
|
|
| `PUT` | `/api/v1/security/guard/rules/{ruleId}/toggle` | Enable/disable a single rule |
|
|
|
|
Each rule matches on tool name + argument pattern and yields an `allow` / `deny` / `require_approval` action, ordered by priority. Details in [Security & Approval](./security).
|
|
|
|
### File Guard
|
|
|
|
File Guard has two layers:
|
|
|
|
1. **Allowed / denied path rules** — like Tool Guard, stored in the database and edited from the admin **Security** page; REST is `GET` / `PUT /api/v1/security/guard/config/file-guard`. **Not in application.yml.**
|
|
2. **Global fallback sandbox root** — the only piece that lives in application.yml. When a conversation has no per-workspace base path configured, file/shell tools are confined to this root (fail-closed default):
|
|
|
|
```yaml
|
|
mateclaw:
|
|
workspace:
|
|
sandbox:
|
|
enabled: true # set false to restore the legacy unconstrained behaviour
|
|
root: ${user.dir}/data/workspace # fallback sandbox root, created at startup
|
|
```
|
|
|
|
Environment overrides: `MATECLAW_WORKSPACE_SANDBOX_ENABLED` / `MATECLAW_WORKSPACE_SANDBOX_ROOT`.
|
|
|
|
### JWT authentication
|
|
|
|
```yaml
|
|
mateclaw:
|
|
jwt:
|
|
secret: ${JWT_SECRET:}
|
|
expiration: 86400000
|
|
```
|
|
|
|
::: warning
|
|
`JWT_SECRET` is required at startup in every environment. Set a unique random value of at least 32 UTF-8 bytes; generate one with `openssl rand -base64 48`. Never commit it. Rotating it invalidates existing tokens.
|
|
:::
|
|
|
|
### Skill workspace
|
|
|
|
```yaml
|
|
mateclaw:
|
|
skill:
|
|
workspace:
|
|
root: ${user.home}/.mateclaw/skills
|
|
auto-init: true
|
|
delete-policy: archive
|
|
bundled-skills-path: skills
|
|
```
|
|
|
|
### Multimodal default providers
|
|
|
|
```yaml
|
|
mate:
|
|
image:
|
|
default-provider: dashscope
|
|
video:
|
|
default-provider: dashscope
|
|
tts:
|
|
default-provider: cosyvoice
|
|
stt:
|
|
default-provider: paraformer
|
|
music:
|
|
default-provider: dashscope
|
|
```
|
|
|
|
Details in [Multimodal](./multimodal).
|
|
|
|
---
|
|
|
|
## Environment variables
|
|
|
|
::: warning Manage LLM keys in the console
|
|
Provider, key, and model rows in `Settings → Models` are primary. `DASHSCOPE_API_KEY` remains only as a compatibility fallback for DashScope auto-configuration; do not assume equivalent environment variables are read for other providers.
|
|
:::
|
|
|
|
| Variable | Required | Purpose |
|
|
|----------|----------|---------|
|
|
| `SERPER_API_KEY` | — | Google Serper search key (search tools not yet UI-managed) |
|
|
| `TAVILY_API_KEY` | — | Tavily search key (same as above) |
|
|
| `JWT_SECRET` | Yes | JWT signing secret |
|
|
| `MATECLAW_CORS_ALLOWED_ORIGINS` | — | CORS allowlist (recommended in production) |
|
|
| `DB_PASSWORD` / `DB_ADMIN_PASSWORD` | Docker | PostgreSQL application / bootstrap-admin passwords (must differ) |
|
|
| `DB_USERNAME` / `DB_ADMIN_USERNAME` | — | PostgreSQL application / bootstrap-admin usernames |
|
|
| `DB_HOST` / `DB_PORT` / `DB_NAME` | — | Database address, port, and name |
|
|
| `SPRING_PROFILES_ACTIVE` | — | Docker Compose sets `postgres`; self-managed deployments may use `mysql` / `kingbase` |
|
|
|
|
### Setting them
|
|
|
|
**Linux / macOS:**
|
|
|
|
```bash
|
|
export JWT_SECRET="$(openssl rand -base64 48)"
|
|
export SERPER_API_KEY=your-serper-key # optional
|
|
```
|
|
|
|
**Windows (PowerShell):**
|
|
|
|
```powershell
|
|
$env:JWT_SECRET = openssl rand -base64 48
|
|
```
|
|
|
|
**Docker (`.env` file):**
|
|
|
|
```properties
|
|
DB_PASSWORD=secure-password-here
|
|
DB_ADMIN_PASSWORD=different-secure-password-here
|
|
# Generate with: openssl rand -base64 48
|
|
JWT_SECRET=replace-with-generated-value
|
|
```
|
|
|
|
After startup, open `http://localhost:18080`, sign in as `admin / admin123`, and add your first LLM provider under `Settings → Models → Add Provider`.
|
|
|
|
---
|
|
|
|
## Database schema init
|
|
|
|
MateClaw uses **Flyway** for schema migrations:
|
|
|
|
1. `db/migration/h2/V*__*.sql` — H2-dialect migration scripts
|
|
2. `db/migration/mysql/V*__*.sql` — MySQL-dialect migration scripts
|
|
3. After migrations, seed data is loaded from `db/data-*.sql` — idempotent
|
|
|
|
Flyway selects the migration dialect from the active Spring profile. Startup runs `migrate` with checksum validation enabled by default in all bundled profiles. Applied migration files must not be edited: checksum drift or a failed migration stops startup rather than silently changing the schema history.
|
|
|
|
**Desktop upgrade compatibility:** an existing desktop database whose applied scripts differ from the new release can now fail to start. A new database and an unchanged migration history need no repair. Keep a backup that can be opened with the previous application version; do not delete the database to clear a validation error.
|
|
|
|
If validation fails:
|
|
|
|
1. Stop the application and back up the database. Keep the exact previous and target release artifacts, and inspect the failing migration and schema history.
|
|
2. Compare the old and new SQL with the actual schema/data. Prefer restoring the expected migration file or a maintainer-provided forward migration. `repair` changes migration metadata; it does **not** execute changed DDL, undo partial DDL/data changes, or prove the schema is correct. Resolve any partial migration effects before proceeding.
|
|
3. Only after confirming that history repair is appropriate, set `mateclaw.flyway.auto-repair=true` (environment variable `MATECLAW_FLYWAY_AUTOREPAIR=true`) for one controlled startup. Repair uses the configured migration locations and is followed by normal migration. Keep validation enabled.
|
|
4. Remove the opt-in immediately afterwards, restart normally, and verify validation and application behavior before allowing writes. If recovery fails, restore the backup with its matching application version.
|
|
|
|
The opt-in defaults to `false`, including Desktop. It is not an unattended upgrade policy. `spring.flyway.validate-on-migrate` remains externally configurable, but setting it to `false` bypasses the validation guard and is not a repair procedure.
|
|
|
|
### Table conventions
|
|
|
|
- All tables prefixed `mate_`
|
|
- `snake_case` columns, `camelCase` Java fields (auto-mapped by MyBatis Plus)
|
|
- Every table has `create_time`, `update_time`, `deleted`
|
|
- Logical delete: `deleted = 0` active, `deleted = 1` soft-deleted
|
|
|
|
### H2 console in dev
|
|
|
|
[http://localhost:18088/h2-console](http://localhost:18088/h2-console):
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| JDBC URL | `jdbc:h2:file:./data/mateclaw` |
|
|
| Username | `sa` |
|
|
| Password | *(empty)* |
|
|
|
|
### Switching to MySQL
|
|
|
|
```sql
|
|
CREATE DATABASE mateclaw CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
```
|
|
|
|
```bash
|
|
export SPRING_PROFILES_ACTIVE=mysql
|
|
export DB_PASSWORD=your-password
|
|
mvn spring-boot:run
|
|
```
|
|
|
|
---
|
|
|
|
## Runtime settings (`mate_system_setting`)
|
|
|
|
Things you want to change without restarting:
|
|
|
|
| Key | Type | Purpose |
|
|
|-----|------|---------|
|
|
| `default_agent_id` | Long | Agent used when none specified |
|
|
| `default_model_config_id` | Long | Default model configuration |
|
|
| `max_conversation_turns` | Integer | Max turns per conversation |
|
|
| `enable_memory` | Boolean | Enable memory extraction |
|
|
| `search_enabled` | Boolean | Global web search toggle |
|
|
| `search_provider` | String | `serper` / `tavily` / `duckduckgo` / `searxng` |
|
|
| `search_fallback_enabled` | Boolean | Fall through to next provider on failure |
|
|
| `serper_api_key` | String | Serper key (masked in UI) |
|
|
| `tavily_api_key` | String | Tavily key (masked in UI) |
|
|
| `language` | String | `zh-CN` / `en-US` default UI language |
|
|
| `stream_enabled` | Boolean | SSE streaming output |
|
|
| `debug_mode` | Boolean | Show extra debug info in UI |
|
|
|
|
All editable from `Settings → System`. Changes take effect immediately.
|
|
|
|
### Search service configuration
|
|
|
|
Web search config has been migrated from `application.yml` to the **System Settings** page. Changes take effect immediately without restart.
|
|
|
|
::: tip
|
|
API keys are displayed masked. When saving, keys are only overwritten when a new value is entered. Blank input means "keep existing key".
|
|
:::
|
|
|
|
---
|
|
|
|
## Logging
|
|
|
|
```yaml
|
|
logging:
|
|
level:
|
|
vip.mate: INFO
|
|
vip.mate.agent: DEBUG
|
|
vip.mate.agent.graph: DEBUG
|
|
org.springframework.ai: INFO
|
|
root: INFO
|
|
```
|
|
|
|
For deep debugging, set `vip.mate: TRACE`. Log volume is high — don't leave it on in production.
|
|
|
|
---
|
|
|
|
## CORS
|
|
|
|
Development: Vite's dev server handles CORS via its proxy. Production: frontend is embedded in the JAR, no CORS needed.
|
|
|
|
If you deploy the frontend separately:
|
|
|
|
```yaml
|
|
mateclaw:
|
|
cors:
|
|
allowed-origins:
|
|
- http://localhost:5173
|
|
- https://your-domain.com
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration precedence
|
|
|
|
Settings resolve in this order (highest priority first):
|
|
|
|
1. **Environment variables**
|
|
2. **Command-line arguments** (`--server.port=9090`)
|
|
3. **`application-{profile}.yml`**
|
|
4. **`application.yml`**
|
|
5. **Database `mate_system_setting`** (for runtime-configurable values)
|
|
|
|
---
|
|
|
|
## Next
|
|
|
|
- [Models](./models) — provider and model config in detail
|
|
- [Security & Approval](./security) — JWT, Tool Guard, File Guard, audit log
|
|
- [Memory](./memory) — memory tuning parameters
|
|
- [LLM Wiki](./wiki) — `mate.wiki` block explained
|
|
- [Channels](./channels) — channel-specific configuration
|