Site Settings
Configure branding, registration policy, security, notifications, storage, and compliance entry points
Site settings determine the logged-out pages, authentication flow, resource limits, and runtime policies. Only users with the corresponding admin:settings:* permissions or super administrator status can see the matching tabs.
Accessing System Settings
- Log in as administrator.
- Navigate to Admin → Site Settings (Settings section in the sidebar).
- Choose a category from the settings sub-navigation.
Settings categories:
- General (
/site-settings) - Security (
/site-settings/security) - Notifications (
/site-settings/notifications) - Storage (
/site-settings/storage) - Memory (
/site-settings/memory) - SSO (
/site-settings/sso)
Settings are stored as key-value site settings and exposed through GET /api/v1/admin/site-settings (single key: GET/PUT /api/v1/admin/site-settings/{key}, bulk update: PUT /api/v1/admin/site-settings). Viewing requires admin:settings:read; updating requires admin:settings:update.
General Settings
Site Information
Configure site name, URL, description, icon, default language, and authentication page layout:
| Field | Type | Default | Description |
|---|---|---|---|
site_name | string | Clouisle | Site name |
site_url | string | empty | Site URL |
site_description | string | empty | Site description |
site_icon | string | empty | Site icon URL |
default_language | en or zh | en | Default language |
auth_page_layout | centered or split | centered | Authentication page layout |
Update site information: Navigate to Settings → General, update fields, and click Save Changes.
Theme and Display
Configure theme mode, primary color, branding display, and interface elements:
| Field | Type | Default | Description |
|---|---|---|---|
theme_mode | light, dark, or system | system | Site default theme mode (users can override it in their own settings) |
theme_primary_color | string | empty | Theme primary color (empty uses the built-in palette) |
theme_branding_display | full, name_only, icon_only, or hidden | full | Branding display |
Additional theme tokens (primary foreground, background, card, sidebar, navbar, accent, chart colors, etc.) can also be customized.
Update branding: Navigate to Settings → General, adjust theme mode and color tokens, and click Save Changes.
Language Settings
Configure site default language and multilingual support:
| Field | Type | Default | Description |
|---|---|---|---|
default_language | en or zh | en | Site default language |
Users can switch the interface language in their personal settings. After switching, interface text and notification messages use the corresponding language translation.
Legal & Compliance
Configure ICP record, terms of service, and privacy policy:
| Field | Type | Default | Description |
|---|---|---|---|
icp_record_number | string | empty | ICP record number |
icp_record_url | string | empty | ICP record URL |
terms_enabled | boolean | false | Enable terms of service |
terms_url | string | empty | Terms URL |
terms_text | string | empty | Terms text (Markdown, used when no URL) |
privacy_enabled | boolean | false | Enable privacy policy |
privacy_url | string | empty | Privacy policy URL |
privacy_text | string | empty | Privacy policy text (Markdown, used when no URL) |
require_terms_acceptance_on_register | boolean | false | Require terms acceptance on registration |
Terms and privacy entries are shown only when enabled and a URL or text is provided. Registration acceptance is enforced only when require_terms_acceptance_on_register is true.
Security Settings
Registration
Configure registration, approval, email verification, and account deletion policies:
| Field | Type | Default | Description |
|---|---|---|---|
allow_registration | boolean | true | Allow registration |
require_approval | boolean | true | Admin approval for new users |
email_verification | boolean | true | Email verification |
allow_account_deletion | boolean | true | Allow account deletion |
default_role_id | string | Viewer role | Default role (set automatically at initialization) |
default_team_id | string | empty | Default team |
default_team_role | viewer, member, or admin | member | Default team role |
Password Policy
Configure password complexity requirements:
| Field | Type | Default | Description |
|---|---|---|---|
min_password_length | number | 8 | Minimum password length |
require_uppercase | boolean | true | Require uppercase letter |
require_number | boolean | true | Require number |
require_special_char | boolean | false | Require special character |
require_lowercase setting.Password expiration configuration:
| Field | Type | Default | Description |
|---|---|---|---|
password_expiration_enabled | boolean | false | Enable password expiration |
password_expiration_days | number | 90 | Password expiration days |
password_expiration_warning_days | number | 7 | Warning days before expiration |
password_history_count | number | 5 | Password history count |
password_min_age_days | number | 0 | Minimum password age in days |
force_password_change_first_login | boolean | false | Force password change on first login |
Session Settings
Configure session timeout, login attempt limits, and CAPTCHA:
| Field | Type | Default | Description |
|---|---|---|---|
session_timeout_days | number | 30 | Session timeout in days |
single_session | boolean | false | Allow only a single session per user |
max_login_attempts | number | 5 | Max login attempts before lockout |
lockout_duration_minutes | number | 15 | Lockout duration in minutes |
enable_captcha | boolean | false | Enable CAPTCHA |
single_session boolean, and the session lifetime is session_timeout_days (default 30 days).Two-Factor Authentication
| Field | Type | Default | Description |
|---|---|---|---|
require_totp | boolean | false | Require all users to enable TOTP |
Admin TOTP statistics and per-user status/disable endpoints are available under /api/v1/admin/totp.
Human Verification
| Field | Type | Default | Description |
|---|---|---|---|
enable_captcha | boolean | false | Enable human verification on the login page |
Once enabled, password logins must carry a one-time verification credential (captcha_id + captcha_token): the front end first calls POST /api/v1/login/captcha/click to exchange a valid click interaction for a private one-time proof, then submits it with the login. A missing credential raises captcha_required; a failed check raises captcha_invalid.
A single switch, nothing more
The Security page has exactly one CAPTCHA switch ("Enable Human Verification") — there are no failure thresholds, validity periods, or difficulty settings. Treat it as a supplement that raises the cost of automated attempts, not as a replacement for lockout and TOTP: brute-force protection actually comes from max_login_attempts (default 5) / lockout_duration_minutes (default 15) and require_totp. Assuming enable_captcha means "bot logins are solved" leaves a brute-force exposure.
Model Endpoint Allowlist
Before saving or testing a model with a new API endpoint:
- Navigate to Settings → Security.
- Add the endpoint Origin to Model Endpoint Allowlist, one per line.
- Include only the scheme, hostname, and non-default port, for example
https://gateway.example.comorhttp://ollama.internal:11434. - Save the Security settings, then save or test the model again.
Security
Prefer HTTPS for remote endpoints. Use HTTP only for endpoints on a trusted private network because API keys and model traffic are otherwise sent without transport encryption.
Matching is exact. URL paths are ignored, but the scheme, hostname, and port must all match. Removing an Origin blocks subsequent model discovery, connection tests, and runtime requests without restarting the service. The default allowlist ships with 20 known provider origins (e.g. https://api.openai.com, https://api.anthropic.com, http://localhost:11434) and stores at most 200 entries.
Outbound Network Allowlist (SSRF Exemption)
Clouisle applies one shared SSRF check to custom HTTP tools, workflow HTTP request nodes, knowledge base URL imports, and database tool connection tests: the host is resolved to IPs first, and any resolved IP falling into the private (is_private) / loopback (is_loopback) / link-local (is_link_local) / reserved (is_reserved) / multicast (is_multicast) / unspecified (is_unspecified) categories is rejected. Typical members: 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.169.254, fe80::/10, 0.0.0.0, ::, and the hostnames localhost, local, metadata.google.internal.
To call internal APIs, microservices, or intranet databases, add the approved targets one per line under Settings → Security → Outbound Network Allowlist (SSRF Exemption) (setting key ssrf_allowed_targets, a JSON array):
| Form | Example | Matching rule |
|---|---|---|
| Single IP | 192.168.1.50 | Exact address match |
| CIDR subnet | 10.10.0.0/16 | Any resolved IP inside the subnet is allowed |
| Exact domain | api.internal.service | Must contain .; case-insensitive |
| Wildcard domain | *.corp.internal | Matches every subdomain and the base domain itself |
Targets that can never be allowlisted
Rejected at save time: *, 0.0.0.0, ::, 169.254.169.254, metadata.google.internal, and any CIDR overlapping cloud metadata (169.254.0.0/16), multicast (224.0.0.0/4), or unspecified (0.0.0.0/32) ranges (including 0.0.0.0/0 and ::/0). Invalid entries raise an error instead of being silently dropped.
Other constraints and behaviour:
- The allowlist holds at most 200 entries; duplicates are de-duplicated. Hostnames without a
.(such aslocalhost) cannot be an entry — use an IP or CIDR instead. - An empty allowlist blocks every internal target — that is the default posture. The wider you open it, the easier tools and workflows become an intranet-probing pivot.
- Validation re-reads the setting and resolves the host on every request, so changes take effect immediately with no restart.
- The Fake-IP benchmark pool
198.18.0.0/15(Clash/Surge/Mihomo TUN mode) is automatically allowed so public domains are not falsely flagged as SSRF.
Notification Settings
SMTP (Email)
Configure email sending:
| Field | Type | Default | Description |
|---|---|---|---|
smtp_enabled | boolean | false | Enable SMTP |
smtp_host | string | empty | SMTP host |
smtp_port | number | 587 | SMTP port |
smtp_encryption | none, ssl, or tls | tls | Encryption method |
smtp_username | string | empty | SMTP username |
smtp_password | string | empty | SMTP password |
email_from_name | string | Clouisle | Sender name |
email_from_address | string | empty | Sender address |
Update SMTP settings: Navigate to Settings → Notifications, enter SMTP details, set sender name and address, click Test (POST /api/v1/admin/site-settings/test-email), then click Save Changes.
smtp_enabled defaults to false and smtp_host to empty — out of the box, email is unconfigured. Until you enable it and fill in host, port, encryption, credentials, and sender address, email notifications silently stay in-app only: nothing errors and nothing is replayed later. Click Test to confirm delivery before saving.
External Notification Channels
The following channels can be enabled and configured (each with its own settings page section and a test endpoint):
| Channel | Key Settings | Test Endpoint |
|---|---|---|
| DingTalk | dingtalk_enabled, type (webhook or app), webhook URL/secret or app key/secret/agent ID | /test-dingtalk |
| WeChat Work | wechat_enabled, wechat_notification_type (webhook or app), webhook URL, or corp ID (wechat_corp_id) / agent ID (wechat_agent_id) / app secret (wechat_secret) | /test-wechat |
| Feishu | feishu_enabled, type (webhook or app), webhook URL/secret or app ID/secret | /test-feishu |
| Slack | slack_enabled, incoming webhook URL | /test-slack |
| Webhook | webhook_enabled, URL, method, custom headers, body template, HMAC secret | /test-webhook |
Auto Notifications
The Auto Notifications tab (GET/PUT /api/v1/admin/site-settings/auto-notifications) controls which event types create notifications and which external channels receive them. See Notifications & External Channels for details.
Email Templates
app/core/i18n.py).Notification Preferences
Notification delivery in Clouisle is configured globally by administrators — there is no per-user notification preference system. Individual users cannot customize which notifications they receive.
Note: Per-user preferences (email frequency/digests, per-type toggles, quiet hours / do-not-disturb, push notifications, notification grouping, priority levels, custom rules, and user webhook endpoints) are not implemented.
In-App Notifications
Every user sees their notifications in the notification center and at /app/notifications. Notifications are scoped as:
- global: visible to all users
- team: visible to members of the target team
- user: visible to a specific user
External Channels (Admin-Configured)
Administrators configure external delivery channels globally for automatic notification types. Available channels:
- Email (requires SMTP configuration)
- DingTalk
- Feishu
- Webhook (generic webhook)
- Slack
A channel only sends notifications when it is both selected in the global config and enabled/configured by the administrator. If no channels are configured, notifications stay in-app only.
What Administrators Can Configure
Administrators choose which automatic event types are enabled (enabled_types). By default the following types are enabled:
| Type | Event |
|---|---|
team.member_added / team.member_removed | Team membership changes |
team.role_changed / team.ownership_transferred | Role / ownership changes |
team.model_granted / team.model_revoked | Team model access changes |
user.activated / user.deactivated | Account status changes |
user.password_reset | Administrator resets a password |
user.pending_approval | New registration awaiting approval |
kb.doc_indexed / kb.doc_failed | Knowledge base document processing |
workflow.run_failed | Workflow execution failures |
workflow.pause_pending | A workflow paused and is waiting for human approval |
apikey.expiring / apikey.expired | API key lifecycle |
security.login_anomaly | Login from a new location/device |
security.account_locked | Account locked after failed attempts |
security.password_changed | Password changed |
Additional types (e.g. workflow.run_success, agent.published, agent.unpublished, password.expiring) exist and can be enabled.
Admins configure this under Admin Dashboard → Site Settings → Notifications → Auto Notifications (and the corresponding channel tabs: Email, DingTalk, WeChat, Feishu, Webhook, Slack).
What Users Can Do
As a user you can:
- View notifications in the notification center and at
/app/notifications - Mark individual notifications as read
- Mark all notifications as read
- Filter the notification list (by type, level, scope, unread, and search)
See Notifications & External Channels for details.
Notification API
GET /api/v1/notifications— list visible notifications (filters: scope, type, level, unread, search)GET /api/v1/notifications/unread-count— unread countPOST /api/v1/notifications/read— mark notifications read (notification_idsormark_all)- Admin endpoints (
/api/v1/admin/notifications) — create/delete notifications, manage auto-notification config
PATCH /api/v1/notifications/{id} and no user-level DELETE /api/v1/notifications/{id} — reading is a bulk action and deletion is admin-only.Best Practices
For users:
- Check the notification center regularly
- Review security notifications immediately
For administrators:
- Enable external channels only after configuring them (SMTP, DingTalk, etc.)
- Choose enabled types deliberately to avoid notification noise
Background Memory Extraction Settings
Memory (/site-settings/memory) queues extraction for pending user turns after the configured cooldown, or immediately when the pending-turn threshold is reached. The Agent must also have memory enabled; disabling either the Agent memory feature or the global switch prevents extraction tasks.
| Field | Type | Default | Constraints and behavior |
|---|---|---|---|
memory_async_extraction_enabled | boolean | false | Enable background extraction |
memory_extraction_model_id | string | "" | Empty uses the fallback model chain; unavailable or disabled models also fall back |
memory_extraction_cooldown_seconds | integer | 180 | 10-3600, debounce window |
memory_extraction_max_pending_turns | integer | 6 | 1-50, trigger immediately at this pending-turn count |
The extraction model falls back in this order: explicitly configured enabled model, the Agent's assigned model, the system default chat model, then the first available chat model. The cooldown debounces extraction; reaching the pending-turn threshold queues it immediately.
Storage Settings
File Storage
Configure storage backend and knowledge base upload size limits:
| Field | Type | Default | Description |
|---|---|---|---|
upload_storage_backend | local or object | local | Upload storage backend |
kb_document_max_upload_size_mb | number (1-1024) | 50 | KB single file upload size limit (MB) |
Update storage settings: Navigate to Settings → Storage, configure storage backend and max upload size, then click Save Changes.
Object Storage (S3-compatible)
Configure S3-compatible object storage:
| Field | Type | Default | Description |
|---|---|---|---|
upload_storage_backend | object | - | Upload storage backend set to object storage |
object_storage_endpoint | string | empty | Object storage endpoint |
object_storage_bucket | string | empty | Bucket name |
object_storage_region | string | empty | Region |
object_storage_access_key | string | empty | Access Key |
object_storage_secret_key | string | empty | Secret Key |
object_storage_force_path_style | boolean | true | Use path-style URLs |
object_storage_secure | boolean | true | Use HTTPS |
Configure object storage: Navigate to Settings → Storage, enter the endpoint, bucket, region, access key, and secret key, configure path-style and HTTPS options, then click Save Changes.
Audit Log Retention
| Field | Type | Default | Description |
|---|---|---|---|
audit_log_retention_days | number (30-3650) | 365 | Audit log retention days |
audit_log_archive_path | string | /var/log/clouisle/audit_archives | Local path archive JSON files are written to |
Logs older than the retention period are archived (manually triggered) to monthly JSON files under the archive path and then deleted. See Audit Log Management for details.
Audit Alerts (Not Wired Up)
The following five keys are seeded into the database at initialization, but no code reads them — there is no detection task and no delivery path, so configuring them produces no alerts:
| Field | Type | Default | Description |
|---|---|---|---|
audit_alert_enabled | boolean | true | Suspected leftover alert master switch |
audit_alert_webhook | string | empty | Suspected leftover alert webhook URL |
audit_alert_failed_login_threshold | number | 5 | Suspected leftover failed-login threshold |
audit_alert_failed_login_window | number | 5 | Suspected leftover detection window (minutes) |
audit_alert_bulk_deletion_threshold | number | 10 | Suspected leftover bulk-deletion threshold |
For real security alerting, use the implemented path: the security.* events and external channels of Auto Notifications.
SSO Settings
Global SSO Behavior
Configured in Settings → Security (SSO section) or Settings → SSO:
| Field | Type | Default | Description |
|---|---|---|---|
sso_enabled | boolean | false | Enable SSO |
sso_allow_password_login | boolean | true | Allow password login |
sso_auto_create_users | boolean | true | Auto-create users |
sso_require_approval | boolean | false | Require approval |
sso_match_by_email | boolean | true | Match by email |
SSO Providers
SSO providers are managed in Settings → SSO. Providers are created generically with a name and protocol — there is no preset picker (Google, GitHub, Azure AD, etc.); each provider's configuration and attribute mapping are entered manually. See SSO Configuration for the full guide.
Team Settings
Teams group users and resources (agents, workflows, and knowledge bases). Team admins manage members and basic team information; model authorization can only be changed by a superuser.
Note: Team slugs, visibility, invitation flows, join requests, member limits, per-team resource limits, per-team security/API settings, billing, data retention, custom domains, and branding are not implemented.
Accessing Team Management
There are two entry points with completely different permissions and capabilities:
| Entry point | Path | Required permission | Capabilities |
|---|---|---|---|
| Admin team management | /teams | admin:team:read (or superuser) | Cross-team view/create/edit; model authorization is superuser-only |
| Team settings (team-scoped) | /app/team | Team membership plus team:manage / team:update (team admin or owner) | The current team's members, basic info, and a read-only model tab |
Open them from the Team switcher: Manage All Teams (Admin) goes to /teams (shown only with admin:team:read) and Manage Current Team goes to /app/team (shown only with team:manage).
Members and Viewers do not have admin:team:read, so they never see the /teams entry; inside the team switcher they only get Manage current team (and that still requires team:manage). When someone asks "why can't I see team management", check this permission before suspecting a frontend bug.
Team Information
Only three fields can be edited:
| Field | Description |
|---|---|
| Name | Team display name (required) |
| Description | Optional description (max 500 chars) |
| Avatar URL | Optional avatar image URL |
Note: There is no team slug — teams are identified by ID and referenced by name in the UI.
Model Authorization
Team model authorization can only be performed by a superuser. On /app/team → Model Authorization, a team admin or owner sees a read-only view: authorized models, enable state, and a "today's usage / limit" bar (limits are assigned by the system administrator; no limit means uncapped). Changing authorizations requires the team detail under /teams, which itself requires admin:team:read.
| Operation | Endpoint | Permission |
|---|---|---|
| List a team's authorized models | GET /api/v1/teams/{team_id}/models | Team member or superuser |
| Authorize a model | POST /api/v1/teams/{team_id}/models | Superuser only |
| Change quota/priority/enable state | PUT /api/v1/teams/{team_id}/models/{model_id} | Superuser only |
| Revoke an authorization | DELETE /api/v1/teams/{team_id}/models/{model_id} | Superuser only |
| Batch authorize/revoke | POST / DELETE /api/v1/teams/{team_id}/models/batch | Superuser only |
| List authorizable models | GET /api/v1/teams/{team_id}/available-models | Superuser only |
Only authorized models appear in the team's Agent and knowledge base model pickers.
Telling team admins to "go authorize the model themselves" is a common process mistake: the UI offers no such control and a superuser must do it. It also means model quotas are centrally governed — teams cannot raise their own limits.
Member Management
Members must already have Clouisle accounts; there is no email-invitation or join-request flow.
Adding Members
- Open Manage Teams (
/teams) and select a team. - Open the Members tab.
- Click Add Member.
- Choose an existing user and a role (Admin, Member, or Viewer — Owner cannot be assigned here).
- Confirm.
Only the team Owner or Admin can add members. The Owner cannot add another member as Owner.
Changing Member Roles
- Find the member in the member list
- Choose "Change Role"
- Select the new role (Admin, Member, or Viewer)
Only the team Owner can change member roles (except for the Owner themselves).
Removing Members
- Find the member in the member list
- Click "Remove"
- Confirm
The Owner cannot be removed by other members.
Leaving a Team
- Open Manage Teams (
/teams) and select the team. - Open Members.
- Confirm
The Owner cannot leave until ownership is transferred.
Transferring Ownership
- Open Manage Teams (
/teams) and select the team. - Open Members.
- Confirm the transfer
The previous owner becomes an Admin, and the new owner gains full control.
Team Roles
Roles are fixed: Owner, Admin, Member, Viewer. There are no per-team custom roles. See Teams & Members for the full permission matrix.
What Does NOT Exist
The following team-level features are not implemented:
- Team slug / custom URL
- Team visibility (private/internal/public) and discovery
- Invitation expiry, require-approval, allowed email domains
- Member limits
- Resource limits (agents, KBs, workflows, conversations)
- Per-team password/2FA/session/IP policies
- Team API settings, API key policies, rate limits
- Billing / subscriptions / payment methods
- Data retention / export / deletion policies
- Audit alerts, custom domain, branding
See also:
- Teams & Members — Detailed team management guide
- Roles & Permissions — Roles and permissions
Rollout Settings (Private)
These keys live in the retrieval category with public=false: they are absent from the site-settings UI and from the public settings API, and exist for operators to control the staged rollout of hybrid retrieval:
| Field | Type | Default | Description |
|---|---|---|---|
retrieval_hybrid_mode | rollout, enabled, or disabled | rollout | Hybrid retrieval master switch |
retrieval_hybrid_team_ids | JSON array | [] | Explicit team-ID allowlist included in the rollout |
retrieval_hybrid_percentage | number | 100 | Deterministic rollout percentage (0-100, bucketed by hash of the team set) |
Precedence: the environment variable RETRIEVAL_HYBRID_KILL_SWITCH=true wins over everything and disables hybrid retrieval; disabled turns it off globally; enabled turns it on globally; under rollout, a team matching the allowlist is enabled, otherwise the hash bucket < percentage decides.
Under rollout, retrieval_hybrid_percentage is a deterministic hash of the team set (the same set of teams always lands in the same bucket), not random sampling — so changing the percentage changes which teams are included rather than flipping individual requests. Switching the mode to disabled reverts retrieval to a single mode globally and directly affects recall quality.
Feature Flags and Other Settings
- Feature flags (enabling/disabling agents, workflows, KBs, etc.)
- Email templates
- Security headers (HSTS, CSP, X-Frame-Options)
- CORS configuration
- IP whitelisting
- API rate limiting
- Webhook configuration as a general system feature
- Third-party integrations (Salesforce, HubSpot, Slack apps, analytics like Google Analytics/Mixpanel)
- Maintenance mode
- Database pool / cache settings
- Settings export/import and reset-to-defaults workflows
Model endpoints are restricted via the Model Endpoint Allowlist (Security) instead of a global integration registry.
Key Defaults
Default public settings for a new site: site name Clouisle, centered authentication pages, theme follows system, icon and name displayed, registration allowed, email verification on, CAPTCHA off, SSO off, password login allowed, and knowledge base single-file upload 50MB.
When Changes Take Effect
Page settings usually affect the public site and subsequent requests immediately after saving; model endpoints, storage, and deployment environment variables are read by the server, so restart the relevant services according to your deployment after changing them. After saving, verify the login and sign-up pages in an incognito window.
Security Principles
- Store
SECRET_KEY, SMTP passwords, SSO client secrets, object storage keys, and model API Keys only as server-side secrets. - The allowlist matches against full Origins; an empty allowlist blocks model endpoints.
- Before enabling SSO-only, confirm at least one connection works and keep an administrator recovery path.
- Before changing the audit log retention days, confirm the archive path and backup policy.
See the Site settings reference for the field-level checklist.
How is this guide?