Files
Li-Day-Day 58c19856fd
Release / Prepare Scheduled Release (push) Has been skipped
Release / Publish Release (push) Failing after 0s
feat:Improve Lite gateway scheduling, proxy stability, and Hermes recovery (#160)
* feat(runtime): improve Lite gateway scheduling and proxy stability

- Expand the runtime gateway port range to match 100 instances per pod
- Scale runtime deployments based on pending backlog
- Serialize gateway creation per pod and handle starting/creating states
- Clean up missing gateway bindings from runtime agent reports
- Improve Lite gateway proxy token stripping and auth header injection
- Update deployment manifests, docs, and related tests

* fix(runtime): harden Hermes Lite gateway recovery

- Add hashed gateway token aliases for short-term token compatibility
- Fix /resume conversations failing when old sessions use mismatched gateway tokens
- Recover ports only from stale error bindings without affecting active gateways

* feat(runtime): enable bidirectional desktop clipboard and direct proxy

- Enable WebTop/Selkies/Kasm clipboard by default with per-instance overrides
- Document clipboard verification, configuration pitfalls, and IME troubleshooting
- Enable direct desktop proxy in the K8s and K3s manifests

---------

Co-authored-by: litiantian03 <litiantian03@ieisystem.com>
2026-07-13 14:37:03 +08:00

1657 lines
56 KiB
YAML

# ClawManager single-node install profile.
# Official validation target: HostPath on one labeled storage node.
# Before installing, label exactly one node:
# kubectl label node <node> clawmanager.io/storage-node=true --overwrite
# Replace paths or StorageClass names only if you understand the single-node constraints.
apiVersion: v1
kind: Namespace
metadata:
name: clawmanager-system
---
apiVersion: v1
kind: Secret
metadata:
name: clawmanager-secrets
namespace: clawmanager-system
type: Opaque
stringData:
mysql-root-password: root123
mysql-password: clawreef123
jwt-secret: change-me-in-production
runtime-agent-control-token: change-me-runtime-control-token
runtime-agent-report-token: change-me-runtime-report-token
openclaw-gateway-token: change-me-openclaw-gateway-token
minio-root-user: minioadmin
minio-root-password: minioadmin123
minio-access-key: minioadmin
minio-secret-key: minioadmin123
---
apiVersion: v1
kind: ConfigMap
metadata:
name: clawmanager-mysql-init
namespace: clawmanager-system
data:
001_init_schema.sql: |
CREATE DATABASE IF NOT EXISTS clawmanager CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE clawmanager;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(320) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role ENUM('admin', 'user') DEFAULT 'user',
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_login TIMESTAMP,
INDEX idx_username (username),
INDEX idx_role (role)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instances (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
type ENUM('openclaw', 'ubuntu', 'debian', 'centos', 'custom', 'webtop', 'hermes') DEFAULT 'ubuntu',
runtime_type ENUM('desktop', 'shell') NOT NULL DEFAULT 'desktop',
status ENUM('creating', 'running', 'stopped', 'error', 'deleting') DEFAULT 'creating',
cpu_cores DECIMAL(10,2) NOT NULL,
memory_gb INT NOT NULL,
disk_gb INT NOT NULL,
gpu_enabled BOOLEAN DEFAULT FALSE,
gpu_type VARCHAR(100),
gpu_count INT DEFAULT 0,
os_type VARCHAR(50) NOT NULL,
os_version VARCHAR(50) NOT NULL,
image_registry VARCHAR(255),
image_tag VARCHAR(100),
storage_class VARCHAR(50) DEFAULT 'standard',
mount_path VARCHAR(255) DEFAULT '/data',
pod_name VARCHAR(255),
pod_namespace VARCHAR(255),
pod_ip VARCHAR(45),
access_url VARCHAR(500),
access_token VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
started_at TIMESTAMP,
stopped_at TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_user_id (user_id),
INDEX idx_status (status),
INDEX idx_type (type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS persistent_volumes (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
pvc_name VARCHAR(255) UNIQUE NOT NULL,
pvc_namespace VARCHAR(255) NOT NULL,
storage_size_gb INT NOT NULL,
storage_class VARCHAR(50),
mount_path VARCHAR(255),
status ENUM('pending', 'bound', 'released', 'failed') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
INDEX idx_instance_id (instance_id),
UNIQUE KEY uk_pvc_name_namespace (pvc_name, pvc_namespace)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS backups (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
backup_name VARCHAR(255) NOT NULL,
backup_size_gb INT,
backup_path VARCHAR(500),
status ENUM('creating', 'completed', 'failed', 'deleted') DEFAULT 'creating',
backup_type ENUM('manual', 'scheduled') DEFAULT 'manual',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP,
expires_at TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
INDEX idx_instance_id (instance_id),
INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS backup_schedules (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
schedule_name VARCHAR(255),
cron_expression VARCHAR(100) NOT NULL,
retention_days INT DEFAULT 30,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
INDEX idx_instance_id (instance_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS user_quotas (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL UNIQUE,
max_instances INT DEFAULT 10,
max_cpu_cores DECIMAL(10,2) DEFAULT 40,
max_memory_gb INT DEFAULT 100,
max_storage_gb INT DEFAULT 500,
max_gpu_count INT DEFAULT 2,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instance_usage (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
cpu_usage_percent DECIMAL(5,2),
memory_usage_gb DECIMAL(10,2),
disk_usage_gb DECIMAL(10,2),
gpu_usage_percent DECIMAL(5,2),
uptime_seconds INT,
recorded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
INDEX idx_instance_recorded (instance_id, recorded_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS audit_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
action VARCHAR(100) NOT NULL,
resource_type VARCHAR(50) NOT NULL,
resource_id INT,
details JSON,
ip_address VARCHAR(45),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
INDEX idx_user_id (user_id),
INDEX idx_action (action),
INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO users (username, email, password_hash, role, is_active)
SELECT 'admin', 'admin@clawmanager.local', '$2a$10$pbenze514mwv3pvQySQBVOsF5J4DBXL2kVo1hLa8JFhQu5x3AKvBi', 'admin', TRUE
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = 'admin');
INSERT INTO user_quotas (user_id, max_instances, max_cpu_cores, max_memory_gb, max_storage_gb, max_gpu_count)
SELECT id, 100, 200, 1000, 5000, 10 FROM users
WHERE username = 'admin'
AND NOT EXISTS (SELECT 1 FROM user_quotas WHERE user_id = users.id);
002_add_webtop_instance_type.sql: |
USE clawmanager;
ALTER TABLE instances
MODIFY COLUMN type ENUM('openclaw', 'ubuntu', 'debian', 'centos', 'custom', 'webtop', 'hermes') DEFAULT 'ubuntu';
003_add_system_image_settings.sql: |
USE clawmanager;
CREATE TABLE IF NOT EXISTS system_image_settings (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_type VARCHAR(50) NOT NULL,
runtime_type ENUM('desktop', 'shell') NOT NULL DEFAULT 'desktop',
display_name VARCHAR(255) NOT NULL,
image VARCHAR(500) NOT NULL,
is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_instance_type (instance_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
004_fix_seeded_admin_password.sql: |
USE clawmanager;
UPDATE users
SET password_hash = '$2a$10$pbenze514mwv3pvQySQBVOsF5J4DBXL2kVo1hLa8JFhQu5x3AKvBi'
WHERE username = 'admin'
AND password_hash = '$2a$10$N9qo8uLOickgx2ZMRZoMy.MqrzL9wGC3qD3Q.ZHqQH6t3q7l1L5uG';
005_update_openclaw_default_image.sql: |
USE clawmanager;
UPDATE system_image_settings
SET image = 'ghcr.io/yuan-lab-llm/agentsruntime/openclaw:latest'
WHERE instance_type = 'openclaw'
AND image IN (
'ericpearlee/openclaw:v2026.3.24',
'ghcr.io/yuan-lab-llm/clawmanager-openclaw-image/openclaw:latest'
);
006_add_openclaw_config_center.sql: |
USE clawmanager;
SET @openclaw_snapshot_column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'instances'
AND COLUMN_NAME = 'openclaw_config_snapshot_id'
);
SET @openclaw_snapshot_column_sql = IF(
@openclaw_snapshot_column_exists = 0,
'ALTER TABLE instances ADD COLUMN openclaw_config_snapshot_id INT NULL AFTER access_token',
'SELECT 1'
);
PREPARE openclaw_snapshot_column_stmt FROM @openclaw_snapshot_column_sql;
EXECUTE openclaw_snapshot_column_stmt;
DEALLOCATE PREPARE openclaw_snapshot_column_stmt;
CREATE TABLE IF NOT EXISTS openclaw_config_resources (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
resource_type VARCHAR(50) NOT NULL,
resource_key VARCHAR(100) NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
version INT NOT NULL DEFAULT 1,
tags_json LONGTEXT NOT NULL,
content_json LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE KEY uk_openclaw_resource_key (user_id, resource_type, resource_key),
INDEX idx_openclaw_resource_user_type (user_id, resource_type),
INDEX idx_openclaw_resource_user_enabled (user_id, enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS openclaw_config_bundles (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
version INT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_openclaw_bundle_user (user_id),
INDEX idx_openclaw_bundle_user_enabled (user_id, enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS openclaw_config_bundle_items (
id INT AUTO_INCREMENT PRIMARY KEY,
bundle_id INT NOT NULL,
resource_id INT NOT NULL,
sort_order INT NOT NULL DEFAULT 0,
required BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bundle_id) REFERENCES openclaw_config_bundles(id) ON DELETE CASCADE,
FOREIGN KEY (resource_id) REFERENCES openclaw_config_resources(id) ON DELETE CASCADE,
UNIQUE KEY uk_openclaw_bundle_resource (bundle_id, resource_id),
INDEX idx_openclaw_bundle_item_bundle (bundle_id, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS openclaw_injection_snapshots (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NULL,
user_id INT NOT NULL,
mode VARCHAR(20) NOT NULL,
bundle_id INT NULL,
selected_resource_ids_json LONGTEXT NOT NULL,
resolved_resources_json LONGTEXT NOT NULL,
rendered_manifest_json LONGTEXT NOT NULL,
rendered_env_json LONGTEXT NOT NULL,
secret_name VARCHAR(255) NULL,
status VARCHAR(30) NOT NULL DEFAULT 'pending',
error_message TEXT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
activated_at TIMESTAMP NULL,
INDEX idx_openclaw_snapshot_user_created (user_id, created_at),
INDEX idx_openclaw_snapshot_instance (instance_id),
INDEX idx_openclaw_snapshot_bundle (bundle_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
007_add_instance_agent_control_plane.sql: |
USE clawmanager;
SET @instance_agent_bootstrap_token_column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'instances'
AND COLUMN_NAME = 'agent_bootstrap_token'
);
SET @instance_agent_bootstrap_token_column_sql = IF(
@instance_agent_bootstrap_token_column_exists = 0,
'ALTER TABLE instances ADD COLUMN agent_bootstrap_token VARCHAR(255) NULL AFTER access_token',
'SELECT 1'
);
PREPARE instance_agent_bootstrap_token_column_stmt FROM @instance_agent_bootstrap_token_column_sql;
EXECUTE instance_agent_bootstrap_token_column_stmt;
DEALLOCATE PREPARE instance_agent_bootstrap_token_column_stmt;
CREATE TABLE IF NOT EXISTS instance_agents (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
agent_id VARCHAR(255) NOT NULL,
agent_version VARCHAR(50) NOT NULL,
protocol_version VARCHAR(50) NOT NULL,
status VARCHAR(30) NOT NULL DEFAULT 'online',
capabilities_json LONGTEXT NOT NULL,
host_info_json LONGTEXT NULL,
session_token VARCHAR(255) NULL,
session_expires_at TIMESTAMP NULL,
last_heartbeat_at TIMESTAMP NULL,
last_reported_at TIMESTAMP NULL,
last_seen_ip VARCHAR(45) NULL,
registered_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
UNIQUE KEY uk_instance_agents_instance (instance_id),
UNIQUE KEY uk_instance_agents_session_token (session_token),
INDEX idx_instance_agents_agent_id (agent_id),
INDEX idx_instance_agents_status (status),
INDEX idx_instance_agents_last_heartbeat (last_heartbeat_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instance_runtime_status (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
infra_status VARCHAR(30) NOT NULL DEFAULT 'creating',
agent_status VARCHAR(30) NOT NULL DEFAULT 'offline',
openclaw_status VARCHAR(30) NOT NULL DEFAULT 'unknown',
openclaw_pid INT NULL,
openclaw_version VARCHAR(100) NULL,
current_config_revision_id INT NULL,
desired_config_revision_id INT NULL,
summary_json LONGTEXT NULL,
system_info_json LONGTEXT NULL,
health_json LONGTEXT NULL,
last_reported_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
UNIQUE KEY uk_instance_runtime_status_instance (instance_id),
INDEX idx_instance_runtime_status_agent_status (agent_status),
INDEX idx_instance_runtime_status_openclaw_status (openclaw_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instance_desired_state (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
desired_power_state VARCHAR(30) NOT NULL DEFAULT 'running',
desired_config_revision_id INT NULL,
desired_runtime_action VARCHAR(50) NULL,
updated_by INT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL,
UNIQUE KEY uk_instance_desired_state_instance (instance_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instance_commands (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
agent_id VARCHAR(255) NULL,
command_type VARCHAR(50) NOT NULL,
payload_json LONGTEXT NULL,
status VARCHAR(30) NOT NULL DEFAULT 'pending',
idempotency_key VARCHAR(255) NOT NULL,
issued_by INT NULL,
issued_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
dispatched_at TIMESTAMP NULL,
started_at TIMESTAMP NULL,
finished_at TIMESTAMP NULL,
timeout_seconds INT NOT NULL DEFAULT 300,
result_json LONGTEXT NULL,
error_message TEXT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
FOREIGN KEY (issued_by) REFERENCES users(id) ON DELETE SET NULL,
UNIQUE KEY uk_instance_commands_idempotency (instance_id, idempotency_key),
INDEX idx_instance_commands_instance_status (instance_id, status),
INDEX idx_instance_commands_agent_status (agent_id, status),
INDEX idx_instance_commands_issued_at (issued_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instance_config_revisions (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
source_snapshot_id INT NULL,
source_bundle_id INT NULL,
revision_no INT NOT NULL,
content_json LONGTEXT NOT NULL,
checksum VARCHAR(255) NOT NULL,
status VARCHAR(30) NOT NULL DEFAULT 'published',
published_by INT NULL,
published_at TIMESTAMP NULL,
activated_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
FOREIGN KEY (published_by) REFERENCES users(id) ON DELETE SET NULL,
UNIQUE KEY uk_instance_config_revision_unique (instance_id, revision_no),
INDEX idx_instance_config_revision_instance (instance_id, revision_no),
INDEX idx_instance_config_revision_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
008_add_skill_management.sql: |
USE clawmanager;
CREATE TABLE IF NOT EXISTS skill_blobs (
id INT AUTO_INCREMENT PRIMARY KEY,
content_hash VARCHAR(128) NOT NULL,
archive_hash VARCHAR(128) NOT NULL,
object_key VARCHAR(512) NOT NULL,
file_name VARCHAR(255) NOT NULL,
media_type VARCHAR(100) NOT NULL DEFAULT 'application/gzip',
size_bytes BIGINT NOT NULL DEFAULT 0,
scan_status VARCHAR(30) NOT NULL DEFAULT 'pending',
risk_level VARCHAR(30) NOT NULL DEFAULT 'unknown',
last_scanned_at TIMESTAMP NULL,
last_scan_result_id INT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_skill_blobs_content_hash (content_hash),
INDEX idx_skill_blobs_scan_status (scan_status),
INDEX idx_skill_blobs_risk_level (risk_level)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS skills (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
skill_key VARCHAR(120) NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT NULL,
current_version_id INT NULL,
source_type VARCHAR(30) NOT NULL DEFAULT 'uploaded',
status VARCHAR(30) NOT NULL DEFAULT 'active',
risk_level VARCHAR(30) NOT NULL DEFAULT 'unknown',
last_scanned_at TIMESTAMP NULL,
last_scan_result_id INT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE KEY uk_skills_user_key (user_id, skill_key),
INDEX idx_skills_user_status (user_id, status),
INDEX idx_skills_risk_level (risk_level)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS skill_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
skill_id INT NOT NULL,
blob_id INT NOT NULL,
version_no INT NOT NULL,
manifest_json LONGTEXT NULL,
source_type VARCHAR(30) NOT NULL DEFAULT 'uploaded',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (skill_id) REFERENCES skills(id) ON DELETE CASCADE,
FOREIGN KEY (blob_id) REFERENCES skill_blobs(id) ON DELETE RESTRICT,
UNIQUE KEY uk_skill_versions_skill_version (skill_id, version_no),
UNIQUE KEY uk_skill_versions_skill_blob (skill_id, blob_id),
INDEX idx_skill_versions_skill_id (skill_id, version_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS instance_skills (
id INT AUTO_INCREMENT PRIMARY KEY,
instance_id INT NOT NULL,
skill_id INT NOT NULL,
skill_version_id INT NULL,
source_type VARCHAR(40) NOT NULL DEFAULT 'discovered_in_instance',
install_path VARCHAR(1024) NULL,
observed_hash VARCHAR(128) NULL,
status VARCHAR(30) NOT NULL DEFAULT 'active',
last_seen_at TIMESTAMP NULL,
removed_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
FOREIGN KEY (skill_id) REFERENCES skills(id) ON DELETE CASCADE,
FOREIGN KEY (skill_version_id) REFERENCES skill_versions(id) ON DELETE SET NULL,
UNIQUE KEY uk_instance_skills_instance_skill (instance_id, skill_id),
INDEX idx_instance_skills_instance (instance_id, status),
INDEX idx_instance_skills_skill (skill_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS skill_scan_results (
id INT AUTO_INCREMENT PRIMARY KEY,
blob_id INT NOT NULL,
engine VARCHAR(60) NOT NULL,
risk_level VARCHAR(30) NOT NULL DEFAULT 'unknown',
status VARCHAR(30) NOT NULL DEFAULT 'completed',
summary TEXT NULL,
findings_json LONGTEXT NULL,
scanned_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (blob_id) REFERENCES skill_blobs(id) ON DELETE CASCADE,
INDEX idx_skill_scan_results_blob (blob_id, scanned_at),
INDEX idx_skill_scan_results_risk (risk_level, scanned_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
009_cpu_cores_decimal.sql: |
USE clawmanager;
ALTER TABLE instances MODIFY COLUMN cpu_cores DECIMAL(10,2) NOT NULL;
ALTER TABLE user_quotas MODIFY COLUMN max_cpu_cores DECIMAL(10,2) DEFAULT 40;
011_add_hermes_instance_type.sql: |
USE clawmanager;
ALTER TABLE instances
MODIFY COLUMN type ENUM('openclaw', 'ubuntu', 'debian', 'centos', 'custom', 'webtop', 'hermes') DEFAULT 'ubuntu';
012_update_agents_runtime_default_images.sql: |
USE clawmanager;
UPDATE system_image_settings
SET image = 'ghcr.io/yuan-lab-llm/agentsruntime/openclaw:latest'
WHERE instance_type = 'openclaw'
AND image IN (
'ericpearlee/openclaw:v2026.3.24',
'ghcr.io/yuan-lab-llm/clawmanager-openclaw-image/openclaw:latest'
);
UPDATE system_image_settings
SET image = 'ghcr.io/yuan-lab-llm/agentsruntime/hermes:latest'
WHERE instance_type = 'hermes'
AND image IN (
'registry.example.com/hermes-webtop:latest',
'lscr.io/linuxserver/webtop:ubuntu-xfce'
);
013_normalize_agents_runtime_image_names.sql: |
USE clawmanager;
UPDATE system_image_settings
SET image = 'ghcr.io/yuan-lab-llm/agentsruntime/openclaw:latest'
WHERE image = 'ghcr.io/Yuan-lab-LLM/AgentsRuntime/openclaw:latest';
UPDATE system_image_settings
SET image = 'ghcr.io/yuan-lab-llm/agentsruntime/hermes:latest'
WHERE image = 'ghcr.io/Yuan-lab-LLM/AgentsRuntime/hermes:latest';
019_add_instance_runtime_type.sql: |
USE clawmanager;
SET @instance_runtime_type_column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'instances'
AND COLUMN_NAME = 'runtime_type'
);
SET @instance_runtime_type_column_sql = IF(
@instance_runtime_type_column_exists = 0,
'ALTER TABLE instances ADD COLUMN runtime_type ENUM(''desktop'', ''shell'') NOT NULL DEFAULT ''desktop'' AFTER type',
'SELECT 1'
);
PREPARE instance_runtime_type_column_stmt FROM @instance_runtime_type_column_sql;
EXECUTE instance_runtime_type_column_stmt;
DEALLOCATE PREPARE instance_runtime_type_column_stmt;
020_add_system_image_runtime_type.sql: |
USE clawmanager;
SET @system_image_runtime_type_column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'system_image_settings'
AND COLUMN_NAME = 'runtime_type'
);
SET @system_image_runtime_type_column_sql = IF(
@system_image_runtime_type_column_exists = 0,
'ALTER TABLE system_image_settings ADD COLUMN runtime_type ENUM(''desktop'', ''shell'') NOT NULL DEFAULT ''desktop'' AFTER instance_type',
'SELECT 1'
);
PREPARE system_image_runtime_type_column_stmt FROM @system_image_runtime_type_column_sql;
EXECUTE system_image_runtime_type_column_stmt;
DEALLOCATE PREPARE system_image_runtime_type_column_stmt;
021_add_openclaw_shell_runtime_image.sql: |
USE clawmanager;
SET @system_image_is_enabled_column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'system_image_settings'
AND COLUMN_NAME = 'is_enabled'
);
SET @system_image_is_enabled_column_sql = IF(
@system_image_is_enabled_column_exists = 0,
'ALTER TABLE system_image_settings ADD COLUMN is_enabled BOOLEAN NOT NULL DEFAULT TRUE',
'SELECT 1'
);
PREPARE system_image_is_enabled_column_stmt FROM @system_image_is_enabled_column_sql;
EXECUTE system_image_is_enabled_column_stmt;
DEALLOCATE PREPARE system_image_is_enabled_column_stmt;
SET @system_image_unique_instance_type_index_name = (
SELECT INDEX_NAME
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'system_image_settings'
AND COLUMN_NAME = 'instance_type'
AND NON_UNIQUE = 0
AND INDEX_NAME <> 'PRIMARY'
LIMIT 1
);
SET @system_image_unique_instance_type_index_sql = IF(
@system_image_unique_instance_type_index_name IS NOT NULL,
CONCAT(
'ALTER TABLE system_image_settings DROP INDEX `',
REPLACE(@system_image_unique_instance_type_index_name, '`', '``'),
'`'
),
'SELECT 1'
);
PREPARE system_image_unique_instance_type_index_stmt FROM @system_image_unique_instance_type_index_sql;
EXECUTE system_image_unique_instance_type_index_stmt;
DEALLOCATE PREPARE system_image_unique_instance_type_index_stmt;
INSERT INTO system_image_settings (instance_type, runtime_type, display_name, image, is_enabled)
SELECT
'openclaw',
'desktop',
'OpenClaw Desktop',
'ghcr.io/yuan-lab-llm/agentsruntime/openclaw:latest',
TRUE
WHERE NOT EXISTS (
SELECT 1
FROM system_image_settings
WHERE instance_type = 'openclaw'
AND runtime_type = 'desktop'
)
AND NOT EXISTS (
SELECT 1
FROM system_image_settings
WHERE instance_type = 'openclaw'
AND is_enabled = FALSE
);
INSERT INTO system_image_settings (instance_type, runtime_type, display_name, image, is_enabled)
SELECT
'openclaw',
'shell',
'OpenClaw Lite',
'ghcr.io/yuan-lab-llm/agentsruntime/openclaw-lite:latest',
TRUE
WHERE NOT EXISTS (
SELECT 1
FROM system_image_settings
WHERE instance_type = 'openclaw'
AND runtime_type = 'shell'
)
AND NOT EXISTS (
SELECT 1
FROM system_image_settings
WHERE instance_type = 'openclaw'
AND is_enabled = FALSE
);
022_add_openclaw_config_bundle_skills.sql: |
USE clawmanager;
CREATE TABLE IF NOT EXISTS openclaw_config_bundle_skills (
id INT AUTO_INCREMENT PRIMARY KEY,
bundle_id INT NOT NULL,
skill_id INT NOT NULL,
sort_order INT NOT NULL DEFAULT 0,
required BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bundle_id) REFERENCES openclaw_config_bundles(id) ON DELETE CASCADE,
FOREIGN KEY (skill_id) REFERENCES skills(id) ON DELETE CASCADE,
UNIQUE KEY uk_openclaw_bundle_skill (bundle_id, skill_id),
INDEX idx_openclaw_bundle_skill_bundle (bundle_id, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
023_normalize_runtime_config_mounts.sql: |
USE clawmanager;
UPDATE instances
SET mount_path = '/config',
updated_at = CURRENT_TIMESTAMP
WHERE type IN ('openclaw', 'ubuntu', 'webtop', 'hermes')
AND mount_path IN ('/data', '/home/user/data', '/config/.hermes');
031_add_hermes_lite_runtime_image.sql: |
USE clawmanager;
UPDATE system_image_settings
SET
image = 'ghcr.io/yuan-lab-llm/agentsruntime/hermes-lite:latest',
display_name = 'Hermes Lite',
is_enabled = TRUE
WHERE instance_type = 'hermes'
AND runtime_type = 'shell'
AND image IN (
'ghcr.io/yuan-lab-llm/agentsruntime/hermes-shell:latest',
'registry.example.com/your-custom-shell-image:latest'
);
INSERT INTO system_image_settings (instance_type, runtime_type, display_name, image, is_enabled)
SELECT
'hermes',
'shell',
'Hermes Lite',
'ghcr.io/yuan-lab-llm/agentsruntime/hermes-lite:latest',
TRUE
WHERE NOT EXISTS (
SELECT 1
FROM system_image_settings
WHERE instance_type = 'hermes'
AND runtime_type = 'shell'
)
AND NOT EXISTS (
SELECT 1
FROM system_image_settings
WHERE instance_type = 'hermes'
AND is_enabled = FALSE
);
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: clawmanager-mysql-pv
labels:
app: clawmanager
managed-by: clawmanager
clawmanager.io/storage-profile: single-node
clawmanager.io/storage-node: "true"
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: clawmanager.io/storage-node
operator: In
values:
- "true"
hostPath:
path: /data/clawmanager/system/mysql
type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
namespace: clawmanager-system
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: manual
volumeName: clawmanager-mysql-pv
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: clawmanager-minio-pv
labels:
app: clawmanager
managed-by: clawmanager
clawmanager.io/storage-profile: single-node
clawmanager.io/storage-node: "true"
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: clawmanager.io/storage-node
operator: In
values:
- "true"
hostPath:
path: /data/clawmanager/system/minio
type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio-data
namespace: clawmanager-system
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: manual
volumeName: clawmanager-minio-pv
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: clawmanager-redis-pv
labels:
app: clawmanager
managed-by: clawmanager
clawmanager.io/storage-profile: single-node
clawmanager.io/storage-node: "true"
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: clawmanager.io/storage-node
operator: In
values:
- "true"
hostPath:
path: /data/clawmanager/system/redis
type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data
namespace: clawmanager-system
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: manual
volumeName: clawmanager-redis-pv
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: clawmanager-workspaces-pv
labels:
app: clawmanager
managed-by: clawmanager
clawmanager.io/storage-profile: single-node
clawmanager.io/storage-node: "true"
spec:
capacity:
storage: 50Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: clawmanager.io/storage-node
operator: In
values:
- "true"
hostPath:
path: /data/clawmanager/system/workspaces
type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: clawmanager-workspaces
namespace: clawmanager-system
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Gi
storageClassName: manual
volumeName: clawmanager-workspaces-pv
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: clawmanager-system
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.4.8
imagePullPolicy: IfNotPresent
args:
- "--innodb-use-native-aio=0"
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: mysql-root-password
- name: MYSQL_DATABASE
value: clawmanager
- name: MYSQL_USER
value: clawmanager
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: mysql-password
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: mysql-init
mountPath: /docker-entrypoint-initdb.d
readinessProbe:
exec:
command: ["sh", "-c", "mysqladmin ping -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD"]
initialDelaySeconds: 20
periodSeconds: 10
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data
- name: mysql-init
configMap:
name: clawmanager-mysql-init
---
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: clawmanager-system
spec:
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio
namespace: clawmanager-system
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio:latest
imagePullPolicy: IfNotPresent
args:
- server
- /data
- --console-address
- ":9001"
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: minio-root-user
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: minio-root-password
ports:
- name: api
containerPort: 9000
- name: console
containerPort: 9001
volumeMounts:
- name: minio-data
mountPath: /data
readinessProbe:
tcpSocket:
port: api
initialDelaySeconds: 10
periodSeconds: 10
volumes:
- name: minio-data
persistentVolumeClaim:
claimName: minio-data
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: clawmanager-system
spec:
selector:
app: minio
ports:
- name: api
port: 9000
targetPort: api
- name: console
port: 9001
targetPort: console
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: clawmanager-team-redis
namespace: clawmanager-system
spec:
replicas: 1
selector:
matchLabels:
app: clawmanager-team-redis
template:
metadata:
labels:
app: clawmanager-team-redis
spec:
containers:
- name: redis
image: redis:7-alpine
imagePullPolicy: IfNotPresent
args:
- redis-server
- --appendonly
- "yes"
ports:
- name: redis
containerPort: 6379
readinessProbe:
tcpSocket:
port: redis
initialDelaySeconds: 5
periodSeconds: 10
volumeMounts:
- name: redis-data
mountPath: /data
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-data
---
apiVersion: v1
kind: Service
metadata:
name: clawmanager-redis
namespace: clawmanager-system
spec:
selector:
app: clawmanager-team-redis
ports:
- name: redis
port: 6379
targetPort: redis
---
apiVersion: v1
kind: Service
metadata:
name: clawmanager-team-redis
namespace: clawmanager-system
spec:
selector:
app: clawmanager-team-redis
ports:
- name: redis
port: 6379
targetPort: redis
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: clawmanager-app
namespace: clawmanager-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: clawmanager-runtime-manager
rules:
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- apps
resources:
- deployments
- deployments/scale
verbs:
- get
- list
- watch
- create
- update
- patch
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: clawmanager-runtime-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: clawmanager-runtime-manager
subjects:
- kind: ServiceAccount
name: clawmanager-app
namespace: clawmanager-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: clawmanager-app-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: clawmanager-app
namespace: clawmanager-system
---
# Explicit lease permissions for control-plane leader election. The
# cluster-admin binding above already covers this; this Role documents the
# requirement and keeps leader election working if RBAC is tightened later.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: clawmanager-app-leaderelection
namespace: clawmanager-system
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "list", "watch", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: clawmanager-app-leaderelection
namespace: clawmanager-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: clawmanager-app-leaderelection
subjects:
- kind: ServiceAccount
name: clawmanager-app
namespace: clawmanager-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: skill-scanner
namespace: clawmanager-system
spec:
replicas: 1
selector:
matchLabels:
app: skill-scanner
template:
metadata:
labels:
app: skill-scanner
spec:
containers:
- name: skill-scanner
image: ghcr.io/yuan-lab-llm/skill-scanner:latest
imagePullPolicy: IfNotPresent
command:
- /opt/skill-scanner-venv/bin/skill-scanner-api
- --host
- 0.0.0.0
- --port
- "8000"
env:
- name: SKILL_SCANNER_LLM_API_KEY
value: ""
- name: SKILL_SCANNER_LLM_MODEL
value: ""
- name: SKILL_SCANNER_LLM_BASE_URL
value: ""
- name: SKILL_SCANNER_META_LLM_API_KEY
value: ""
- name: SKILL_SCANNER_META_LLM_MODEL
value: ""
- name: SKILL_SCANNER_META_LLM_BASE_URL
value: ""
ports:
- name: http
containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: skill-scanner
namespace: clawmanager-system
spec:
selector:
app: skill-scanner
ports:
- name: http
port: 8000
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: clawmanager-app
namespace: clawmanager-system
spec:
replicas: 1
selector:
matchLabels:
app: clawmanager-app
template:
metadata:
labels:
app: clawmanager-app
spec:
serviceAccountName: clawmanager-app
containers:
- name: clawmanager-app
image: ghcr.io/yuan-lab-llm/clawmanager:latest
imagePullPolicy: IfNotPresent
ports:
- name: https
containerPort: 8443
- name: proxy
containerPort: 9001
env:
- name: SERVER_ADDRESS
value: ":9001"
- name: SERVER_MODE
value: "release"
- name: DB_HOST
value: "mysql"
- name: DB_PORT
value: "3306"
- name: DB_USER
value: "clawmanager"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: mysql-password
- name: DB_NAME
value: "clawmanager"
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: jwt-secret
- name: OBJECT_STORAGE_ENDPOINT
value: "minio.clawmanager-system.svc.cluster.local:9000"
- name: OBJECT_STORAGE_REGION
value: ""
- name: OBJECT_STORAGE_ACCESS_KEY
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: minio-access-key
- name: OBJECT_STORAGE_SECRET_KEY
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: minio-secret-key
- name: OBJECT_STORAGE_BUCKET
value: "clawmanager-skills"
- name: OBJECT_STORAGE_USE_SSL
value: "false"
- name: OBJECT_STORAGE_BASE_PATH
value: "skills"
- name: OBJECT_STORAGE_FORCE_PATH_STYLE
value: "true"
- name: K8S_MODE
value: "incluster"
- name: K8S_NAMESPACE
value: "clawmanager"
- name: K8S_STORAGE_CLASS
value: "manual"
- name: CLAWMANAGER_STORAGE_PROFILE
value: "single-node"
- name: K8S_HOSTPATH_FALLBACK_ENABLED
value: "true"
- name: K8S_PVC_BIND_TIMEOUT
value: "2m"
- name: K8S_CONTROL_PLANE_STORAGE_CLASS
value: "manual"
- name: K8S_INSTANCE_STORAGE_CLASS
value: "manual"
- name: K8S_WORKSPACE_STORAGE_CLASS
value: "manual"
- name: K8S_WORKSPACE_ACCESS_MODE
value: "ReadWriteMany"
- name: K8S_PV_HOST_PATH_PREFIX
value: "/data/clawreef"
- name: CLAWMANAGER_WORKSPACE_ARCHIVE_MAX_MIB
value: "500"
- name: PLATFORM_REDIS_URL
value: "redis://clawmanager-redis.clawmanager-system.svc.cluster.local:6379/0"
- name: TEAM_REDIS_URL
value: "redis://clawmanager-redis.clawmanager-system.svc.cluster.local:6379/0"
- name: CLAWMANAGER_DESKTOP_DIRECT_PROXY
value: "true"
# Leader election for control-plane singleton background loops.
# Required before scaling replicas > 1 so SyncService / Team event
# consumers / stale-task monitor run on exactly one replica.
- name: CLAWMANAGER_LEADER_ELECTION
value: "true"
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CLAWMANAGER_TEAM_REDIS_URL
value: "redis://clawmanager-redis.clawmanager-system.svc.cluster.local:6379/0"
- name: CLAWMANAGER_TEAM_MANAGER_BASE_URL
value: "http://clawmanager-gateway.clawmanager-system.svc.cluster.local:9001"
- name: RUNTIME_NAMESPACE
value: "clawmanager-system"
- name: RUNTIME_WORKSPACE_ROOT
value: "/workspaces"
- name: RUNTIME_WORKSPACE_PVC_CLAIM
value: "clawmanager-workspaces"
- name: RUNTIME_MAX_GATEWAYS_PER_POD
value: "100"
- name: RUNTIME_GATEWAY_PORT_START
value: "20000"
- name: RUNTIME_GATEWAY_PORT_END
value: "20299"
- name: RUNTIME_SCHEDULER_ENABLED
value: "true"
- name: RUNTIME_HEARTBEAT_TIMEOUT
value: "10s"
- name: RUNTIME_AGENT_CONTROL_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-control-token
- name: RUNTIME_AGENT_REPORT_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-report-token
- name: OPENCLAW_GATEWAY_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: openclaw-gateway-token
- name: SKILL_SCANNER_ENABLED
value: "true"
- name: SKILL_SCANNER_BASE_URL
value: "http://skill-scanner.clawmanager-system.svc.cluster.local:8000"
- name: SKILL_SCANNER_TIMEOUT_SECONDS
value: "120"
- name: SKILL_SCANNER_NAMESPACE
value: "clawmanager-system"
- name: SKILL_SCANNER_DEPLOYMENT
value: "skill-scanner"
volumeMounts:
- name: tls-cert
mountPath: /var/run/clawreef-tls
readOnly: true
- name: workspaces
mountPath: /workspaces
readinessProbe:
httpGet:
scheme: HTTPS
path: /healthz
port: https
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
httpGet:
scheme: HTTPS
path: /healthz
port: https
initialDelaySeconds: 30
periodSeconds: 20
volumes:
- name: tls-cert
secret:
secretName: clawmanager-tls
optional: true
- name: workspaces
persistentVolumeClaim:
claimName: clawmanager-workspaces
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: openclaw-runtime
namespace: clawmanager-system
labels:
app: openclaw-runtime
clawmanager.io/runtime-type: openclaw
spec:
replicas: 1
selector:
matchLabels:
app: openclaw-runtime
clawmanager.io/runtime-type: openclaw
template:
metadata:
labels:
app: openclaw-runtime
clawmanager.io/runtime-type: openclaw
spec:
containers:
- name: runtime
image: ghcr.io/yuan-lab-llm/agentsruntime/openclaw-lite:latest
imagePullPolicy: Always
env:
- name: CLAWMANAGER_RUNTIME_TYPE
value: openclaw
- name: CLAWMANAGER_BACKEND_URL
value: "http://clawmanager-gateway.clawmanager-system.svc.cluster.local:9001"
- name: CLAWMANAGER_RUNTIME_DEPLOYMENT_NAME
value: openclaw-runtime
- name: CLAWMANAGER_RUNTIME_IMAGE_REF
value: ghcr.io/yuan-lab-llm/agentsruntime/openclaw-lite:latest
- name: RUNTIME_WORKSPACE_ROOT
value: /workspaces
- name: RUNTIME_GATEWAY_PORT_START
value: "20000"
- name: RUNTIME_GATEWAY_PORT_END
value: "20299"
- name: RUNTIME_AGENT_LISTEN_ADDR
value: "0.0.0.0:19090"
- name: RUNTIME_AGENT_PUBLIC_PORT
value: "19090"
- name: RUNTIME_GATEWAY_COMMAND
value: "/usr/local/bin/openclaw gateway run --allow-unconfigured --auth token --bind lan --force"
- name: OPENCLAW_GATEWAY_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: openclaw-gateway-token
- name: RUNTIME_AGENT_CONTROL_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-control-token
- name: RUNTIME_AGENT_REPORT_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-report-token
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
ports:
- name: agent
containerPort: 19090
volumeMounts:
- name: workspaces
mountPath: /workspaces
volumes:
- name: workspaces
persistentVolumeClaim:
claimName: clawmanager-workspaces
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hermes-runtime
namespace: clawmanager-system
labels:
app: hermes-runtime
clawmanager.io/runtime-type: hermes
spec:
replicas: 1
selector:
matchLabels:
app: hermes-runtime
clawmanager.io/runtime-type: hermes
template:
metadata:
labels:
app: hermes-runtime
clawmanager.io/runtime-type: hermes
spec:
containers:
- name: runtime
image: ghcr.io/yuan-lab-llm/agentsruntime/hermes-lite:latest
imagePullPolicy: IfNotPresent
env:
- name: CLAWMANAGER_RUNTIME_TYPE
value: hermes
- name: CLAWMANAGER_BACKEND_URL
value: "http://clawmanager-gateway.clawmanager-system.svc.cluster.local:9001"
- name: CLAWMANAGER_RUNTIME_DEPLOYMENT_NAME
value: hermes-runtime
- name: CLAWMANAGER_RUNTIME_IMAGE_REF
value: ghcr.io/yuan-lab-llm/agentsruntime/hermes-lite:latest
- name: CLAWMANAGER_AGENT_PORT
value: "19090"
- name: CLAWMANAGER_GATEWAY_PORT_START
value: "20000"
- name: CLAWMANAGER_GATEWAY_PORT_END
value: "20299"
- name: HERMES_TUI_DIR
value: /usr/local/lib/hermes-agent/ui-tui
- name: CLAWMANAGER_AGENT_CONTROL_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-control-token
- name: CLAWMANAGER_AGENT_REPORT_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-report-token
- name: RUNTIME_WORKSPACE_ROOT
value: /workspaces
- name: RUNTIME_AGENT_LISTEN_ADDR
value: "0.0.0.0:19090"
- name: RUNTIME_AGENT_PUBLIC_PORT
value: "19090"
- name: RUNTIME_GATEWAY_PORT_START
value: "20000"
- name: RUNTIME_GATEWAY_PORT_END
value: "20299"
- name: RUNTIME_AGENT_CONTROL_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-control-token
- name: RUNTIME_AGENT_REPORT_TOKEN
valueFrom:
secretKeyRef:
name: clawmanager-secrets
key: runtime-agent-report-token
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
ports:
- name: agent
containerPort: 19090
volumeMounts:
- name: workspaces
mountPath: /workspaces
volumes:
- name: workspaces
persistentVolumeClaim:
claimName: clawmanager-workspaces
---
apiVersion: v1
kind: Service
metadata:
name: clawmanager-frontend
namespace: clawmanager-system
spec:
type: NodePort
selector:
app: clawmanager-app
ports:
- name: https
port: 443
targetPort: https
nodePort: 30443
---
apiVersion: v1
kind: Service
metadata:
name: clawmanager-gateway
namespace: clawmanager-system
spec:
type: ClusterIP
selector:
app: clawmanager-app
ports:
- name: api
port: 9001
targetPort: 9001
---
apiVersion: v1
kind: Service
metadata:
name: clawmanager-egress-proxy
namespace: clawmanager-system
spec:
type: ClusterIP
selector:
app: clawmanager-app
ports:
- name: proxy
port: 3128
targetPort: 9001